Scraping BrowserHướng dẫnCloudflare bỏ qua trong cào web

Trình duyệt Scraping và Cloudflare

Tài liệu kỹ thuật này giải thích cách sử dụng các công cụ Trình duyệt Scraping Scrapeless và Scrapeless Web Unlocker để xử lý các thách thức bảo mật khác nhau được thiết lập bởi Cloudflare. Các tính năng chính bao gồm bỏ qua Thử thách JS Cloudflare, Cloudflare Turnstile và thực thi render JavaScript để truy cập nội dung được bảo vệ bởi Cloudflare. Tài liệu này sẽ cung cấp kiến thức nền tảng có liên quan, giới thiệu tính năng, các bước hoạt động và giải thích ví dụ mã.

Hiểu về các Thử thách và Lớp Bảo mật của Cloudflare

Cloudflare, một dịch vụ bảo mật và hiệu năng web phổ biến, chủ yếu bảo vệ các trang web khỏi lưu lượng truy cập độc hại hoặc không mong muốn, chẳng hạn như bot và máy quét. Để làm được điều này, Cloudflare triển khai nhiều cơ chế phát hiện và phòng thủ, bao gồm nhưng không giới hạn ở:

1. Thử thách JS (JavaScript Challenge): Yêu cầu trình duyệt của người truy cập thực thi mã JavaScript cụ thể để xác minh đó là môi trường trình duyệt hợp lệ với chức năng tiêu chuẩn.

2. Thay thế CAPTCHA Turnstile: Một cơ chế xác minh ít xâm phạm hơn để phân biệt giữa người dùng và bot.

3. Dấu vân tay trình duyệt: Thu thập và phân tích các đặc điểm kỹ thuật của trình duyệt và thiết bị (ví dụ: User-Agent, độ phân giải màn hình, phông chữ đã cài đặt, plugin) để xác định và theo dõi khách truy cập.

4. Giới hạn tốc độ: Giám sát và giới hạn số lượng yêu cầu từ một nguồn duy nhất (ví dụ: địa chỉ IP) trong một khoảng thời gian cụ thể để ngăn chặn tấn công brute-forcing hoặc lạm dụng tài nguyên.

Các lớp bảo mật này ngăn các thư viện yêu cầu HTTP cơ bản, các script đơn giản hoặc các trình duyệt headless được cấu hình không đúng cách truy cập vào các trang web được bảo vệ bởi Cloudflare, dẫn đến lỗi xác minh và từ chối truy cập.

Sự khác biệt giữa Thử thách JS Cloudflare và các Thử thách khác

Tính độc đáo của Thử thách JS Cloudflare nằm ở phương pháp xác minh của nó. Nó không chỉ yêu cầu người dùng hoàn thành một nhiệm vụ tương tác đơn giản (ví dụ: nhận dạng hình ảnh); nó đòi hỏi môi trường client (trình duyệt) phải phân tích cú pháp và thực thi thành công mã JavaScript được tạo động, thường bị che khuất, từ Cloudflare. Mã này thực hiện kiểm tra môi trường, các tác vụ tính toán chuyên sâu hoặc logic khác để xác minh khả năng hoạt động phức tạp của client, bắt chước một trình duyệt thực.

Việc vượt qua Thử thách JS thành công liên quan đến việc tạo một token xóa hợp lệ (thường ở dạng cookie cf_clearance). Token này chứng minh rằng client đã vượt qua xác minh khả năng thực thi JavaScript. Nhiều công cụ tự động hóa thiếu một công cụ thực thi JavaScript hoàn chỉnh và mô phỏng môi trường trình duyệt thực tế, do đó không vượt qua được các thử thách như vậy.

Bỏ qua Thử thách JS Cloudflare bằng Trình duyệt Scraping Scrapeless

Trình duyệt Scraping Scrapeless được thiết kế để xử lý các biện pháp bảo vệ trang web phức tạp, bao gồm cả Thử thách JS Cloudflare.

Các bước và Ví dụ mã

Cài đặt Môi trường

Tạo một Thư mục Dự án

Tạo một thư mục mới cho dự án, ví dụ: scrapeless-bypass.

Điều hướng đến thư mục trong terminal của bạn:

cd path/to/scrapeless-bypass

