You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用requests爬取cardmarket网站持续返回403响应的问题求助

原因分析
  • Cloudflare防护机制:cardmarket采用的Cloudflare防护不仅校验请求头,还会验证客户端是否具备真实浏览器的核心特征——比如能否执行JavaScript、生成Canvas指纹、匹配标准TLS握手参数等。requests是纯HTTP请求库,无法模拟这些浏览器行为,因此直接被拦截返回403。
  • 代理有效性不足:你用httpbin.org验证代理仅能确认代理可正常转发请求,但Cloudflare会检测代理IP的信誉度——免费代理池中的IP大多已被Cloudflare标记为恶意爬虫IP,即便能通过httpbin,也无法绕过Cloudflare的验证。
  • 代码逻辑错误:请求cardmarket后尝试调用response.json(),但该网站返回的是HTML页面而非JSON格式,这会直接触发异常,导致你无法看到实际的响应内容(比如Cloudflare的验证页面)。
解决方案

1. 用支持JS渲染的工具替代requests

使用Playwright或Selenium模拟真实浏览器,它们能执行Cloudflare要求的JavaScript验证,自动完成人机校验并获取有效Cookie与页面内容。

示例(Playwright):

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    # 先禁用无头模式,直观查看Cloudflare验证过程
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    # 模拟浏览器导航行为,触发Cloudflare验证
    page.goto("https://www.cardmarket.com/en/Magic")
    # 等待页面加载完成,确保验证通过
    page.wait_for_load_state("networkidle")
    # 获取完整页面HTML
    html_content = page.content()
    print(html_content)
    browser.close()

2. 优化请求头与Cookie管理(仅适用于Cloudflare验证较松的场景)

如果坚持使用requests,需做到:

  • 从真实浏览器中复制完整请求头(包括Accept、Accept-Encoding、Accept-Language、Referer、User-Agent等),确保与浏览器请求头完全一致;
  • 手动在浏览器中完成Cloudflare验证,然后复制浏览器的Cookie(如__cf_bm、cf_clearance)到请求中:
import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    # 补充其他从浏览器复制的请求头字段
}

cookies = {
    # 从浏览器开发者工具的Application->Cookies中复制Cloudflare相关Cookie
    "__cf_bm": "xxx",
    "cf_clearance": "xxx"
}

response = requests.get("https://www.cardmarket.com/en/Magic", headers=headers, cookies=cookies)
print(response.status_code)
print(response.text[:1000])

3. 更换高质量代理

放弃免费代理,选择住宅代理(Residential Proxy)——这类IP来自真实用户设备,IP信誉度高,更容易通过Cloudflare检测。使用时确保代理支持HTTPS,且每次请求更换IP。

4. 修正代码逻辑错误

请求cardmarket后,不要直接调用response.json(),先检查响应状态码并打印部分内容排查问题:

try:
    response = requests.get(url, headers=headers, proxies=proxies, timeout=2)
    print(f"状态码: {response.status_code}")
    # 打印响应前1000字符,判断是否为Cloudflare验证页面
    print(response.text[:1000])
except Exception as e:
    print(f"代理{proxy_url}失败: {str(e)}")

内容的提问来源于stack exchange,提问作者ahoone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:27:52