Scarnox · Blog

网页抓取验证码:为什么会出现,以及如何应对

当网站判定某个请求看起来像自动化程序时,抓取过程中就会出现验证码。常见的触发因素包括:短时间内请求过多、IP 地址信誉不佳、缺少浏览器信号,或者访问了网站保护得比其他页面更严密的页面。应对的做法分三步,并且按这个顺序进行:减少触发因素,在代码中检测验证码,然后识别你无法避免的验证码。本指南涵盖每一步,并指向其他指南了解更多内容。

网站为什么会向抓取器显示验证码

网站在页面被请求的那一刻,几乎无法区分真人和脚本,因此它会观察行为模式。抓取器往往因为以下原因而显得突出:

任何一个因素都可能足以触发验证码。验证码是网站在继续提供页面之前,要求一次类似人类操作的步骤的方式。减少这些模式通常就能减少验证码,这比识别它们更划算。

在代码中检测验证码

在识别任何东西之前,先检查你拿到的页面是否就是验证码页面。一个简单的测试会查找控件的标记并读取 sitekey:

import re
import requests

SITEKEY_RE = re.compile(r'data-sitekey="([0-9a-f-]{36})"')

def fetch(url: str) -> dict:
    resp = requests.get(
        url,
        timeout=30,
        headers={"User-Agent": "ExampleBot/1.0 (+https://example.com/bot)"},
    )
    html = resp.text
    if "h-captcha" in html or "g-recaptcha" in html:
        match = SITEKEY_RE.search(html)
        return {"captcha": True, "sitekey": match.group(1) if match else None, "html": html}
    return {"captcha": False, "sitekey": None, "html": html}

page = fetch("https://example.com/search?q=shoes")
if page["captcha"]:
    print("captcha found, sitekey:", page["sitekey"])

h-captcha 和 g-recaptcha 这两个字符串只是页面所用的标记,因此这种检测只是一个信号,而不是保证。如果没有找到 sitekey,请参阅如何查找验证码 sitekey。

无法避免时再识别

当页面上有 PopularCaptcha 控件,并且你拿到了它的 sitekey 时,你可以向 Scarnox API 发送一次 POST 请求获取 token,然后把它提交到 h-captcha-response 字段中。包含错误处理的完整函数,请参阅用一次请求从 Python 识别验证码。Token 在大约两分钟后过期,请立即使用。时间细节见验证码 token 过期。

Scarnox 目前的实时支持包括 PopularCaptcha,无代理以及使用你自己的代理两种方式。reCAPTCHA v2 和 v3、Cloudflare Turnstile、GeeTest、AWS WAF 和 Arkose 即将支持。如果你的目标使用了其中某种,验证码指南会说明一般性的选择,但不要在尚未上线的识别方案上构建生产流程。

针对每个被拦截页面的决策流程

当你的抓取器遇到验证码时,一个简单的决策顺序能让任务保持合规,并降低请求量:

  1. 有没有可以替代的数据源? 如果某个 API、数据源或导出文件能覆盖你需要的字段,就切换过去,并停止请求该页面。
  2. robots.txt 是否允许该路径? 如果不允许,就跳过它。不要为一个被要求避开的页面去识别验证码。
  3. 是不是发送得太多、太快? 暂停更长时间,降低请求频率,稍后再检查。很多验证码会在放慢速度之后消失。
  4. 这是上线的验证码类型吗? 如果是 PopularCaptcha,就可以应用本指南中的识别方法。如果是即将支持的类型,请暂停任务,并持续关注上线通知。
  5. 该页面是你获准自动化的吗? 如果答案不清楚,请先询问网站所有者,然后再继续。

第四步是最常被忽略的一步。只有验证码类型受支持,识别器才有用。如果一个任务反复尝试一种不受支持的类型,只会浪费时间和请求。

在任务中处理验证码,而不是在循环中

把识别放在需要 token 的代码路径内,这样任务就可以记录每次验证码的情况,在某个页面持续失败时停止,然后继续前进。一个不断请求验证码页面的无限循环,是让网站防火墙永久封禁你的地址最快的方式。

监控失败情况

按 URL 和一天中的时间段,统计返回验证码的页面数量。如果验证码只出现在网站的某一板块,或者只在发送了一定数量的请求之后才出现,这就能告诉你触发因素在哪里。这些信息比更快的识别器更有用,因为它告诉你应该改变什么。

不应该做的事

负责任地抓取

下一步