Khởi tạo Dự án Node.js

Chạy lệnh sau để tạo tệp package.json:

npm init -y

Cài đặt các Thuộc tính cần thiết

Cài đặt Puppeteer-core, cho phép kết nối từ xa đến các phiên bản trình duyệt:

npm install puppeteer-core

Nếu Puppeteer chưa được cài đặt trên hệ thống của bạn, hãy cài đặt phiên bản đầy đủ:

npm install puppeteer puppeteer-core

Thu thập và Cấu hình Khóa API Scrapeless của bạn.

Kết nối và Đảm bảo CAPTCHA được Giải quyết Thành công

Scrapeless tự động phát hiện và giải quyết CAPTCHA khi kết nối với trình duyệt để truy cập trang web mục tiêu. Tuy nhiên, chúng ta cần đảm bảo CAPTCHA được giải quyết thành công. Trình duyệt Scraping Scrapeless mở rộng CDP (Chrome DevTools Protocol) tiêu chuẩn với một tập hợp các khả năng tùy chỉnh mạnh mẽ. Trạng thái của bộ giải quyết CAPTCHA có thể được quan sát trực tiếp bằng cách kiểm tra kết quả trả về từ API CDP:

  • Captcha.detected: CAPTCHA được phát hiện
  • Captcha.solveFinished: CAPTCHA được giải quyết thành công
  • Captcha.solveFailed: Giải quyết CAPTCHA thất bại
import puppeteer from "puppeteer-core";
import EventEmitter from 'events';
const emitter = new EventEmitter()
const scrapelessUrl = 'wss://browser.scrapeless.com/browser?token=your_api_key&session_ttl=180&proxy_country=ANY';
 
export async function example(url) {
  const browser = await puppeteer.connect({
    browserWSEndpoint: scrapelessUrl,
    defaultViewport: null
  });
  console.log("Verbonden met Scrapeless browser");
  try {
    const page = await browser.newPage();
    // Listen for captcha events
    console.debug("addCaptchaListener: Start listening for captcha events");
    await addCaptchaListener(page);
    console.log("Navigated to URL:", url);
    await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
    console.log("onCaptchaFinished: Waiting for captcha solving to finish...");
    await onCaptchaFinished()
    // Screenshot for debugging
    console.debug("Taking screenshot of the final page...");
    await page.screenshot({ path: 'screenshot.png', fullPage: true });
  } catch (error) {
    console.error(error);
  } finally {
    await browser.close();
    console.log("Browser closed");
  }
}
 
async function addCaptchaListener(page) {
  const client = await page.createCDPSession();
  client.on("Captcha.detected", (msg) => {
    console.debug("Captcha.detected: ", msg);
  });
  client.on("Captcha.solveFinished", async (msg) => {
    console.debug("Captcha.solveFinished: ", msg);
    emitter.emit("Captcha.solveFinished", msg);
    client.removeAllListeners()
  });
}
 
async function onCaptchaFinished(timeout = 60_000) {
  return Promise.race([
    new Promise((resolve) => {
      emitter.on("Captcha.solveFinished", (msg) => {
        resolve(msg);
      });
    }),
    new Promise((_, reject) => setTimeout(() => reject('Timeout'), timeout))
  ])
}

Luồng công việc ví dụ này truy cập trang web mục tiêu và xác nhận CAPTCHA đã được giải quyết thành công bằng cách lắng nghe sự kiện CDP Captcha.solveFinished. Cuối cùng, nó chụp ảnh màn hình của trang để xác minh.

Ví dụ này định nghĩa hai phương pháp chính:

  • addCaptchaListener: để lắng nghe các sự kiện CAPTCHA trong phiên trình duyệt
  • onCaptchaFinished: để chờ cho đến khi CAPTCHA đã được giải quyết

Mã ví dụ trên có thể được sử dụng để lắng nghe các sự kiện CDP cho ba loại CAPTCHA phổ biến được thảo luận trong bài viết này: reCAPTCHA v2, Cloudflare Turnstile và Cloudflare 5s Challenge.

Lưu ý rằng Cloudflare 5s Challenge hơi đặc biệt. Đôi khi nó không kích hoạt một thử thách thực sự, và chỉ dựa vào phát hiện sự kiện CDP để thành công có thể dẫn đến hết thời gian chờ. Do đó, việc chờ một phần tử cụ thể xuất hiện trên trang sau khi thử thách là một giải pháp ổn định hơn.

