Thu thập dữ liệu web tự động với n8n và Puppeteer

Viewed 4

Chia sẻ của Little Excel

Bạn đang tìm cách tự động thu thập dữ liệu từ các trang web, kể cả những trang "khó tính" nhất? HTTP request thông thường đôi khi không đủ sức, đặc biệt khi website sử dụng nhiều JavaScript để tải nội dung hoặc có các biện pháp chống cào dữ liệu. Đây là lúc Puppeteer, một thư viện Node.js mạnh mẽ, kết hợp với n8n, nền tảng tự động hóa quy trình làm việc, trở thành giải pháp cứu cánh. Bài viết này sẽ hướng dẫn bạn chi tiết cách sử dụng Puppeteer trong n8n để thu thập dữ liệu web n8n puppeteer một cách hiệu quả.

Puppeteer là gì và tại sao nó vượt trội hơn HTTP Request thông thường?

Puppeteer là một thư viện Node do đội ngũ Chrome của Google phát triển. Nó cung cấp một API cấp cao để điều khiển Chrome hoặc Chromium qua Giao thức DevTools. Hiểu đơn giản, Puppeteer cho phép bạn "lập trình" một trình duyệt tự động thực hiện các tác vụ như:

  • Mở trang web.
  • Chờ nội dung tải xong (bao gồm cả JavaScript).
  • Tương tác với các yếu tố trên trang (click, điền form).
  • Cuộn trang.
  • Chụp ảnh màn hình hoặc tạo file PDF từ trang web.
  • Trích xuất dữ liệu từ cấu trúc HTML của trang.

Vậy, tại sao HTTP request thông thường lại không đủ?

Khi bạn gửi một HTTP request (ví dụ, bằng node HTTP Request trong n8n), bạn chỉ nhận được phản hồi ban đầu từ server. Nhiều trang web hiện đại tải nội dung động bằng JavaScript sau khi trang đã được nạp ban đầu. HTTP request sẽ không "chờ" JavaScript chạy xong, do đó bạn có thể bỏ lỡ phần lớn dữ liệu quan trọng.

Hơn nữa, một số trang web có cơ chế phát hiện và chặn các request không đến từ trình duyệt thực sự. Puppeteer giải quyết những vấn đề này bằng cách:

  1. Mô phỏng trình duyệt hoàn chỉnh: Nó chạy một phiên bản trình duyệt thực sự (headless hoặc full), bao gồm cả việc thực thi JavaScript.
  2. Vượt qua các rào cản cơ bản: Nó có thể "giả vờ" là một người dùng thực sự, giúp truy cập vào các trang web có biện pháp bảo vệ đơn giản.

Rất may mắn, cộng đồng n8n đã phát triển một node tích hợp Puppeteer, giúp việc thu thập dữ liệu web n8n puppeteer trở nên dễ dàng hơn bao giờ hết mà không cần phải viết quá nhiều code phức tạp từ đầu.

Cài đặt Puppeteer Node trong n8n

Để bắt đầu, bạn cần cài đặt community node cho Puppeteer vào n8n.

  1. Trong giao diện n8n, đi tới Settings > Community Nodes.
  2. Nhấn vào nút Install.
  3. Trong ô tìm kiếm, nhập tên package: n8n-nodes-puppeteer.
  4. Nhấn Install và chờ quá trình cài đặt hoàn tất.

Sau khi cài đặt thành công, bạn sẽ tìm thấy node "Puppeteer" khi tìm kiếm trong bảng Node Palette.

Khám phá các Action cơ bản của Puppeteer Node trong n8n

Node Puppeteer trong n8n cung cấp bốn action chính:

  1. Get Page Content: Lấy toàn bộ nội dung HTML của trang.
  2. Get PDF: Chuyển đổi trang web thành file PDF.
  3. Get Screenshot: Chụp ảnh màn hình của trang web.
  4. Run Custom Script: Cho phép bạn chạy mã Puppeteer tùy chỉnh để thực hiện các tác vụ phức tạp hơn.

Hãy cùng đi qua từng action với ví dụ cụ thể.

1. Get Page Content: Lấy nội dung trang Web

Action này sẽ trả về nội dung HTML của trang web bạn chỉ định. Điểm khác biệt lớn so với HTTP request là Puppeteer sẽ chờ trang tải xong (bao gồm cả JavaScript) trước khi lấy nội dung.

