做公开资讯采集这几年,Cloudflare绝对是绕不开的一道坎。前两年碰上海外一批技术博客和资讯站,清一色套了Cloudflare防护,原生requests上去直接403,连页面HTML都摸不到。
一开始想当然觉得是IP的问题,前前后后换了三家代理供应商,钱花了小两千,结果新IP撑不过三个请求就进挑战页,整体通过率不到30%。后来抓包逐层拆才反应过来:根本不是IP的锅——我们的请求从TCP握手那一刻起,TLS指纹就已经明明白白写着“我是Python程序”,对方根本不用看请求内容,协议层一对就直接打回。
前后折腾了两周,从纯HTTP客户端摸到无头浏览器,摸透了不同防护等级的应对逻辑,总结出三套分层方案。不用上来就砸钱买高端住宅代理,普通防护的站点,零代理费用就能做到90%以上的通过率。
一、先搞清楚:你面对的是哪个等级的防护?
很多人上来就问“怎么过Cloudflare”,其实它的防护是分级的,不同等级对应的方案天差地别,搞错了就是白费力气。先判断清楚类型,再选对应方案,效率能高好几倍。
一级防护:协议层指纹检测
最轻的一档,只校验TLS指纹、HTTP头完整性、请求特征,没有JS挑战。
- 典型表现:浏览器直接访问正常,原生requests/httpx请求直接返回403;没有“Just a moment”的等待页面。
- 常见场景:个人博客、普通资讯站、技术文档站。
- 应对成本:极低,改个客户端就能解决。
二级防护:5秒盾JS挑战
最常见的一档,返回包含JS的挑战页面,客户端执行完JS计算、生成cf_clearance Cookie后才能正常访问。
- 典型表现:打开页面先显示“正在验证浏览器”,5秒左右自动跳转;页面源码里有大量混淆JS。
- 常见场景:中小型社区、内容站、普通企业官网。
- 应对成本:中等,需要能执行JS的环境过挑战。
三级防护:托管式人机挑战
最高的一档,结合浏览器环境检测、行为分析,可能弹出Turnstile无感人机验证,甚至滑块、点选。
- 典型表现:频繁弹出验证、IP稍一频繁就出挑战页、纯脚本环境完全通不过。
- 常见场景:大型社区、电商平台、高价值数据站点。
- 应对成本:较高,需要完整浏览器环境+行为优化。
绝大多数人日常碰到的都是前两档,根本用不着最重型的方案。先定位清楚等级,再对症下药,性价比最高。
二、方案一:轻量级,curl_cffi对齐协议指纹,搞定一级防护
这是性价比最高的方案,改两行代码就能解决80%的基础防护站点,也是我日常用得最多的。
为什么原生requests永远403?
很多人以为改了User-Agent就等于模拟浏览器了,其实差得远。
TLS握手的时候,客户端会发送加密套件列表、扩展列表、椭圆曲线参数等信息。Python requests、httpx这类库的底层网络栈和真实浏览器完全不同,生成的JA4指纹差异极大。Cloudflare只需要看一眼握手指纹,就能准确判断你是Python程序还是真实Chrome,你上层头改得再像都没用。
这就是为什么很多人百思不得其解:我UA、Referer、Cookie全抄浏览器的,怎么还是403?问题出在更底层的协议层。
解决方案:curl_cffi一键对齐浏览器指纹
curl_cffi 基于 curl-impersonate 封装,底层直接复刻Chrome、Firefox等浏览器的完整TLS栈,JA3/JA4指纹和真实浏览器完全一致,协议层直接和真实浏览器无差别。
安装和使用都非常简单:
pip install curl_cffi
基础会话封装:
from curl_cffi import requests
import random
import time
# 直接指定模拟的浏览器版本,TLS指纹自动对齐
session = requests.Session(impersonate="chrome128")
# 请求头要和模拟的浏览器版本完全对应,一个都别漏
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,en-US;q=0.5,en;q=0.3",
"Accept-Encoding": "gzip, deflate, br",
"Referer": "[https://example.com/](https://example.com/)",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1"
}
def fetch_page(url):
try:
resp = session.get(url, headers=headers, timeout=10)
resp.raise_for_status()
return resp.text
except Exception as e:
print(f"请求失败: {e}")
return None
实测效果与踩坑提醒
普通技术博客、资讯站这类一级防护站点,原生requests通过率20%左右,换成curl_cffi之后直接拉到95%以上,连代理都不用开。
几个必踩的坑提前说:
- 不是万能的。它只能解决协议层检测,带JS挑战的二级防护站点过不去,因为它不会执行JS,拿不到
cf_clearance。 - 指纹版本要和UA对应。你模拟Chrome 128,UA就必须写Chrome 128,版本对不上反而会因为特征矛盾拉高风险分。
- 要维护会话Cookie。不要每次请求都新建会话,正常用户是有连续Cookie的。空会话、空Cookie天生高风险。
三、方案二:中阶,浏览器拿Cookie + HTTP客户端复用,兼顾速度与通过率
碰到带5秒盾的二级站点,纯HTTP客户端就不够用了——它跑不了JS,拿不到通关用的cf_clearance Cookie。
很多人这时候就全程上Playwright硬爬,慢得要死还占资源,其实完全没必要。浏览器只用来过挑战拿Cookie,真正采集数据交给HTTP客户端,通过率和真实浏览器一致,速度却能快好几倍。
核心思路
- 用Playwright启动浏览器,访问目标站首页,等待5秒盾自动完成挑战,拿到完整Cookie
- 把Cookie、UA等信息同步到curl_cffi会话中
- 后续所有采集请求都用HTTP客户端发,速度和纯原生请求一致
- Cookie过期前,再用浏览器刷新一次即可,不用全程挂着浏览器
完整实现代码
from playwright.sync_api import sync_playwright
from curl_cffi import requests
def get_cf_cookies(url):
"""用浏览器过5秒盾,拿到有效Cookie"""
with sync_playwright() as p:
browser = p.chromium.launch(
headless="new", # 必须用新无头模式,旧无头很容易被检测
channel="chrome"
)
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
viewport={"width": 1920, "height": 1080},
locale="zh-CN",
timezone_id="Asia/Shanghai"
)
page = context.new_page()
# 访问首页,等待挑战自动通过
page.goto(url, wait_until="networkidle")
# 额外等待几秒,确保挑战完成、Cookie写入
page.wait_for_timeout(6000)
# 提取所有Cookie
cookies = context.cookies()
browser.close()
return cookies
def build_session(cookies):
"""把浏览器Cookie同步到HTTP会话"""
session = requests.Session(impersonate="chrome128")
for cookie in cookies:
session.cookies.set(cookie['name'], cookie['value'], domain=cookie['domain'])
return session
# 使用流程
if __name__ == "__main__":
target_url = "[https://example.com](https://example.com)"
# 1. 浏览器拿Cookie
cookies = get_cf_cookies(target_url)
# 2. 构建HTTP会话
session = build_session(cookies)
# 3. 后续批量采集全走HTTP,速度拉满
for i in range(100):
resp = session.get(f"{target_url}/page/{i}")
# 解析数据...
关键注意点
- 必须用新无头模式。旧版无头的环境特征非常明显,很容易被检测出来;
headless=new模式底层就是真实Chrome,特征差异极小。 - 不要刚打开就抓Cookie。等页面跳转完成、
cf_clearance写入之后再取,不然拿到的是无效Cookie。 - Cookie有有效期。一般几个小时到一天不等,失效了就重新用浏览器刷一次,不用频繁刷。
这套方案应对中等防护的站点非常稳,通过率接近真实浏览器,采集速度却是全程无头浏览器的5-10倍,性价比极高。
四、方案三:高阶,行为优化+会话预热,应对高强度防护
碰到防护等级高的站点,比如大型社区、内容平台,光有指纹和Cookie还不够。你环境是对的,但行为全是爬虫特征,照样会频繁出验证、被限流。
很多人觉得过了5秒盾就完事了,结果爬个三五页就又弹挑战,核心原因就是行为太反常。小红书、知乎这类国内内容平台的逻辑也高度相似:重点从来不是破解什么盾,是把风险分压在阈值以下。
分享几个经过验证的行为优化思路,做完之后验证码出现频率能降80%:
1. 完整访问路径,不要直奔目标
真实用户一定是从首页、列表页、搜索页一步步进到详情页的。直接请求深层接口、跳过所有前置路径,风险分直接拉满。
- 采集前先访问首页,初始化会话
- 先走2-3页列表页,模拟浏览翻页
- 再逐步进入详情页,Referer和上一页严格对应
- 中途穿插返回列表、翻下一页的动作,不要一条路走到黑
2. 频率随机化,不要固定节拍
固定间隔、匀速请求是最典型的程序特征。真人操作的节奏一定是波动的:看长文章停得久,看短文章翻得快,偶尔还会停下来干点别的。
- 用正态分布生成请求间隔,不要用均匀随机,更不要固定值
- 每请求10-15页,插入一次10-20秒的长停留,模拟用户阅读、喝水的间隙
- 高峰期适当降速,不要半夜猛冲,正常用户不会凌晨三点每分钟刷十几页
3. IP、指纹、会话三者绑定
不要交叉混用:同一个IP对应一套Cookie、一套指纹、一个浏览器环境。频繁换IP、同IP乱换Cookie、同Cookie换不同指纹,都会触发异常检测。
- 稳定的IP比频繁换IP更安全。同一个IP稳定跑正常行为,比十分钟换八个IP的风险分低得多。
- 不要一个IP跑多个不相关的业务。不同站点、不同类型的任务分开用不同的IP段。
4. 错误降级,不要硬冲
碰到挑战页、403不要立刻疯狂重试,越重试风险分越高。
- 第一次出挑战,先停30秒再刷新一次
- 连续两次失败,就换会话重新过挑战,不要死磕
- 整体失败率上升时,主动降速,而不是加并发
五、最容易踩的五个误区
误区1:换IP就能解决一切
这是新手最容易陷进去的坑。403了就换IP,换了还封就买更贵的IP,结果钱花了不少,问题没解决。
很多时候封的根本不是IP,是你的客户端指纹。指纹不对,换多少IP都是刚上去就被识别,白费钱。先把底层特征对齐了,再考虑IP的事。
误区2:curl_cffi是万能的
网上很多文章吹“curl_cffi秒过Cloudflare”,都是标题党。它只能解决协议层的检测,带JS挑战的站点根本过不去,更别说三级的人机验证了。
对它的定位要准:是基础层的优化,不是万能钥匙。
误区3:全程用无头浏览器采集
很多人为了稳,全程Playwright跑,结果速度慢、并发低、服务器成本高。
浏览器只应该用来过挑战、拿Cookie。真正的批量数据采集,交给HTTP客户端效率高得多。能轻量就不要重型,架构越简单越稳。
误区4:只改UA,其他头全丢
请求头是一个整体,不是改个UA就完事了。Accept、Accept-Language、Sec-Fetch系列、Referer,缺一个或者格式不对,都会拉高风险分。
最稳妥的方式:从浏览器DevTools里把请求头原封不动抄下来,一个字段都别改,顺序也尽量保持一致。
误区5:追求速度,忽略稳定性
很多人总想着一秒钟爬多少页,结果跑十分钟就全封了,一天下来没多少有效数据。
采集这个事,稳永远比快重要。慢一点但能24小时不间断跑,产出量远高于猛冲半小时就全军覆没。把频率降下来,行为做正常,长期产出反而更高。
最后总结
Cloudflare的对抗从来不是单点突破,是分层匹配的游戏。
- 一级防护:对齐TLS指纹就够了,curl_cffi两行代码解决,零成本
- 二级防护:浏览器拿Cookie + HTTP复用,兼顾速度和通过率
- 三级防护:再加上行为优化和会话预热,把风险分压到阈值以下
不要上来就买最贵的代理、上最重的浏览器方案,先判断防护等级,从最轻的方案开始试。能用低成本解决的问题,就没必要堆资源。
最后还是要提醒一句:本文仅讨论公开数据采集的请求优化技术,所有数据采集行为请严格遵守《网络安全法》及目标网站的robots协议,只爬取公开允许的内容,不得用于非法商业用途。
本文系统解析Cloudflare三级防护机制:一级协议层指纹检测、二级5秒JS挑战、三级托管式人机验证。提出三套分层应对方案——curl_cffi对齐TLS指纹解决一级防护;Playwright过盾+HTTP客户端复用应对二级;叠加行为优化(访问路径模拟、频率随机化、IP-指纹-会话绑定、错误降级)攻克三级防护。强调避免换IP万能论、curl_cffi局限性、无头浏览器滥用等五大误区,聚焦信息技术领域中的反爬对抗核心策略。
&spm=1001.2101.3001.5002&articleId=169267706&d=1&t=3&u=d33306acbcc84d148bb33cbe1dcb2fa8)
345

被折叠的 条评论
为什么被折叠?



