Tự động hoá nhập liệu website với Puppeteer và n8n

Viewed 1

Chia sẻ bởi Little Excel

Trong thế giới số ngày nay, việc tương tác với website để nhập liệu, trích xuất thông tin hay thực hiện các tác vụ lặp đi lặp lại là một phần không thể thiếu trong nhiều quy trình công việc. Tuy nhiên, thực hiện thủ công những công việc này không chỉ tốn thời gian, công sức mà còn dễ phát sinh sai sót. Đây là lúc giải pháp tự động hóa với Puppeteer n8n tỏa sáng, giúp bạn giải phóng khỏi những thao tác nhàm chán và nâng cao hiệu suất làm việc.

Bài viết này sẽ cung cấp một hướng dẫn chi tiết, từ việc chuẩn bị môi trường, viết script Puppeteer cơ bản, đến tích hợp vào n8n và xử lý các vấn đề thường gặp, giúp bạn tự tin làm chủ công cụ mạnh mẽ này.

Tại Sao Nên Tự Động Hóa Nhập Liệu với Puppeteer và n8n?

Trước khi đi vào chi tiết kỹ thuật, hãy cùng tìm hiểu lý do tại sao sự kết hợp giữa Puppeteer và n8n lại là một lựa chọn tuyệt vời cho việc tự động hóa trình duyệt:

  • Puppeteer là gì? Puppeteer là một thư viện Node.js được phát triển bởi Google, cung cấp một API cấp cao để điều khiển trình duyệt Chrome hoặc Chromium qua giao thức DevTools. Với Puppeteer, bạn có thể tự động hóa hầu hết mọi thứ mà bạn làm thủ công trên trình duyệt: mở trang, điều hướng, nhấp chuột, điền biểu mẫu, chụp ảnh màn hình, tạo PDF, và nhiều hơn nữa.
  • n8n là gì? n8n là một nền tảng tự động hóa quy trình làm việc mã nguồn mở, mạnh mẽ và linh hoạt. Nó cho phép bạn kết nối các ứng dụng và dịch vụ khác nhau (bao gồm cả việc chạy script tùy chỉnh) để tạo ra các luồng công việc tự động mà không cần nhiều kiến thức về lập trình.
  • Sức mạnh kết hợp: Khi Puppeteer được tích hợp vào n8n (thông qua node Puppeteer), bạn có thể xây dựng các kịch bản tự động hóa trình duyệt phức tạp, kích hoạt chúng dựa trên các sự kiện khác nhau, xử lý dữ liệu thu thập được và tích hợp với hàng trăm ứng dụng khác trong hệ sinh thái n8n.
  • Thách thức cần lưu ý: Mặc dù mạnh mẽ, việc tự động hóa trình duyệt cũng gặp phải một số thách thức như xử lý CAPTCHA (một cơ chế được thiết kế để phân biệt người và máy) hay các website có nội dung tải động (dynamic content). Tuy nhiên, với kiến thức và kỹ thuật phù hợp, nhiều trường hợp vẫn có thể được giải quyết.

Trong video "Excel Talk #15: Puppeteer n8n (2)", Ngọc Thành Nguyễn đã đặt câu hỏi về cách nhập liệu tự động vào các website cơ bản. Video đã trình bày một cách chi tiết cách sử dụng Puppeteer để mô phỏng hành vi người dùng, từ việc mở trang, điền thông tin đến nhấn nút. Chúng ta sẽ cùng khám phá lại những bước này.

Bước Chuẩn Bị: Phát Triển Script Puppeteer trên Máy Tính Cá Nhân

Một lời khuyên hữu ích từ video là bạn nên phát triển và thử nghiệm script Puppeteer trên máy tính cá nhân của mình trước khi đưa vào n8n. Lý do là vì:

  • Dễ dàng gỡ lỗi (debug): Môi trường phát triển tích hợp (IDE) như WebStorm, VS Code cung cấp các công cụ gỡ lỗi mạnh mẽ, giúp bạn nhanh chóng xác định và sửa lỗi trong code.
  • Quan sát trực quan: Bạn có thể chạy Puppeteer ở chế độ không ẩn (non-headless) để trực tiếp quan sát các hành động của trình duyệt, giúp việc kiểm tra và tinh chỉnh script trở nên dễ dàng hơn.

