使用curl_cffi请求Metro页面遭Cloudflare拦截,求解决方案
解决curl_cffi抓取Metro网站时的Cloudflare拦截问题
问题根源
你碰到的是Cloudflare的人机验证拦截:虽然修改User-Agent能让cURL返回200,但curl_cffi里手动设置的旧版User-Agent(Chrome109)和impersonate='chrome131'模拟的浏览器指纹不匹配,反而触发了更严格的检测;另外Cloudflare不会只验证User-Agent,还会检查请求头顺序、TLS握手信息、Cookie会话等多个维度的浏览器指纹。
具体解决思路
- 删除手动设置的User-Agent:
impersonate参数会自动生成对应浏览器版本的标准User-Agent,手动设置的旧版本值会和模拟的指纹冲突,直接移除即可。 - 补充浏览器默认请求头:添加真实浏览器会发送的
Accept、Accept-Language、Referer等头,让请求更贴近正常浏览行为。 - 用Session保持Cookie:Cloudflare会通过Cookie跟踪会话状态,首次验证通过后,后续请求携带Cookie可避免重复触发验证码。
- 切换模拟的浏览器版本:如果chrome131仍被检测,尝试换成更稳定的版本(比如
chrome120或firefox121),不同版本的指纹检测严格度有差异。
修改后的代码示例
from curl_cffi import requests url = "https://www.metro.ca/en/online-grocery/aisles/fruits-vegetables" # 只保留必要的补充头,让impersonate自动生成匹配的标准头 headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Referer': 'https://www.metro.ca/', } # 使用Session持久化Cookie session = requests.Session() response = session.get(url, headers=headers, impersonate='chrome131') print(response.status_code) print(response.text[:500]) # 打印前500字符验证内容
额外注意事项
- 如果还是触发验证码,需要添加代理IP,避免单一IP频繁请求被标记。
- 控制请求间隔,不要短时间内重复请求,模拟人类浏览的节奏。
- 确保curl_cffi是最新版本,旧版本可能存在指纹模拟的漏洞。
内容的提问来源于stack exchange,提问作者Osama Abdullah
相关产品推荐
相关产品推荐