Ví dụ: Giả sử chúng ta muốn lấy dữ liệu từ trang bảng giá chứng khoán (ví dụ: một trang của SSI).

  • Thử với HTTP Request Node: Nếu bạn dùng node HTTP Request để GET dữ liệu từ URL này, rất có thể bạn sẽ nhận được thông báo lỗi, bị chặn, hoặc yêu cầu xác thực, vì trang web phát hiện bạn không phải là trình duyệt. Trong nhiều trường hợp, bạn có thể nhận được thông báo "Enable JavaScript" hoặc bị block hoàn toàn.
  • Thử với Puppeteer - Get Page Content:
    • Thêm node Puppeteer vào workflow.
    • Chọn action Get Page Content.
    • Nhập URL của trang bảng giá vào trường URL.
    • Chạy node.
      Bạn sẽ thấy Puppeteer có thể truy cập và lấy về nội dung HTML của trang. Mặc dù nội dung có thể phức tạp, nhưng nó chứng tỏ Puppeteer đã "vào" được trang.

2. Get Screenshot: Chụp ảnh trang Web

Đây là một cách tuyệt vời để kiểm tra trực quan xem Puppeteer có thực sự truy cập và hiển thị trang web đúng như mong đợi hay không.

  • Trong node Puppeteer, chọn action Get Screenshot.
  • Nhập URL.
  • Bạn có thể chọn tùy chọn Full Page để chụp toàn bộ trang, kể cả phần không nhìn thấy trên màn hình.
  • Chạy node.
    Kết quả sẽ là một file ảnh (thường là PNG) của trang web tại thời điểm Puppeteer truy cập. Điều này rất hữu ích để debug và xác nhận. Ví dụ, nếu trang hiển thị lúc 20:54:26 và ảnh chụp lúc 20:54:50, bạn biết nó đã vào và chụp ngay lúc đó.

3. Get PDF: Lưu trang web dưới dạng PDF

Tương tự như Get Screenshot, action này cho phép bạn lưu toàn bộ nội dung hiển thị của trang web dưới dạng một file PDF.

  • Chọn action Get PDF.
  • Nhập URL.
  • Chạy node.
    Bạn sẽ nhận được một file PDF chứa nội dung trang.

Tùy chỉnh nâng cao cho Puppeteer Node để thu thập dữ liệu web n8n Puppeteer hiệu quả

Phần "Add Option" trong node Puppeteer mở ra rất nhiều khả năng tùy chỉnh mạnh mẽ, giúp bạn đối phó với các trang web phức tạp và các cơ chế chống bot.

Timeout: Thời gian chờ tải trang

  • Timeout: Xác định thời gian tối đa (tính bằng mili giây) mà Puppeteer sẽ chờ một trang hoặc một hành động hoàn tất.
    • Nếu đặt quá thấp (ví dụ 30ms tương đương 0.03 giây), trang có thể chưa kịp tải xong và Puppeteer sẽ báo lỗi timeout.
    • Nếu đặt cao hơn (ví dụ 10000ms tương đương 10 giây), Puppeteer sẽ có đủ thời gian chờ trang tải xong trước khi thực hiện hành động tiếp theo.

Wait Until: Chờ đến khi sự kiện nhất định xảy ra

Thay vì chờ một khoảng thời gian cố định, Wait Until cho phép Puppeteer chờ đến khi một sự kiện cụ thể của trang xảy ra. Có 4 tùy chọn chính:

  • load: Chờ cho đến khi sự kiện load của trang được kích hoạt. Điều này có nghĩa là toàn bộ nội dung HTML, CSS, và JavaScript đã được tải và thực thi.
  • domcontentloaded: Chờ cho đến khi sự kiện DOMContentLoaded được kích hoạt. DOM (Document Object Model) đã sẵn sàng, nhưng các tài nguyên như hình ảnh hoặc stylesheet có thể vẫn đang tải. Thường nhanh hơn load nhưng có thể chưa có đủ nội dung nếu trang phụ thuộc nhiều vào JS load sau.
  • networkidle0: Chờ cho đến khi không có kết nối mạng nào mới được thực hiện trong ít nhất 500 mili giây. Hữu ích cho các trang Single Page Application (SPA) tải dữ liệu liên tục.
  • networkidle2: Chờ cho đến khi không có nhiều hơn 2 kết nối mạng đang hoạt động trong ít nhất 500 mili giây. Đây là một lựa chọn phổ biến, cân bằng giữa việc chờ đủ lâu và không chờ quá lâu.