Hãy bắt đầu với việc cài đặt Puppeteer (nếu bạn chưa có):

npm install puppeteer
# hoặc
yarn add puppeteer

Dưới đây là cấu trúc cơ bản của một script Puppeteer sử dụng async/await để thực hiện các tác vụ tự động hóa:

const puppeteer = require('puppeteer');

async function automateBrowser() {
  // Khởi tạo trình duyệt
  const browser = await puppeteer.launch({ headless: false }); // headless: false để thấy cửa sổ trình duyệt
  const page = await browser.newPage(); // Mở một tab mới

  // Các thao tác tự động hóa sẽ được viết ở đây

  // await browser.close(); // Đóng trình duyệt sau khi hoàn tất (có thể comment lại khi đang debug)
}

automateBrowser();

Khởi Tạo Trình Duyệt và Điều Hướng

  1. Khởi chạy Trình duyệt (puppeteer.launch()):

    • headless: false: Tùy chọn này cho phép bạn nhìn thấy cửa sổ trình duyệt đang chạy. Khi triển khai thực tế, bạn có thể đặt là true để chạy ngầm.
    • Trong video, tác giả cũng đề cập đến việc thiết lập defaultViewport: null để đảm bảo trang web hiển thị toàn bộ nội dung, không bị giới hạn bởi viewport mặc định.
    • Một tùy chọn hữu ích khác là args để tùy chỉnh kích thước cửa sổ, ví dụ: args: ['--window-size=1280,720'].
    const browser = await puppeteer.launch({
      headless: false,
      defaultViewport: null, // Hiển thị toàn bộ nội dung trang
      args: [`--window-size=1280,720`] // Thiết lập kích thước cửa sổ
    });
    const page = await browser.newPage();
    
  2. Điều hướng đến Trang Web (page.goto()):
    Sử dụng await page.goto('URL_CUA_BAN') để mở một trang web cụ thể. Ví dụ, chúng ta sẽ thử với Google:

    await page.goto('https://www.google.com');
    

Tương Tác Với Các Thành Phần Trang Web

