Scraping Browser指南网络爬取中的绕过Cloudflare

Web抓取中的Cloudflare绕过

抓取浏览器和Cloudflare

本文档介绍如何使用Scrapeless抓取浏览器和Scrapeless Web Unlocker工具来处理Cloudflare设置的各种安全挑战。主要功能包括绕过Cloudflare JS挑战、Cloudflare Turnstile以及执行JavaScript渲染以访问受Cloudflare保护的内容。本文档将提供相关的背景知识、功能介绍、操作步骤和代码示例说明。

理解Cloudflare挑战和安全层

Cloudflare是一款流行的Web安全和性能服务,主要保护网站免受恶意或意外流量(例如机器人和扫描程序)的攻击。为此,Cloudflare实施了各种检测和防御机制,包括但不限于:

**1. JS挑战(JavaScript挑战):**要求访问者的浏览器执行特定的JavaScript代码,以验证它是一个具有标准功能的合法浏览器环境。

**2. Turnstile CAPTCHA替代方案:**一种侵入性较小的验证机制,用于区分人类用户和机器人。

**3. 浏览器指纹识别:**收集和分析浏览器和设备的技术特征(例如,User-Agent、屏幕分辨率、已安装字体、插件)以识别和跟踪访问者。

**4. 速率限制:**监控并限制特定时间内来自单个来源(例如,IP地址)的请求数量,以防止暴力破解或资源滥用。

这些安全层阻止基本的HTTP请求库、简单的脚本或配置不当的无头浏览器访问受Cloudflare保护的网站,导致验证失败和访问被拒。

Cloudflare JS挑战与其他挑战的区别

Cloudflare JS挑战的独特性在于其验证方法。它不仅要求用户完成简单的交互式任务(例如,图像识别);它要求客户端环境(浏览器)成功解析并执行Cloudflare生成的动态的、通常是混淆的JavaScript代码。此代码执行环境检查、计算密集型任务或其他逻辑,以验证客户端的复杂行为能力,模拟真实的浏览器。

成功通过JS挑战涉及生成有效的清除令牌(通常为cf_clearance cookie的形式)。此令牌证明客户端通过了JavaScript执行能力验证。许多自动化工具缺乏完整的JavaScript执行引擎和真实的浏览器环境模拟,因此无法通过此类挑战。

使用Scrapeless抓取浏览器绕过Cloudflare JS挑战

Scrapeless抓取浏览器旨在处理复杂的网站保护措施,包括Cloudflare JS挑战。

步骤和代码示例

环境设置

创建项目文件夹

为项目创建一个新文件夹,例如:scrapeless-bypass。

在终端中导航到该文件夹:

cd path/to/scrapeless-bypass

初始化Node.js项目

运行以下命令以创建package.json文件:

npm init -y

安装所需的依赖项

安装Puppeteer-core,它允许远程连接到浏览器实例:

npm install puppeteer-core

如果系统上尚未安装Puppeteer,请安装完整版本:

npm install puppeteer puppeteer-core

获取和配置您的Scrapeless API密钥。

连接并确保CAPTCHA已成功解决

Scrapeless在连接到浏览器以访问目标网站时会自动检测并解决CAPTCHA。但是,我们需要确保CAPTCHA已成功解决。Scrapeless抓取浏览器通过强大的自定义功能扩展了标准CDP(Chrome DevTools协议)。可以通过检查从CDP API返回的结果直接观察CAPTCHA求解器的状态:

  • Captcha.detected: 检测到CAPTCHA
  • Captcha.solveFinished: CAPTCHA成功解决
  • Captcha.solveFailed: CAPTCHA解决失败
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))
  ])
}

此示例工作流程访问目标网站并通过侦听Captcha.solveFinished CDP事件确认CAPTCHA已成功解决。最后,它捕获页面的屏幕截图以进行验证。

此示例定义了两种主要方法:

  • addCaptchaListener: 用于侦听浏览器会话中的CAPTCHA事件
  • onCaptchaFinished: 用于等待直到CAPTCHA已解决

上述示例代码可用于侦听本文讨论的三种常见CAPTCHA类型的CDP事件:reCAPTCHA v2、Cloudflare Turnstile和Cloudflare 5s挑战

请注意,Cloudflare 5s挑战有点特殊。有时它不会触发实际的挑战,并且仅仅依赖于CDP事件检测成功可能会导致超时。因此,在挑战之后等待页面上出现特定元素是更稳定的解决方案。

连接到Scrapeless Browserless WebSocket

Scrapeless 提供WebSocket连接,允许Puppeteer直接与无头浏览器交互,绕过Cloudflare挑战。

完整的WebSocket连接地址:

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

代码示例:绕过Cloudflare挑战

我们只需要以下代码即可连接到Scrapeless的browserless服务。

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!')

访问受Cloudflare保护的网站和屏幕截图验证

接下来,我们使用scrapeless browserless 直接访问cloudflare-challenge测试站点并添加屏幕截图,以便进行视觉验证。在截取屏幕截图之前,请注意您需要使用waitForSelector等待页面上的元素,以确保已成功绕过Cloudflare挑战。

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'});

此时,您已使用Scrapeless Browserless绕过Cloudflare挑战。

获取cf_clearance Cookie和Header

通过Cloudflare挑战后,您可以从成功的页面中检索请求标头和cf_clearance cookie。

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

启用请求拦截以捕获请求标头并匹配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();
});

使用Scrapeless Web Unlocker进行JavaScript渲染

对于核心内容依赖于客户端JavaScript执行才能完全加载和显示的受Cloudflare保护的网站,Scrapeless Web Unlocker提供了一个专门的解决方案。

Scrapeless 通用API支持JavaScript渲染和动态交互,使其成为绕过Cloudflare的有效工具。

JavaScript渲染

JavaScript渲染支持处理动态加载的内容和SPA(单页应用程序)。它支持完整的浏览器环境,处理更复杂的页面交互和渲染需求。

使用js_render=true,我们将使用浏览器发出请求

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

JavaScript指令

提供广泛的JavaScript指令集,允许与网页进行动态交互。

这些指令能够单击元素、填充表单、提交表单或等待特定元素出现,为诸如单击“阅读更多”按钮或提交表单之类的任务提供灵活性。

{
  "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
      }
    ]
  }
}

挑战绕过示例

以下示例使用axios向Scrapeless的Web Unlocker服务发送请求。它启用js_render并在js_instructions参数中使用wait_for指令来等待页面上绕过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();

运行上述脚本后,您将能够在控制台中看到成功绕过Cloudflare挑战的页面的HTML。