Để kiểm tra các network connection này, bạn có thể mở Developer Tools (F12) trong trình duyệt, chọn tab "Network". Khi trang tải, bạn sẽ thấy các request được liệt kê. networkidle0networkidle2 theo dõi các request này để quyết định khi nào trang "ổn định".

Emulate Device: Giả lập thiết bị

Một số trang web hiển thị nội dung khác nhau hoặc có các biện pháp bảo mật khác nhau tùy thuộc vào thiết bị truy cập (desktop, mobile, tablet). Emulate Device cho phép Puppeteer giả lập mình là một thiết bị cụ thể.

Ví dụ thực tế với Sky Scanner:
Trang web đặt vé máy bay Sky Scanner có thể rất khó cào dữ liệu. Nếu bạn truy cập bằng Puppeteer mặc định, có khả năng cao bạn sẽ bị nhận diện là bot và gặp trang xác minh (ví dụ: yêu cầu giữ một nút để chứng minh bạn là người).

Tuy nhiên, nếu bạn thử:

  1. Trong node Puppeteer, mục "Add Option", chọn Emulate Device.
  2. Chọn một thiết bị, ví dụ: iPad Pro 11 landscape.
  3. Chạy lại node.
    Rất có thể lần này Puppeteer sẽ vượt qua được bước kiểm tra bot ban đầu và truy cập vào trang kết quả tìm kiếm (dù sau đó có thể gặp vấn đề về cookie, nhưng đó là một bước tiến). Điều này cho thấy việc giả lập thiết bị có thể là một yếu tố quan trọng để thu thập dữ liệu web n8n puppeteer thành công.

Các tùy chọn quan trọng khác:

  • Page Size (Max Pages): Số lượng tab/trang tối đa mà Puppeteer có thể mở đồng thời.
  • Stealth Mode: Kích hoạt một số kỹ thuật để giúp Puppeteer khó bị các hệ thống chống bot phát hiện hơn. Tuy nhiên, các hệ thống hiện đại vẫn có thể phát hiện được.
  • Proxy Server: Nếu bạn thu thập dữ liệu với tần suất cao từ cùng một IP, trang web có thể chặn IP của bạn. Sử dụng proxy server giúp bạn thay đổi địa chỉ IP, tránh bị chặn.
  • Headless Mode: Mặc định, Puppeteer chạy ở chế độ "headless" (không có giao diện người dùng đồ họa). Điều này tiết kiệm tài nguyên. Bạn có thể tắt headless (set là false) để xem trình duyệt thực sự chạy, hữu ích cho việc debug.
  • Extra Headers: Cho phép bạn thêm hoặc sửa đổi các HTTP header gửi đi, ví dụ như User-Agent, để giả mạo một trình duyệt cụ thể.

Sức mạnh của "Run Custom Script" với Puppeteer trong n8n

Đây là action linh hoạt và mạnh mẽ nhất, cho phép bạn viết mã JavaScript sử dụng API của Puppeteer để thực hiện các tác vụ thu thập dữ liệu phức tạp.

Ví dụ: Thu thập dữ liệu từ Sky Scanner bằng Custom Script

Giả sử bạn đã có một đoạn code Puppeteer (viết bằng Node.js thuần) để cào dữ liệu giá vé từ Sky Scanner. Đoạn code này có thể bao gồm các bước:

  1. Mở trình duyệt (puppeteer.launch()).
  2. Mở một trang mới (browser.newPage()).
  3. Điều hướng đến URL tìm kiếm (page.goto(url)).
  4. Chờ các yếu tố cụ thể xuất hiện (page.waitForSelector()).
  5. Tương tác với trang (ví dụ: page.click() để chấp nhận cookie, page.evaluate() để cuộn trang).
  6. Trích xuất dữ liệu từ các thẻ HTML (ví dụ: page.$$eval() để lấy thông tin chuyến bay, giá vé).
  7. Đóng trình duyệt (browser.close()).