Sau khi đã mở được trang web, bước tiếp theo là tương tác với các phần tử trên đó như nút bấm, ô nhập liệu.

  1. Xử lý Pop-up Cookie (Ví dụ trên Google):
    Nhiều trang web, bao gồm Google, sẽ hiển thị một pop-up yêu cầu chấp nhận cookie. Để tự động hóa, chúng ta cần tìm ra "selector" của nút chấp nhận và nhấp vào đó.

    • Lấy Selector: Nhấp chuột phải vào phần tử bạn muốn tương tác trên trình duyệt, chọn "Inspect" (Kiểm tra). Trong bảng DevTools hiện ra, tìm thẻ HTML tương ứng và xác định một thuộc tính duy nhất như id, class, hoặc một tổ hợp các thuộc tính.
    • page.waitForSelector('selector'): Chờ cho đến khi phần tử với selector được chỉ định xuất hiện trên trang. Điều này rất quan trọng vì các phần tử có thể mất một chút thời gian để tải.
    • page.click('selector'): Nhấp chuột vào phần tử.

    Ví dụ, để đóng pop-up cookie của Google (selector có thể thay đổi theo thời gian):

    // Selector này là ví dụ, bạn cần kiểm tra lại trên trang Google thực tế
    const cookieButtonSelector = '.QS5gu.sy4vM'; // Giả sử đây là class của nút "Accept all"
    
    try {
      await page.waitForSelector(cookieButtonSelector, { timeout: 5000 }); // Chờ tối đa 5 giây
      await page.click(cookieButtonSelector);
      console.log('Đã nhấp vào nút cookie.');
    } catch (error) {
      console.log('Không tìm thấy nút cookie hoặc đã tự động ẩn:', error.message);
    }
    

    Lưu ý về selector CSS: Dấu . đứng trước tên class (ví dụ: .my-class), dấu # đứng trước ID (ví dụ: #my-id). Nếu class có khoảng trắng, hãy thay thế bằng dấu chấm (ví dụ: class="btn primary" sẽ thành .btn.primary).

  2. Nhập Dữ Liệu Vào Ô Input:
    Tương tự, để nhập liệu vào một ô tìm kiếm:

    • Tìm selector của ô input.
    • Sử dụng page.type('input_selector', 'Nội dung cần nhập').

    Ví dụ, nhập "Puppeteer n8n" vào ô tìm kiếm của Google:

    const searchInputSelector = 'textarea[name="q"]'; // Selector cho ô tìm kiếm của Google
    await page.waitForSelector(searchInputSelector);
    await page.type(searchInputSelector, 'Puppeteer n8n');
    
  3. Tạo Độ Trễ "Giống Người Thật":
    Các hành động tự động thường diễn ra rất nhanh. Để làm cho quá trình tự động hóa trông "giống người" hơn hoặc để chờ các tác vụ nền hoàn thành, bạn có thể thêm độ trễ:

    • Độ trễ giữa các hành động:
      await new Promise(resolve => setTimeout(resolve, 2000)); // Chờ 2 giây
      
    • Độ trễ khi gõ phím: Tùy chọn delay trong page.type() giúp mô phỏng tốc độ gõ của con người.
      await page.type(searchInputSelector, 'Puppeteer n8n', { delay: 100 }); // Delay 100ms giữa mỗi ký tự
      
  4. Nhấp Nút Tìm Kiếm hoặc Submit:
    Sau khi nhập liệu, bạn sẽ cần nhấp vào nút tìm kiếm.

    // Selector này là ví dụ cho nút tìm kiếm của Google, có thể thay đổi
    // Thường là một thẻ input type="submit" hoặc button
    const searchButtonSelector = 'input[name="btnK"]'; // Cần kiểm tra lại selector này
    
    // Chờ nút submit có thể không cần thiết nếu nó đã hiển thị cùng lúc với ô input
    // Nhưng để chắc chắn, có thể thêm waitForSelector
    await page.waitForSelector(searchButtonSelector, { visible: true, timeout: 5000 }); 
    await page.click(searchButtonSelector);
    

Đối Phó Với CAPTCHA và Cơ Chế Chống Bot

Một thách thức lớn khi tự động hóa là các cơ chế chống bot như CAPTCHA. Video cũng đề cập rằng Google có thể chặn các truy cập tự động và yêu cầu xác thực.
Việc vượt qua CAPTCHA một cách tự động là rất khó và thường vi phạm điều khoản dịch vụ của website. Puppeteer (đặc biệt với các plugin như puppeteer-extra-plugin-stealth) có một số kỹ thuật để cố gắng làm cho trình duyệt tự động trông giống trình duyệt của người dùng hơn, nhưng không có gì đảm bảo thành công 100% với các hệ thống chống bot tinh vi. Đối với các tác vụ đơn giản, việc thêm độ trễ và mô phỏng hành vi người dùng có thể giúp ích.

Tích Hợp Script Puppeteer vào Quy Trình n8n

Sau khi script Puppeteer của bạn đã hoạt động ổn định trên máy tính cá nhân, đã đến lúc đưa nó vào n8n để tích hợp vào các quy trình làm việc lớn hơn.

n8n cung cấp một node "Puppeteer" chuyên dụng. Bạn có thể chọn action "Run Custom Script" để chạy code JavaScript Puppeteer của mình.

Di Chuyển Code Puppeteer vào n8n

