常见的抓取障碍及其应对方法
在做出任何改变之前,先弄清楚究竟是什么在阻碍你——是标明供应商名称的标头、各个状态码的真实含义,还是哪些问题代理可以解决、哪些无法解决。
- 运营商级NAT信任 —— 目标无法在不屏蔽真实用户的情况下屏蔽的地址。
- 按需轮换 — 当你决定时,将真正失效的地址停用。
- 按国家匹配的退出 —— 这样就不会将地理封锁误认为机器人封锁。
- 专用硬件 —— 您的 IP 地址所享有的声誉,正是您自己建立起来的。
运营商IP地址与真实用户共用,因此封禁其中一个会造成高昂成本。
如果重置移动IP后问题仍未解决,那么问题从来就不是IP本身。
因爬虫被阻而浪费的大部分时间,都花在了解决错误的问题上。仅凭状态码很少能告诉你究竟发生了什么,而“轮换 IP 地址并重试”这种本能反应,则将所有症状都视为同一种“病症”。本页提供了一份故障分诊指南:先弄清楚是什么在阻碍你,然后选择相应的解决方案。
找出阻碍你的因素
在进行任何更改之前,请阅读响应内容,而不是状态行。主要的反机器人供应商通常会(往往是不经意地)透露其身份,而每家供应商所暗示的解决方法各不相同:
| 破绽 | 是谁 | 其含义 |
|---|---|---|
| cf-ray 标题,或 server: cloudflare | Cloudflare | 正文通常包含其自身的代码——例如,1020 表示防火墙规则,1015 表示速率限制。出现 JavaScript 插页广告,说明它需要浏览器支持。 |
| x-datadome 页眉、带有品牌标识的挑战页面 | DataDome | 高度依赖指纹识别。仅凭一个干净的IP地址通常无法解决问题;客户端必须看起来像一个浏览器。 |
| _px3 Cookie,或对 px-captcha | PerimeterX(现更名为HUMAN) | 行为评分占据很大比重——语速和互动的重要性不亚于内容本身。 |
| 无厂商标识,素面短身款 | 本网站的规则 | 通常更简单:一个 User-Agent 过滤器、一个必填标头,或者一条你能遵守的速率规则。 |
在首次出现错误时,将完整的响应头和正文的前几百字节导出并保存下来。下面几乎所有问题都能通过该捕获记录得到解答,而且在开始修改设置后要重现某个代码块,远比一次性记录下来要困难得多。
各个状态码的实际含义
两种看似同样失败的反应,其原因可能截然相反。这是值得内化的一套对应关系:
| 回复 | 最可能的原因 | 首先可以尝试的方法 |
|---|---|---|
| 403 立即,微小或空的躯体 | 反机器人拒绝机制——基于指纹或请求头,而非权限 | 在处理代理之前,先修复客户端的 TLS 配置文件和头部信息 |
| 403 在取得一系列成功之后 | 这个地址名副其实——无论是费率还是交易量 | 降低并发数,然后轮换问题IP |
| 429 带 Retry-After | 诚实的速率限制 | 请 exactly 等待这么久。不要旋转并立即重试 |
| 407 | 是你的代理拒绝了你,而不是目标 | 检查凭据,或确认该主机是否在白名单中 |
| 503 附带一个挑战页面 | JavaScript 的插播式等待 | 一个真正的浏览器,或者一个无需浏览器即可返回数据的端点 |
| 200 无数据——软阻塞 | 挑战或空壳被视为成功 | 对内容进行验证,而非状态——这正是会悄无声息地破坏数据集的元凶 |
| 重定向循环,或是同意壁或区域壁 | 地理位置或Cookie状态,而非机器人检测 | 从正确的国家/地区退出,并将Cookie保留到下一次会话 |
软阻塞值得特别关注,因为这是唯一一种表面上不像是失败的情况。如果抓取工具将 HTTP 200 状态码视为成功,它就会欢天喜地地写入数千条空记录,并报告运行正常。在接受页面之前,请先验证某个已知字段是否存在。
一项能节省一天时间的分诊指令
三个问题,按此顺序。每个问题都能排除一类原因,因此你可以一次只改变一个因素,而不是同时调整四个:
- 是在第一次请求时就失败了吗?
那么说明该地址尚未建立起任何声誉,几乎可以肯定它是无害的。请查看请求头、User-Agent 和 TLS 配置文件。在此处轮换 IP 地址不会产生任何影响,而且只是在浪费资源。
- 还是在取得了一系列成功之后?
那么,客户端的形态没有问题,是你采取的某种措施导致了这种情况。可能是速率、流量或模式。首先应降低每个主机的并发数;只有在确认该地址本身已被消耗后,才进行轮换。
- 在同一网络连接下的浏览器中能正常运行吗?
那么网络路径就没有问题,问题就出在你的客户端上。通过你的客户端请求一个指纹回显服务(例如 tls.peet.ws),并将它的 JA3、JA4 和 HTTP/2 指纹与真实浏览器的指纹进行比较。如果这里出现不匹配,那就是问题的全部答案。
每次只更改一个变量,并将失败的请求作为固定测试用例保留下来。常见的失败模式是同时更换代理、User-Agent 和客户端库,结果发现能正常工作,却始终无法确定究竟是哪一个起到了作用——因此下一次测试又得从头开始。
针对具体原因的解决方案
根据证据所指向的内容进行分类,并如实说明代理指标究竟针对其中哪一项:
- IP声誉、速率限制、地理限制 — 这确实是代理的职责。对于目标方而言,封禁位于CGNAT后方的运营商IP成本很高,因为该IP背后有数千名真实用户,而且只要从正确的国家连接,就能绕过那些看似针对机器人的地理限制。
- TLS 或 HTTP/2 指纹 — 这完全不是代理问题。请使用能够模拟真实浏览器握手过程的客户端(例如 curl_cffi),或者直接调用真实的浏览器。仅凭一个地址无法让 urllib3 像 Chrome 那样进行握手。
- 无头泄漏 — navigator.webdriver、缺失的插件界面以及 SwiftShader WebGL 渲染器,这些特征表明这是一个自动化浏览器,无论它从何处退出。
- 矛盾 — 英国的IP地址与美国/纽约时区相匹配,或者数据中心IP范围内的移动设备User-Agent。各层之间的一致性比任何单层的安全强度更为重要。
- 图案 — 完全均匀的间隔和任何人都无法维持的速率都会被直接测得。没有任何代理能掩盖访问模式;唯有改变该模式才能做到。
在干净的运营商IP上进行测试的好处在于它能排除哪些可能性。如果一个新的移动IP地址表现得与旧的完全一样,那么问题就从来不是地址本身,而你刚刚排除了清单上最昂贵的一项。该 立柱导轨 更深入地介绍了指纹层,并且该 最佳实践指南 涵盖了在问题尚未发生前就将其扼杀在萌芽状态的费率管控措施。
针对干净的运营商IP进行测试
PXM2实时节点——选择您希望目标用户看到请求来自的国家/地区,即可获得一个专属的4G/5G IP地址,该地址提供无限带宽和轮询功能:
法国
印度
新加坡
常见问题解答
为什么在抓取数据时会收到403错误?
如果立即收到一个仅包含状态码403的响应(无正文或仅包含微小的JSON错误),这几乎总是出于防机器人考虑,而非权限问题。如果这种情况发生在首次请求时,请检查您的请求头和TLS指纹;如果是在连续成功请求后才开始出现,请检查您的请求速率。 这两者的解决方法截然不同,判断错误可能会让你白白浪费一整天的时间。
我该如何判断是哪种反机器人系统在屏蔽我?
请查看响应内容,而非状态行。Cloudflare 会设置 cf-ray 头和 cloudflare 服务器头,且其自身的错误代码(如 1020 和 1015)会出现在响应正文中。DataDome 会设置 x-datadome 头,并显示带有品牌标识的验证页面。 PerimeterX(现更名为 HUMAN)会设置一个 _px3 Cookie 并引用 px-captcha。每种情况都意味着需要采取不同的解决方法。
403 和 429 之间有什么区别?
带有 Retry-After 头部的 429 状态码是合理的速率限制:服务器正在告诉你当前的访问频率不合适,并告知了何时可以再次尝试。请遵守这一规定。403 状态码则表示完全拒绝为你提供服务,此时若仅轮换 IP 地址而不做其他任何调整,通常只会白白耗尽 IP 地址配额。
为什么该页面在我的浏览器中能加载,但在 Python 中却无法加载?
因为您的客户端不会像浏览器那样进行握手。加密套件顺序、TLS 扩展顺序和 HTTP/2 设置共同构成一个 JA3 或 JA4 指纹,该指纹会与已知的浏览器值进行比对。 您可以通过客户端请求指纹回显服务(例如 tls.peet.ws)并进行比对来确认这一点。解决方法是使用能够模拟真实 TLS 配置文件或真实浏览器的客户端——而不是使用其他代理。
移动代理能解决所有数据抓取被封的问题吗?
不,这一点值得明确说明。 代理服务器可以修复IP声誉、解除针对特定地址的速率限制,并绕过地理封锁。但对于TLS指纹不匹配、无头浏览器暴露自身身份、请求头缺失或矛盾,以及人类无法模拟的访问模式,它都无能为力。如果一个“干净”的移动IP也无济于事,那么问题根源就在上述列表之中。
相关移动代理指南
一旦弄清楚是什么在阻碍你,该主题群的其余部分就会详细介绍解决方法。