Kết nối với Scrapeless Browserless WebSocket

Scrapeless cung cấp kết nối WebSocket, cho phép Puppeteer tương tác trực tiếp với trình duyệt headless, bỏ qua các thử thách Cloudflare.

Địa chỉ kết nối WebSocket đầy đủ:

wss://browser.scrapeless.com/browser?token=APIKey&session_ttl=180&proxy_country=ANY

Ví dụ mã: Bỏ qua Thử thách Cloudflare

Chúng ta chỉ cần mã sau để kết nối với dịch vụ browserless của Scrapeless.

import puppeteer from 'puppeteer-core';
 
const API_KEY = 'your_api_key'
const host = 'wss://browser.scrapeless.com';
const query = new URLSearchParams({
  token: API_KEY,
  session_ttl: '180', // The life cycle of a browser session, in seconds
  proxy_country: 'GB', // Agent country
  proxy_session_id: 'test_session_id', // The proxy session id is used to keep the proxy ip unchanged. The session time is 3 minutes by default, based on the proxy_session_duration setting.
  proxy_session_duration: '5' // Agent session time, unit minutes
}).toString();
 
const connectionURL = `${host}/browser?${query}`;
const browser = await puppeteer.connect({
    browserWSEndpoint: connectionURL,
    defaultViewport: null,
});
console.log('Connected!')

Truy cập các Trang web được Bảo vệ bởi Cloudflare và Xác minh Ảnh chụp màn hình

Tiếp theo, chúng ta sử dụng scrapeless browserless để truy cập trực tiếp vào trang kiểm tra thử thách cloudflare và thêm ảnh chụp màn hình, cho phép xác minh trực quan. Trước khi chụp ảnh màn hình, lưu ý rằng bạn cần sử dụng waitForSelector để chờ các phần tử trên trang, đảm bảo thử thách Cloudflare đã được bỏ qua thành công.

const page = await browser.newPage();
await page.goto('https://www.scrapingcourse.com/cloudflare-challenge', {waitUntil: 'domcontentloaded'});
// By waiting for elements in the site page, ensuring that the Cloudflare challenge has been successfully bypassed.
await page.waitForSelector('main.page-content .challenge-info', {timeout: 30 * 1000})
await page.screenshot({path: 'challenge-bypass.png'});

Tại thời điểm này, bạn đã bỏ qua thử thách Cloudflare bằng Scrapeless Browserless.

Sau khi vượt qua thử thách Cloudflare, bạn có thể truy xuất các tiêu đề yêu cầu và cookie cf_clearance từ trang thành công.

const cookies = await browser.cookies()
const cfClearance = cookies.find(cookie => cookie.name === 'cf_clearance')?.value

Bật chặn yêu cầu để chụp các tiêu đề yêu cầu và khớp các yêu cầu trang sau khi thử thách Cloudflare.

await page.setRequestInterception(true);
page.on('request', request => {
  // Match page requests after cloudflare challenge
  if (request.url().includes('https://www.scrapingcourse.com/cloudflare-challenge') && request.headers()?.['origin']) {
    const accessRequestHeaders = request.headers();
    console.log('[access_request_headers] =>', accessRequestHeaders);
  }
  request.continue();
});

Bỏ qua Cloudflare Turnstile bằng Trình duyệt Scraping Scrapeless

Trình duyệt Scraping Scrapeless cũng xử lý các thử thách Cloudflare Turnstile.

Tương tự, khi gặp phải Cloudflare Turnstile, trình duyệt scraping browserless vẫn có thể xử lý nó tự động. Ví dụ sau truy cập vào trang kiểm tra cloudflare-turnstile. Sau khi nhập tên người dùng và mật khẩu, nó sử dụng phương pháp waitForFunction để chờ dữ liệu từ window.turnstile.getResponse(), đảm bảo thử thách được bỏ qua thành công. Sau đó, nó chụp ảnh màn hình và nhấp vào nút đăng nhập để điều hướng đến trang tiếp theo.

Các bước và Ví dụ mã:

const page = await browser.newPage();
await page.goto('https://www.scrapingcourse.com/login/cf-turnstile', { waitUntil: 'domcontentloaded' });
await page.locator('input[type="email"]').fill('admin@example.com')
await page.locator('input[type="password"]').fill('password')
// Wait for turnstile to unlock successfully
await page.waitForFunction(() => {
  return window.turnstile && window.turnstile.getResponse();
});
await page.screenshot({ path: 'challenge-bypass-success.png' });
await page.locator('button[type="submit"]').click()
await page.waitForNavigation()
await page.screenshot({ path: 'next-page.png' });

Sau khi chạy script này, bạn sẽ thấy hiệu ứng mở khóa thông qua ảnh chụp màn hình.

Sử dụng Scrapeless Web Unlocker để Render JavaScript

Đối với các trang web được bảo vệ bởi Cloudflare, nơi nội dung cốt lõi dựa vào việc thực thi JavaScript phía client để tải và hiển thị hoàn chỉnh, Scrapeless Web Unlocker cung cấp một giải pháp chuyên dụng.

Scrapeless Universal API cho phép render JavaScript và tương tác động, làm cho nó trở thành một công cụ hiệu quả để bỏ qua Cloudflare.

Render JavaScript

Render JavaScript hỗ trợ xử lý nội dung được tải động và SPA (Single-Page Applications). Nó hỗ trợ môi trường trình duyệt đầy đủ, xử lý các tương tác trang và yêu cầu render phức tạp hơn.

Với js_render=true, chúng ta sẽ sử dụng trình duyệt cho yêu cầu

{
  "actor": "unlocker.webunlocker",
  "input": {
    "url": "https://www.google.com/",
    "js_render": true
  },
  "proxy": {
    "country": "US"
  }
}

Hướng dẫn JavaScript

Cung cấp một tập hợp rộng các hướng dẫn JavaScript, cho phép tương tác động với các trang web.

Các hướng dẫn này cho phép nhấp vào các phần tử, điền vào biểu mẫu, gửi biểu mẫu hoặc chờ các phần tử cụ thể xuất hiện, cung cấp tính linh hoạt cho các tác vụ như nhấp vào nút “Đọc thêm” hoặc gửi biểu mẫu.

{
  "actor": "unlocker.webunlocker",
  "input": {
    "url": "https://example.com",
    "js_render": true,
    "js_instructions": [
      {
        "wait_for": [
          ".dynamic-content",
          30000
        ]
        // Wait for element
      },
      {
        "click": [
          "#load-more",
          1000
        ]
        // Click element
      },
      {
        "fill": [
          "#search-input",
          "search term"
        ]
        // Fill form
      },
      {
        "keyboard": [
          "press",
          "Enter"
        ]
        // Simulate key press
      },
      {
        "evaluate": "window.scrollTo(0, document.body.scrollHeight)"
        // Execute custom JS
      }
    ]
  }
}

Ví dụ Bỏ qua Thử thách

Ví dụ sau sử dụng axios để gửi yêu cầu đến dịch vụ Web Unlocker của Scrapeless. Nó cho phép js_render và sử dụng hướng dẫn wait_for trong tham số js_instructions để chờ một phần tử trên trang sau khi bỏ qua thử thách Cloudflare:

import axios from 'axios'
 
async function sendRequest() {
  const host = "api.scrapeless.com";
  const url = `https://${host}/api/v1/unlocker/request`;
  const API_KEY = 'your_api_key'
 
  const payload = {
    actor: "unlocker.webunlocker",
    proxy: {
      country: "US"
    },
    input: {
      url: "https://www.scrapingcourse.com/cloudflare-challenge",
      js_render: true,
      js_instructions: [
        {
          wait_for: [
            "main.page-content .challenge-info",
            30000
          ]
        }
      ]
    },
  }
 
  try {
    const response = await axios.post(url, payload, {
      headers: {
        'Content-Type': 'application/json',
        'x-api-token': API_KEY
      }
    });
    console.log("[page_html_body] =>", response.data);
  } catch (error) {
    console.error('Error:', error);
  }
}
sendRequest();

Sau khi chạy script trên, bạn sẽ có thể thấy HTML của trang đã bỏ qua thử thách Cloudflare thành công trong console.