如何抓取受 Cloudflare 保护的网站(2026 指南)
Cloudflare 位于大量公共网站的前端,因此一个在某个网站上能正常工作的抓取器,到了下一个网站上往往就会碰壁。你通常会以 HTTP 403 或 503、一个“Just a moment...”过渡页面,或者页面上的 Turnstile 复选框的形式注意到它。本指南说明 Cloudflare 在检查什么,哪些方法有效且不触碰你不该触碰的东西,以及验证码识别在其中处于什么位置。简短地说:确认你可以抓取该网站,放慢速度,发送看起来像正常客户端的请求,需要 JavaScript 时就使用真实浏览器,只有到这一步才处理验证码。Turnstile 是 Cloudflare 最常用的验证码。Scarnox 对 Turnstile 的支持即将推出。目前上线的验证码类型是 PopularCaptcha。
Cloudflare 在检查什么
Cloudflare 会根据多个信号为每个请求打分:
- IP 信誉。 来自云数据中心的地址,起始分数低于来自家庭宽带的地址。
- 请求频率和模式。 同一地址每秒发出数百个请求,无论请求头如何,看起来都像机器人。
- 请求头和 TLS 指纹。 原始的 HTTP 库通常会发送主流浏览器从不发送的请求头、请求头顺序和 TLS 握手。
- JavaScript 执行。 挑战页面会运行脚本,检查是否存在真实的浏览器环境。
- Cookie。 通过挑战之后,Cloudflare 会签发一个与该会话绑定的放行 Cookie。
分数高时会静默放行;分数中等时会出现交互式挑战;分数低时则直接封锁。大部分工作在于让你的分数提高,方法是表现得像一个守规矩的客户端,而不是与检查对抗。
第 1 步:确认你应该抓取该网站
在进行任何技术工作之前,先阅读网站的 robots.txt 和服务条款。封禁通常是网站所有者在告诉你某些信息。缓慢地、出于明确目的地抓取公开页面,是一回事。强行突破封禁去获取所有者限制的数据,则是另一回事,Scarnox 不支持后者。法律概述涵盖了一般性问题。
第 2 步:把普通请求做对
许多看起来“被封”的爬虫,其实只是发送了糟糕的请求。请先修复以下几点:
- 发送当前的 User-Agent,以及浏览器会发送的请求头,例如
Accept和Accept-Language。 - 使用同一个会话对象,使 Cookie 在请求之间保留,就像浏览器一样。
- 在请求之间加入延迟,并带一点随机抖动。
- 遇到
429和503响应时退避,而不是紧凑地循环重试。
import random
import time
import requests
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/124.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
})
def polite_get(url: str, attempts: int = 4) -> requests.Response:
r = None
for attempt in range(attempts):
r = session.get(url, timeout=30)
if r.status_code not in (429, 503):
return r
# 带抖动的指数退避:约 1、2、4 秒再加随机值。
time.sleep(2 ** attempt + random.uniform(0, 1))
return r
如果这样就能通过,那你就完成了。请保留这里的延迟设置。
第 3 步:判断你遇到的是哪种挑战
响应会告诉你很多信息:
- “Just a moment...”页面。 这是 JavaScript 挑战。真实浏览器通常几秒钟后就能自行通过。之后,同一会话中的后续请求就可以复用放行 Cookie。
- 表单或页面上的 Turnstile 控件。 这是验证码。在表单接受提交之前,需要先从控件获取 token。
- 带错误码的封锁页面。 地址或请求已被直接拒绝。调整节奏并修复请求,通常比其他任何方法都更有帮助。识别验证码并不能把硬性封锁变成数据。
先判断你看到的是哪一种,能省下大量无效的工作。
第 4 步:需要时使用真实浏览器
如果页面只有在 JavaScript 运行之后才显示内容,普通的 HTTP 客户端永远看不到它。请改用 Playwright 或 Selenium 驱动完整的浏览器。无头浏览器是可以被检测到的,因此在依赖它之前,请先阅读无头浏览器检测,并把它的设置调整为真实访客所处的环境。JavaScript 网站指南给出了一个完整示例。
第 5 步:检查你的 IP 信誉
云数据中心地址是干净请求得到低分的最常见原因。住宅地址通常得分较好,代价是速度更慢、成本更高。这种取舍在住宅代理与数据中心代理对比中有所说明。
轮换本身也有其陷阱。每个请求都更换地址看起来不自然,因为真实访客在整个访问过程中只使用一个地址。粘性会话,即在一组相关请求中保持同一个地址,通常比快速轮换效果更好。抓取用轮换代理对此有详细说明。
第 6 步:验证码识别在哪里介入
有时控件确实会出现,比如在你正在测试的表单上,或在你获得授权自动化的页面上。此时 Turnstile 的 token 是该流程中必需的一步。Scarnox 对 Turnstile 的支持即将推出,所以请不要基于它构建生产代码。目前上线的验证码类型是 PopularCaptcha,它使用的是另一种控件。
对于任何基于 token 的验证码,通用流程都是相同的。你从页面中读取 sitekey,请求一个 token,然后把 token 放入网站期望的表单字段。Token 的有效期很短,所以要立即提交。PopularCaptcha Python 指南从头到尾展示了这一流程,验证码类型详解则比较了你会遇到的各种控件。
如果你想在 Turnstile 支持上线时已经准备就绪,现在就可以开始免费试用。免费试用额度,无需信用卡:注册账户。目前上线验证码类型的费率,请查看定价页面。
负责任地抓取
- 阅读
robots.txt,并遵守你所抓取网站的条款。 - 对爬虫进行限速,并尽量在非高峰时段运行。
- 缓存响应,避免无理由地重复抓取同一个页面。
- 除非你有合法依据,否则避免收集个人数据。
- 如果网站限制了访问,就停下来,不要试图突破该限制。