0

Cào dữ liệu Website cực đơn giản với Puppeteer: Ví dụ thực tế từ Phongtro123

Chào mọi người, chắc hẳn khi học Web Scraping (cào dữ liệu), cái tên Puppeteer không còn quá xa lạ. Đây là một thư viện NodeJS mạnh mẽ giúp điều khiên trình duyệt Chrome/Chromium thông qua mã code.

Hôm nay, mình sẽ chia sẻ một đoạn scrip ngắn ngọn để lấy danh mục (Categories) từ website phongtro123.com. Đây là một ví dụ điển hình cho việc xử lý dữ liệu động.

1. Chuẩn bị đồ nghề

Trước khi bắt dầu, hãy đảm bảo bạn đã cài đặt NodeJS. Sau đó, khởi tạo project và cài đặt Puppeteer:

npm init -y
npm i puppeteer

2. Giải mã đoạn Code

Dưới đây là cấu trúc logic để chúng ta "lẻn" vào một website và lấy thông tin mình cần:

Khởi tạo truy cập

Chúng ta sẽ định nghĩa hàm scrapeCategory. Điểm quan trọng ở đây là sử dụng page.goto(url, { waitUntil: 'networkidle2' }). Tùy chọn này đảm bảo trang web đã tải xong các request từ network trước khi chúng ta thực hiện hành động tiếp theo.

Sử dụng phương thức $$eval

Đây là "vũ khí" chính. $$eval cho phép chúng ta chạy lệnh document.querySelectorAll ngay bên trong môi trường trình duyệt và trả về kết quả cho Node.js.

Đoạn Code hoàn chỉnh:

const puppeteer = require('puppeteer');

/**
 * Hàm cào danh mục từ trang chủ
 */
const scrapeCategory = (browser, url) => new Promise(async (resolve, reject) => {
    try {
        let page = await browser.newPage();
        console.log('>> Mở tab mới ...');
        
        await page.goto(url, { waitUntil: 'networkidle2' });
        console.log('>> Truy cập vào ' + url);

        // Chờ selector cụ thể xuất hiện để đảm bảo dữ liệu đã render
        await page.waitForSelector('#webpage');
        console.log('>> Website đã load xong ...');

        const dataCategory = await page.$$eval(
            '.pt123__nav > ul > li', // Selector trỏ đến các menu item
            els => els.map(el => {
                const anchor = el.querySelector('a');
                return anchor ? {
                    category: anchor.innerText.trim(),
                    link: anchor.href
                } : null;
            }).filter(Boolean) // Loại bỏ các giá trị null
        );

        await page.close();
        console.log('>> Tab đã đóng.');
        resolve(dataCategory);

    } catch (error) {
        console.log('Lỗi ở scrape category: ' + error);
        reject(error);
    }
});

// Chạy hàm chính (Main)
(async () => {
    const browser = await puppeteer.launch({ headless: true }); // Chạy chế độ ẩn danh
    const url = 'https://phongtro123.com';
    
    console.log('--- Bắt đầu cào dữ liệu ---');
    const data = await scrapeCategory(browser, url);
    
    console.table(data); // Hiển thị dạng bảng cho đẹp
    
    await browser.close();
    console.log('--- Hoàn tất ---');
})();

3. Một vài lưu ý nhỏ (Tips)

  • WaitSelector: Luôn dùng waitForSelector để chắc chắn phần tử bạn muốn lấy đã tồn tại, tránh lỗi null khi website load chậm.
  • Headless Mode: Khi đang code/debug, bạn nên để { headless: false } để thấy trình duyệt tự động nhảy như thế nào. Khi chạy thực tế trên server thì mới để true.
  • Tôn trọng Robot.txt: Đừng cào dữ liệu quá nhanh hoặc quá nhiều trong thời gian ngắn để tránh làm ảnh hưởng đến hiệu năng của website người khác nhé!

Tạm kết

Chỉ với vài dòng code, Puppeteer đã giúp chúng ta lấy được toàn bộ danh mục của một trang web. Hy vọng ví dụ nhỏ này giúp các bạn hiểu rõ hơn về cách thức hoạt động của công cụ này.

Nếu thấy bài viết hữu ích, đừng quên tặng mình một Upvote để có thêm động lực chia sẻ nhé! 😉


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí