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
: 检测到CAPTCHACaptcha.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。