如何用 CapSkip SDK 在 Python 中识别 reCAPTCHA v2

solve recaptcha v2 in python - How to Solve reCAPTCHA v2 in Python With the CapSkip SDK

reCAPTCHA v2 有三种变体,在 Python 中它们是同一个函数,只是使用不同的关键字参数。Checkbox 是最基本的调用,Invisible 和 Enterprise 是标志参数,两者也可同时设置。Python 还是唯一拥有真正独立异步客户端的 CapSkip SDK,一旦你需要同时识别多个验证码,这一点就很重要。

设置

# 需要 Python 3.10 或更高版本。
pip install capskip

CapSkip 在本地识别,因此请先启动桌面应用,然后将客户端指向其设置中显示的端口:

from capskip import CapSkip

solver = CapSkip(
    apiKey="capskip",        # any string when key validation is off
    host="127.0.0.1",
    port=8080,
    recaptchaTimeout=300,    # seconds
)

在生产环境中,改为从环境变量读取这些值:

import os
from capskip import CapSkip

solver = CapSkip(
    apiKey=os.getenv("CAPSKIP_API_KEY", "capskip"),
    host=os.getenv("CAPSKIP_HOST", "127.0.0.1"),
    port=int(os.getenv("CAPSKIP_PORT", "8080")),
)

三种变体

变体需添加的关键字
复选框
隐形invisible=1
Enterpriseenterprise=1
隐形 Enterprise两者
# Checkbox: the baseline call.
result = solver.recaptcha(
    sitekey="6Lc...YOUR_SITEKEY",
    url="https://example.com/login",
)

print(result["code"])   # g-recaptcha-response token

# Invisible.
result = solver.recaptcha(sitekey=sitekey, url=page_url, invisible=1)

# Enterprise, and both together.
result = solver.recaptcha(sitekey=sitekey, url=page_url, enterprise=1)
result = solver.recaptcha(sitekey=sitekey, url=page_url, enterprise=1, invisible=1)

返回值是一个普通的 dict,因此 result["code"] 就是 token。还有 result["captchaId"] 如果你想记录是哪次内部识别产生了它。

正确获取 sitekey 和 URL

sitekey 是 data-sitekey 小组件容器上的属性,或者是传给 grecaptcha.render 在没有容器时——它始终以 6L 开头,且是公开的。

URL 必须是小组件实际渲染所在的页面。传入你的表单处理程序或登录后的重定向,是 token 识别顺利却随后验证失败的最常见原因。

提交 token

import requests

response = requests.post(
    "https://example.com/login",
    data={
        "g-recaptcha-response": result["code"],
        "username": "...",
        "password": "...",
    },
)

token 有效期约两分钟且只能使用一次,因此请在流程中尽可能晚地识别。如果网站把 token 交给 JavaScript 回调而不是表单字段,识别相同但提交方式不同,这一点我们的 reCAPTCHA v2 回调识别工具 页面有说明。

同时识别多个

这就是 Python 与其他 CapSkip SDK 不同之处。 AsyncCapSkip 是真正的异步实现,而非别名,因此它能真正地并行识别:

import asyncio
from capskip import AsyncCapSkip

async def main():
    solver = AsyncCapSkip()
    r1, r2 = await asyncio.gather(
        solver.recaptcha(sitekey=key_a, url="https://a.example.com"),
        solver.recaptcha(sitekey=key_b, url="https://b.example.com"),
    )
    print(r1["code"], r2["code"])

asyncio.run(main())

在 Node.js 和 .NET SDK 中 AsyncCapSkip 只是一个别名,而在 PHP 中它的存在纯粹是为了让移植的代码能编译。Python 是唯一切换到它会真正改变行为的语言。

错误

from capskip import (
    CapSkip, ValidationException, NetworkException,
    ApiException, TimeoutException,
)

try:
    result = solver.recaptcha(sitekey=sitekey, url=page_url)
except ValidationException:
    pass   # missing or malformed arguments
except NetworkException:
    pass   # CapSkip is not running
except ApiException:
    pass   # bad sitekey or pageurl
except TimeoutException:
    pass   # exceeded recaptchaTimeout

这四个都派生自同一个基类,因此 except CapSkipError 如果你更愿意在一处处理失败,它会捕获全部情况。

使用代理

result = solver.recaptcha(
    sitekey=sitekey,
    url=page_url,
    proxy={"type": "HTTPS", "uri": "user:[email protected]:3128"},
)

reCAPTCHA、Turnstile 和 极验 支持代理。图片验证码不支持,因为它们是从图片字节中识别的,永远不会到达目标网站。

常见问题

我需要轮询结果吗?

不需要。SDK 会在内部轮询并返回完成的 token,因此 CAPCHA_NOT_READY 永远不会出现在你的代码里。它在 250 毫秒后开始检查并逐步退避,这通常比手写的循环更快。

对于单次识别,AsyncCapSkip 值得使用吗?

不太需要。它在多个识别相互重叠时才重要,或者当你已经处于事件循环内、阻塞调用会拖住它时才重要。如果只是脚本中的一次识别,同步客户端更简单。

支持哪些 Python 版本?

3.10 及更新版本。该包没有繁重的依赖,因此可以直接接入现有的爬虫或自动化项目,而不会拉入一大堆额外的包。

小结

一个函数、三种变体,通过 invisibleenterprise选择。读取 result["code"],将其作为 g-recaptcha-response,并在 AsyncCapSkip 批量识别时使用它。

更完整的 Python 接口见 Python 验证码识别 页面,其他语言见 reCAPTCHA v2 识别 页面,还有一个 在线 v2 演示 可供测试。CapSkip 采用 验证码识别工具 在你自己的机器上运行。