Khi viết code trong Custom Script của node Puppeteer trong n8n, hãy lưu ý những điểm sau:

  • Biến có sẵn: n8n cung cấp sẵn các biến $browser$page. Bạn không cần phải viết lại puppeteer.launch() hay browser.newPage() nếu bạn chỉ muốn thực hiện các thao tác trên trang mặc định mà node mở ra.
    // Trong Custom Script của node Puppeteer n8n
    // $browser và $page đã có sẵn
    
    // Ví dụ: truy cập Google và nhập liệu
    await $page.goto('https://www.google.com');
    
    // Xử lý cookie (selector có thể cần cập nhật)
    const cookieButtonSelector = 'div[jscontroller="rPlPmd"] button[jsname="b3VHJd"]'; // Selector ví dụ
    try {
        await $page.waitForSelector(cookieButtonSelector, { timeout: 3000, visible: true });
        await $page.click(cookieButtonSelector);
    } catch (e) {
        console.log('Không tìm thấy hoặc không cần click nút cookie.');
    }
    
    await new Promise(resolve => setTimeout(resolve, 1000)); // Chờ 1 giây
    
    const searchInputSelector = 'textarea[name="q"]';
    await $page.waitForSelector(searchInputSelector);
    await $page.type(searchInputSelector, 'Puppeteer n8n in n8n', { delay: 50 });
    
    await new Promise(resolve => setTimeout(resolve, 1000)); // Chờ 1 giây
    
    // Nhấn Enter để tìm kiếm thay vì click nút (đơn giản hơn)
    await $page.keyboard.press('Enter');
    
    await new Promise(resolve => setTimeout(resolve, 2000)); // Chờ kết quả tải
    
    // Các thao tác khác...
    
  • Return dữ liệu: Để trả kết quả từ script về cho workflow n8n, sử dụng lệnh return. Bạn có thể trả về dữ liệu JSON và/hoặc dữ liệu nhị phân (binary).

Chụp Ảnh Màn Hình Làm Bằng Chứng ($page.screenshot())

Một tính năng hữu ích là chụp ảnh màn hình trang web để kiểm tra kết quả hoặc lưu lại bằng chứng.

// Trong Custom Script của node Puppeteer n8n, sau các thao tác

const screenshotBuffer = await $page.screenshot();

// Trả về screenshot dưới dạng binary data
return [{
  json: { // Dữ liệu JSON bạn muốn trả về
    status: "Thành công",
    searchedFor: "Puppeteer n8n in n8n"
  },
  binary: { // Dữ liệu binary
    screenshot: screenshotBuffer // n8n sẽ tạo một binary property tên là 'screenshot'
  }
}];

Xử Lý và Hiển Thị Kết Quả Screenshot trong n8n

Chạy Puppeteer trên Server Không Có Giao Diện (Headless)

Khi bạn triển khai n8n trên một server không có môi trường desktop (ví dụ: VPS, Docker), Puppeteer sẽ cần chạy ở chế độ headless: true. Node Puppeteer trong n8n thường đã được cấu hình để xử lý tốt trường hợp này. Nếu bạn đã đặt headless: false trong code local, bạn có thể không cần tùy chọn này trong n8n, hoặc đảm bảo rằng cấu hình của node Puppeteer cho phép chạy headless. Video cũng đề cập đến việc nếu n8n được cài trên server không có X server, việc chạy non-headless sẽ thất bại.

Hiển Thị Ảnh Screenshot Trực Tiếp trong n8n