Bây giờ, bạn có thể mang đoạn code này vào n8n:

  1. Trong node Puppeteer, chọn action Run Custom Script.
  2. Dán đoạn code JavaScript của bạn vào trường Script.
  3. Lưu ý quan trọng khi chuyển code vào n8n:
    • Bạn không cần puppeteer.launch() hay browser.newPage() vì n8n node đã xử lý việc này. Node cung cấp sẵn các biến như $ (đại diện cho đối tượng Puppeteer), $browser (đối tượng trình duyệt) và $page (đối tượng trang hiện tại). Bạn sẽ sử dụng $page thay vì page mà bạn tự tạo.
    • Bạn không cần browser.close().
    • Đảm bảo code của bạn là async và sử dụng await đúng cách.
  4. Trả về dữ liệu cho n8n: Để n8n có thể sử dụng dữ liệu bạn thu thập, bạn cần return một mảng (array) các đối tượng (object). Mỗi đối tượng đại diện cho một item dữ liệu. Cấu trúc phổ biến là:
    // Ví dụ: allData là một mảng chứa các object dữ liệu chuyến bay
    return allData.map(item => ({ json: { data: item } }));
    // Hoặc đơn giản hơn nếu chỉ có một khối dữ liệu lớn:
    // return [{ json: { myKey: collectedDataObject } }];
    
    Trong transcript, người hướng dẫn sử dụng cấu trúc return [{ json: { data: onData } }]; với onData là biến chứa dữ liệu đã thu thập.

Chạy node với custom script này, bạn có thể tự động hóa việc lấy dữ liệu giá vé máy bay phức tạp. Tuy nhiên, hãy nhớ rằng Puppeteer không phải là "viên đạn bạc". Các trang web có hệ thống chống bot tinh vi vẫn có thể phát hiện và chặn bạn, đòi hỏi các kỹ thuật nâng cao hơn.

Hướng dẫn viết Custom Script Puppeteer cơ bản trong n8n

Nếu bạn mới làm quen, việc viết custom script có thể hơi đáng sợ. Dưới đây là các bước cơ bản và một ví dụ:

Các thành phần chính trong một Custom Script:

  1. Điều hướng đến trang:
    await $page.goto('https://your-target-website.com');
    
  2. Chờ đợi (nếu cần):
    await $page.waitForSelector('.some-element-class'); // Chờ một phần tử cụ thể xuất hiện
    await $page.waitForTimeout(5000); // Chờ 5 giây (dùng cẩn thận, ưu tiên waitForSelector hoặc waitForNavigation)
    
  3. Thực thi JavaScript trong ngữ cảnh trang (page.evaluate):
    Đây là hàm cực kỳ quan trọng, cho phép bạn chạy code JavaScript như thể nó được chạy trực tiếp trong Console của trình duyệt.
    const data = await $page.evaluate(() => {
        // Code này chạy trong trình duyệt
        const titleElement = document.querySelector('h1');
        const items = Array.from(document.querySelectorAll('.product-item')).map(item => {
            return {
                name: item.querySelector('.product-name').innerText,
                price: item.querySelector('.product-price').innerText
            };
        });
        return {
            pageTitle: titleElement ? titleElement.innerText : null,
            products: items
        };
    });
    
  4. Trả về dữ liệu cho n8n:
    return [{ json: data }]; // data là biến chứa kết quả từ page.evaluate
    

Ví dụ: Thu thập dữ liệu từ bảng giá chứng khoán (SSI)

Giả sử chúng ta muốn lấy dữ liệu từ bảng giá chứng khoán của SSI.

