网页抓取验证码:为什么会出现,以及如何应对
当网站判定某个请求看起来像自动化程序时,抓取过程中就会出现验证码。常见的触发因素包括:短时间内请求过多、IP 地址信誉不佳、缺少浏览器信号,或者访问了网站保护得比其他页面更严密的页面。应对的做法分三步,并且按这个顺序进行:减少触发因素,在代码中检测验证码,然后识别你无法避免的验证码。本指南涵盖每一步,并指向其他指南了解更多内容。
网站为什么会向抓取器显示验证码
网站在页面被请求的那一刻,几乎无法区分真人和脚本,因此它会观察行为模式。抓取器往往因为以下原因而显得突出:
- 发送请求的速度比任何人点击都快;
- 同一路径被重复访问,中间没有停顿;
- 请求来自数据中心地址,而不是家庭网络;
- 发送的请求头与常见浏览器不匹配;
- 请求之间没有保留 Cookie 或会话状态。
任何一个因素都可能足以触发验证码。验证码是网站在继续提供页面之前,要求一次类似人类操作的步骤的方式。减少这些模式通常就能减少验证码,这比识别它们更划算。
在代码中检测验证码
在识别任何东西之前,先检查你拿到的页面是否就是验证码页面。一个简单的测试会查找控件的标记并读取 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 即将支持。如果你的目标使用了其中某种,验证码指南会说明一般性的选择,但不要在尚未上线的识别方案上构建生产流程。
针对每个被拦截页面的决策流程
当你的抓取器遇到验证码时,一个简单的决策顺序能让任务保持合规,并降低请求量:
- 有没有可以替代的数据源? 如果某个 API、数据源或导出文件能覆盖你需要的字段,就切换过去,并停止请求该页面。
- robots.txt 是否允许该路径? 如果不允许,就跳过它。不要为一个被要求避开的页面去识别验证码。
- 是不是发送得太多、太快? 暂停更长时间,降低请求频率,稍后再检查。很多验证码会在放慢速度之后消失。
- 这是上线的验证码类型吗? 如果是 PopularCaptcha,就可以应用本指南中的识别方法。如果是即将支持的类型,请暂停任务,并持续关注上线通知。
- 该页面是你获准自动化的吗? 如果答案不清楚,请先询问网站所有者,然后再继续。
第四步是最常被忽略的一步。只有验证码类型受支持,识别器才有用。如果一个任务反复尝试一种不受支持的类型,只会浪费时间和请求。
在任务中处理验证码,而不是在循环中
把识别放在需要 token 的代码路径内,这样任务就可以记录每次验证码的情况,在某个页面持续失败时停止,然后继续前进。一个不断请求验证码页面的无限循环,是让网站防火墙永久封禁你的地址最快的方式。
监控失败情况
按 URL 和一天中的时间段,统计返回验证码的页面数量。如果验证码只出现在网站的某一板块,或者只在发送了一定数量的请求之后才出现,这就能告诉你触发因素在哪里。这些信息比更快的识别器更有用,因为它告诉你应该改变什么。
不应该做的事
- 不要为了规避网站的限制而轮换大量 IP 地址。那是一种规避行为,会把一个放慢速度的请求变成一场对抗。
- 不要使用你无权使用的凭据,抓取需要登录的页面。
- 不要为了创建账户、发布垃圾信息或抢购限量商品而识别验证码。
负责任地抓取
- 在开始之前阅读网站的
robots.txt和服务条款。遵守它们规定的禁止路径和抓取延迟。 - 在 User-Agent 中诚实地标明你的机器人身份,并附上可以联系到你的方式。
- 保持较低的请求频率。验证码往往是网站在请求你放慢速度。
- 如果网站要求你停止,就停止。不要绕过一个你被告知要尊重的封锁。
- 依据适用的隐私规则处理个人数据,并且只收集你需要的内容。