Mặc định, khi node Puppeteer trả về một file ảnh nhị phân (binary data) như kết quả của screenshot(), giao diện n8n chỉ hiển thị nút "Download" cho file đó. Video đã chỉ ra một workaround để có thể xem (View) ảnh trực tiếp:

  1. Puppeteer Node (Custom Script): Đảm bảo script của bạn trả về buffer ảnh trong phần binary của đối tượng return.

    // ... (code Puppeteer)
    const screenshotBuffer = await $page.screenshot();
    return [{
      json: { message: "Screenshot taken" },
      binary: {
        rawScreenshot: screenshotBuffer // Tên binary property, ví dụ: rawScreenshot
      }
    }];
    
  2. Thêm Node "Move Binary Data":

    • Mục đích: Chuyển đổi dữ liệu binary của ảnh sang chuỗi Base64.
    • Source Key: rawScreenshot (tên binary property bạn đã đặt ở node Puppeteer).
    • Destination Key: base64ImageString (tên mới cho chuỗi Base64 sẽ được lưu trong json).
    • Operation: Convert to Base64 String.
    • Node này sẽ tạo ra một thuộc tính JSON (ví dụ: json.base64ImageString) chứa dữ liệu ảnh đã được mã hóa Base64.
  3. Thêm Node "Edit Fields" (hoặc "Function Item"):

    • Mục đích: Tạo một binary item mới từ chuỗi Base64, mà n8n có thể hiển thị nút "View".
    • Mode: Add/Update Fields.
    • Fields to Add/Update:
      • Field Name: displayableScreenshot (đây sẽ là tên binary property mới có nút View).
      • Field Value: {{ $('Node_Move_Binary_Data').item.json.base64ImageString }} (thay Node_Move_Binary_Data bằng tên thực tế của node "Move Binary Data" của bạn; trỏ đến chuỗi Base64 đã tạo).
      • Data Type: Binary
      • MIME Type: image/png (hoặc image/jpeg tùy định dạng ảnh).
      • Source Encoding: Base64.

Sau khi thiết lập như vậy, node "Edit Fields" sẽ có một output binary tên là displayableScreenshot với nút "View", cho phép bạn xem ảnh trực tiếp trong giao diện n8n.

Lưu ý: Video cũng đề cập rằng nếu bạn sử dụng action "Get Screenshot" có sẵn trong node Puppeteer (thay vì "Run Custom Script"), thì ảnh kết quả thường sẽ có sẵn nút "View" mà không cần các bước chuyển đổi phức tạp này. Tuy nhiên, "Run Custom Script" mang lại sự linh hoạt cao hơn.

Tùy Chỉnh Nâng Cao với Node Puppeteer trong n8n

Node Puppeteer trong n8n cung cấp nhiều tùy chọn cấu hình sẵn mà không cần bạn phải viết code trong Custom Script:

  • Launch Arguments: Bạn có thể truyền các cờ dòng lệnh cho Chromium. Ví dụ, để đặt kích thước cửa sổ, bạn có thể thêm argument window-size=1280x720 trực tiếp trong cấu hình node.
  • Emulate Device: Giả lập các thiết bị di động khác nhau (iPhone, iPad, các dòng Android phổ biến). Điều này rất hữu ích để kiểm tra giao diện responsive hoặc truy cập phiên bản mobile của website.
  • Timeout: Cấu hình thời gian chờ mặc định cho các thao tác của Puppeteer.

Những tùy chọn này giúp bạn tinh chỉnh hành vi của Puppeteer một cách dễ dàng ngay từ giao diện n8n.

Kết Luận

Tự động hóa việc nhập liệu và tương tác với website bằng Puppeteer n8n mở ra vô vàn khả năng, giúp tiết kiệm thời gian, giảm thiểu sai sót và giải phóng bạn khỏi những công việc lặp đi lặp lại. Từ việc mô phỏng các hành động cơ bản như nhấp chuột, điền form, đến việc chụp ảnh màn hình và tích hợp vào các quy trình phức tạp hơn, sự kết hợp này thực sự mạnh mẽ.

Mặc dù có những thách thức như CAPTCHA, việc hiểu rõ cách hoạt động của Puppeteer, cách lấy selector chính xác và cách cấu trúc script một cách logic là chìa khóa để thành công. Đừng ngần ngại bắt đầu với những script đơn giản, thử nghiệm trên máy tính cá nhân, sau đó dần dần tích hợp vào n8n và khám phá thêm các tính năng nâng cao.

Hy vọng bài viết này đã cung cấp cho bạn những kiến thức nền tảng và các bước thực hành cần thiết để bắt đầu hành trình tự động hóa trình duyệt với Puppeteer và n8n. Chúc bạn thành công!

0 Answers