Cách 1: Đọc thẻ HTML

  • Bước 1: Phân tích trang web:
    Mở trang web trong Chrome. Nhấp chuột phải vào một mã cổ phiếu hoặc giá, chọn "Inspect". Tìm các thẻ HTML chứa thông tin bạn muốn (ví dụ: mã CK, giá khớp lệnh, khối lượng). Chú ý đến class hoặc id của các thẻ này.
    Mẹo: Chrome DevTools có tính năng "Ask AI" (nếu được kích hoạt) có thể giúp bạn tạo selector hoặc đoạn code JavaScript để lấy dữ liệu từ một phần tử đã chọn.

  • Bước 2: Viết Script trong n8n:

    // Trong node Puppeteer, action "Run Custom Script"
    await $page.goto('URL_CUA_TRANG_BANG_GIA_SSI');
    
    // Chờ bảng dữ liệu tải (thay '.selector-bang-du-lieu' bằng selector thực tế)
    try {
        await $page.waitForSelector('.ag-center-cols-container', { timeout: 15000 }); // Ví dụ selector cho bảng ag-Grid
    } catch (e) {
        console.error("Bảng dữ liệu không tải kịp thời gian.");
        return [{ json: { error: "Timeout waiting for data table" } }];
    }
    
    const stockData = await $page.evaluate(() => {
        const rows = Array.from(document.querySelectorAll('.ag-row')); // Lấy tất cả các hàng trong bảng (điều chỉnh selector nếu cần)
        const data = rows.map(row => {
            // Giả sử cột mã CK là cột đầu tiên, giá khớp lệnh là cột thứ 4 (ví dụ)
            // Bạn cần inspect để tìm đúng selector cho từng ô (cell)
            const stockSymbolElement = row.querySelector('.ag-cell[col-id="s"]'); // Ví dụ cho mã CK
            const priceElement = row.querySelector('.ag-cell[col-id="lastPrice"]'); // Ví dụ cho giá khớp lệnh
    
            return {
                symbol: stockSymbolElement ? stockSymbolElement.innerText.trim() : null,
                price: priceElement ? priceElement.innerText.trim() : null
                // Thêm các trường khác bạn muốn lấy
            };
        }).filter(item => item.symbol); // Lọc bỏ các hàng rỗng (nếu có)
    
        return data;
    });
    
    return [{ json: { ssi_data: stockData } }];
    

    Lưu ý: Selector (.ag-center-cols-container, .ag-row, .ag-cell[col-id="s"]) chỉ là ví dụ. Bạn cần tự mình inspect trang SSI để tìm ra các selector chính xác cho dữ liệu bạn muốn. Trang web có thể thay đổi cấu trúc HTML, làm gãy script của bạn.

Cách 2: Bắt các request XHR/Fetch (nếu có)

Nhiều trang web động tải dữ liệu qua các request ngầm (XHR hoặc Fetch).

  • Bước 1: Tìm API Endpoint:
    Mở Developer Tools (F12) > tab "Network". Lọc theo "XHR" hoặc "Fetch". Tải lại trang hoặc tương tác với bảng giá. Bạn sẽ thấy các request được gửi đi. Tìm request nào trả về dữ liệu dạng JSON chứa thông tin bảng giá.
    Ví dụ, bạn có thể thấy một request đến .../something/stockRealtime?... trả về một JSON lớn.

  • Bước 2: Sử dụng URL của API đó với Puppeteer (nếu cần):
    Đôi khi, bạn có thể gọi trực tiếp URL API này bằng node HTTP Request. Tuy nhiên, API này vẫn có thể có các biện pháp bảo vệ (yêu cầu cookie, header đặc biệt). Nếu HTTP Request không thành công, bạn có thể dùng Puppeteer để truy cập URL API đó.

    // Trong node Puppeteer, action "Run Custom Script"
    const apiUrl = 'URL_API_BAN_TIM_DUOC'; 
    await $page.goto(apiUrl);
    
    // Trang API thường trả về JSON thuần, nên ta có thể lấy nội dung body
    const jsonData = await $page.evaluate(() => {
        try {
            return JSON.parse(document.body.innerText);
        } catch (e) {
            // Nếu không phải JSON thuần, trả về text để debug
            return document.body.innerText;
        }
    });
    
    return [{ json: { api_response: jsonData } }];
    

    Trong video, người hướng dẫn đã tìm thấy các URL API trả về dữ liệu JSON cho VNINDEX, VN30, HNX30. Mặc dù cố gắng gọi các URL này bằng Postman hoặc HTTP Request node bị chặn, nhưng Puppeteer (với action Get Page Content hoặc Run Custom Script để truy cập URL API) lại có thể lấy được dữ liệu JSON.

Kết luận

Kết hợp n8n và Puppeteer mở ra một thế giới mới cho việc thu thập dữ liệu web n8n puppeteer tự động. Từ việc lấy nội dung đơn giản, chụp ảnh màn hình, đến việc chạy các script Puppeteer tùy chỉnh để đối phó với các trang web phức tạp và các cơ chế chống bot, bạn đã có trong tay một công cụ mạnh mẽ.

Mặc dù Puppeteer không phải là giải pháp vạn năng cho mọi trường hợp (các trang web rất tinh vi vẫn có thể là thách thức), nó chắc chắn giải quyết được phần lớn các nhu cầu thu thập dữ liệu mà HTTP request thông thường bó tay. Hãy bắt đầu thử nghiệm với các trang web bạn quan tâm, khám phá các tùy chọn của node Puppeteer, và bạn sẽ ngạc nhiên với những gì mình có thể làm được. Chúc bạn thành công trên hành trình tự động hóa của mình!

0 Answers