
Lucas Mitchell
Automation Engineer
已发表 Oct 22, 2026
已更新 Oct 22, 2026 · 最小阅读量

一个 Patchright 脚本也许能顺利导航、找到表单,然后停在 reCAPTCHA 组件上。更换浏览器库本身并不会产生组件和应用所需的应答。此时你需要一个 CAPTCHA 求解器,并检查应用是否接受了该结果。
本 Patchright CAPTCHA 求解教程通过官方 Core SDK 将一个 Python 浏览器会话连接到 CapSolver。关键细节在于页面的 JavaScript 环境:读取可见 DOM 与读取 reCAPTCHA 所属的页面配置,是两种不同的操作。下面的示例正确区分了这两者,在只打开一个页面的前提下完成检测,并在本地开发用夹具中验证结果。仅在你拥有或获得授权去自动化的页面中使用这种方法。
Patchright 是社区维护的 Playwright 分支,在 Python 中提供类似的自动化接口。官方 Python 仓库 记录了其对 Chromium 的支持以及作为 Playwright 替代导入的用法。Patchright 不支持 Firefox 和 WebKit。
开发者使用 Patchright 来控制页面、与元素交互以及运行浏览器工作流。当受支持的 CAPTCHA 阻止一个已获授权的工作流提交表单或到达预期结果时,就需要引入求解器。如果你的页面已经无障碍访问,就没有理由发起付费求解请求。
集成有三个彼此独立的职责。Patchright 负责导航和页面生命周期;求解器读取受支持的挑战输入并请求解答;你的应用工作流决定表单或后续页面是否真正成功。CAPTCHA 术语表 解释了这种职责分离背后的验证机制。
在对自有应用进行日常测试时,优先使用 CAPTCHA 厂商提供的开发设置。付费求解集成检查,与测试普通表单校验是否有效,是两件不同的事。
reCAPTCHA 检测可能需要组件在页面主 JavaScript 环境中创建的配置。Patchright 文档中的 evaluate() 参数 isolated_context 默认值为 True;因此,即使组件可见,页面拥有的 JavaScript 全局对象也可能在常规执行中不可见。
在本指南使用的受控示例中,使用默认执行环境看不到 window.___grecaptcha_cfg,而将 isolated_context=False 时则可以看到。对于此类 reCAPTCHA 路径,SDK 需要访问该页面状态。出现超时或空检测结果时,应先检查上下文,再考虑更改 site key 或重复发起求解请求。
下面的适配器会将 SDK 的执行转发到页面主环境。它不会修改 Patchright 的安装文件,也不会全局切换所有浏览器操作的执行环境。导航和普通定位器依旧使用 raw_page;只有传给 SDK 的 page 对象才使用该封装。将它视为对下文列出版本的一个已测试集成示例,而不是官方 Patchright 合作或通用兼容性的声明。
示例使用 Python 3.12、Patchright 1.64.1 和 capsolver-core 0.1.1。请在隔离环境中安装这些包,并安装 Patchright 的 Chromium 运行时。在进行环境检查时固定这些版本,避免升级包后行为在不知情的情况下发生变化。
python3 -m venv .venv
source .venv/bin/activate
python -m pip install "patchright==1.64.1" "capsolver-core==0.1.1"
python -m patchright install chromium
检测示例本身不需要 CapSolver API key。实际求解则需要你自己的有效 key 和足够的账户资源。使用文档中的 create_capsolver(api_key=...) 选项来配置客户端,并将密钥保存在应用的机密配置中。Core SDK 指南 记录了客户端创建、检测、求解及结果字段。
下面的环境检查是在使用 Google 公共 reCAPTCHA 测试 key 的本地页面上执行的。本指南未执行付费求解、token 回填以及应用对已求解 token 的接受检查。不要将该夹具用作生产环境成功率测试。
该环境检查会打开一个本地夹具页面,等待测试组件初始化,并打印官方 SDK 返回的 CAPTCHA 参数。将其保存为 patchright_sdk_check.py,并在上述环境中使用 Python 运行。
本地 URL 通过浏览器路由提供,因此不需要单独的 Web 服务器。组件脚本仍从 Google 加载,因此需要网络访问。使用的公开 site key 来自 Google reCAPTCHA 测试说明;它是开发用 key,而非私密凭证。
import asyncio
import json
from capsolver_core import create_capsolver
from patchright.async_api import async_playwright
TEST_URL = "http://127.0.0.1:8765/"
HTML = """<!doctype html><html><head><title>CAPTCHA integration check</title></head>
<body><h1>Owned development page</h1>
<div class="g-recaptcha" data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"></div>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</body></html>"""
class MainWorldPage:
def __init__(self, page):
self._page = page
@property
def url(self):
return self._page.url
async def evaluate(self, expression, arg=None):
return await self._page.evaluate(expression, arg, isolated_context=False)
async def wait_for_selector(self, selector, **kwargs):
return await self._page.wait_for_selector(selector, **kwargs)
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
try:
raw_page = await browser.new_page()
await raw_page.route(
TEST_URL, lambda route: route.fulfill(content_type="text/html", body=HTML)
)
await raw_page.goto(TEST_URL)
page = MainWorldPage(raw_page)
for _ in range(60):
ready = await page.evaluate(
"() => !!window.___grecaptcha_cfg && "
"Object.keys(window.___grecaptcha_cfg.clients || {}).length > 0"
)
if ready:
break
await asyncio.sleep(0.5)
else:
raise RuntimeError("Test widget did not initialize")
async with create_capsolver() as cap:
infos = await cap.get_captcha_info(page)
result = [{"type": info.type.value, "url": info.website_url,
"site_key": info.website_key} for info in infos]
print(json.dumps({"captcha_parameters": result}))
assert result and result[0]["type"] == "reCaptchaV2"
finally:
await browser.close()
if __name__ == "__main__":
asyncio.run(main())
一次成功的运行会返回一项数据,其中 type 为 reCaptchaV2,包含本地页面 URL 和公开测试 site key。这表明 Patchright 成功打开了页面,并且 SDK 能通过适配器读取已初始化的组件。该结果不包含求解后的 token,也无法证明生产表单会接受它。
浏览器会在 finally 中被关闭,包括组件加载或检测失败的情况。SDK 客户端也会退出其异步上下文。将这一清理逻辑保留到更长脚本中,尤其在挑战导致异常时。
兑换你的 CapSolver 奖励码
立刻提升你的自动化预算!
在为 CapSolver 账户充值时使用奖励码 CAP26,每次充值都可额外获得 5% 奖励,且无次数上限。
现在就前往你的 CapSolver 控制面板 进行兑换。
求解应当放在浏览器和 SDK 活动上下文之内,并在页面关闭或导航离开之前完成。在你已获授权的应用页面上,使用你的 key 创建 SDK 客户端,按照上文方式封装当前 Patchright 页面,并调用官方的浏览器模式接口。
下面这一行是未经修改的官方 SDK 调用。它需要配置好的 API key;在本 Patchright 适配示例中未对付费执行进行测试。请在 cap 和封装后的 page 仍在作用域内时调用,而不是作为独立脚本运行。
results = await cap.solve_on_page(page)
在继续后续逻辑前检查返回的各项。SDK 提供 error、solution 和 filled 字段,便于区分失败尝试、已返回解答以及 token 是否已填回表单。若缺少所需解答,或相关结果报告错误,就不要提交表单。
对于 reCAPTCHA v2,官方任务参数文档 说明了页面 URL、site key 与任务类型之间的关系。确认检测到的挑战与目标页面匹配。仅仅因为一个 key 格式正确,并不意味着从其他环境或旧页面状态复制来的 key 就是有用输入。
应用成功是求解和回填之后的另一项检查。你的工作流仍可能需要提交表单或等待页面特定的回调。Google 的 服务端验证说明 解释了应用必须验证响应的原因。为自己的应用定义明确的成功信号,例如确认消息或预期结果区域,当该信号未出现时就应停止流程。
不要把 HTTP 响应、一个 token 字符串或 filled=True 视为整个浏览器任务成功的证明。如果页面拒绝了该响应,请保留有用的错误摘要并排查原因,再决定是否重试。关于 CAPTCHA token 和 cookie 的指南 为理解求解器输出提供了背景。
排查应从第一个失败步骤开始:页面加载、组件初始化、上下文访问、求解或应用接受。
| 症状 | 首先检查 |
|---|---|
| 测试组件始终未初始化 | 确认浏览器能加载 Google 的脚本,且组件存在于目标页面上。 |
| 组件可见但检测结果为空 | 确认 SDK 接收到的是封装过的页面对象,并检查在你固定版本上主环境访问是否正常。 |
| SDK 返回错误 | 阅读文档中对应错误说明,核对凭证和任务输入,避免重复发送同样的无效请求。 |
| 存在解答但 fill-back 为 false | 检查受支持挑战的处理方式以及在提交前的页面状态。 |
| 填回成功但工作流卡住 | 检查表单 action、回调行为以及应用本身的拒绝或成功信号。 |
从一个页面、一次尝试开始。只有在理解哪些失败是暂时性的之后,才添加有上限的重试逻辑。在导航之后重用旧结果,可能会把解答与错误的页面状态关联;而盲目重试则会增加成本,却无法修复最初的问题。
在升级自动化任务前,应将 Patchright 和 SDK 的改动一起进行测试。熟悉的 API 并不意味着对每个 Playwright 扩展或 SDK 都有完全一致的执行行为。保留这个小型检测脚本作为兼容性测试,并在自己的环境中单独运行带凭证的求解加应用检查,确认无误再投入生产。
一个有价值的 Patchright 集成,需要把当前浏览器页面、受支持的 CAPTCHA 任务和可观测的应用结果连接起来。先验证页面上下文访问,再使用你自己的凭证验证付费求解,最后检查预期的浏览器动作是否真正完成。这样可以让 CapSolver 专注于 CAPTCHA 步骤,而不把每个导航问题都误认为是它能解决的挑战。
当你在获授权的 Patchright 工作流中需要受支持的 CAPTCHA 响应时,可以考虑使用 CapSolver。确保只在确实出现挑战时才发起求解,并在扩展工作负载前先验证结果。
问:Patchright 本身会自动解决 reCAPTCHA 吗?
不会。浏览器控制并不会提供 reCAPTCHA 解答 token。如果你的授权页面仍然需要 CAPTCHA 响应,请添加受支持的求解步骤,或使用应用的开发测试配置。
问:为什么可见的组件会产生空检测结果?
脚本可能正在读取与组件初始化配置不同的 JavaScript 环境。在认定 site key 缺失之前,先检查组件初始化以及主环境的访问情况。
问:这是官方的 Patchright 集成吗?
不是。这是一个使用官方 Patchright 包和 CapSolver SDK 的集成示例。自定义适配器和检测脚本只在文中列出的版本上执行过;未测试付费求解。
问:本地环境检查需要 API key 吗?
不需要。环境检查仅读取公开开发组件的参数。单独的求解调用则需要有效 API key 和账户资源。
问:我能在这个示例中使用 Firefox 或 WebKit 吗?
否。Patchright 文档支持基于 Chromium 的浏览器。此示例会启动其 Chromium 运行时。
问:令牌回填是否意味着表单已通过验证?
不是。令牌回填和申请被接受是两个独立的结果。在继续你的工作流之前,请在执行所需操作后检查申请的响应。

Lucas Mitchell
Automation Engineer
Helping browser automation recover and continue.
关于作者