CAPSOLVER
博客
如何将 CapSolver 与 Composio AI 浏览器自动化集成

如何将 CapSolver 与 Composio AI 浏览器自动化集成

Logo of CapSolver

Ethan Collins

How to use CapSolver

17-Aug-2026

TL;DR

  • 将完整的Playwright页面工作流——打开、解决、应用结果、提交和验证——封装到一个Composio自定义工具中,该工具可被OpenAI代理SDK通过自然语言指令调用。
  • 该示例涵盖两种挑战类型:返回令牌的reCAPTCHA v2和通过ImageToTextTask识别的图片CAPTCHA,它们作为单独的工具注册到一个会话中。
  • 工作流直接连接到官方OpenAI API,并使用Playwright进行浏览器自动化。
  • 两种常见的集成失败情况是Composio密钥缺少sessions: write权限(返回403)和工具的第一个参数缺少Pydantic BaseModel注解(触发ValidationError)。

1. 简介

本指南将CapSolverComposio集成,作为完成reCAPTCHA v2工作流的代理工具。该工具不仅返回令牌,还会运行完整的页面序列,并将页面的实际响应视为成功条件。OpenAI代理SDK决定何时调用该工具,而Playwright浏览器自动化保留用于提交和验证的页面上下文。

仅在合法、合理、负责任且获得用户授权的工作流中使用此模式。技术能力不意味着有权访问私有、受限、敏感或未经授权的数据;部署前请查阅相关AI自动化指南

工作流:

text 复制代码
运行脚本
  -> OpenAI代理SDK决定调用哪个工具
  -> Composio自定义工具: complete_recaptcha_v2
       -> Playwright打开页面
       -> capsolver.solve(...)返回gRecaptchaResponse
       -> 将令牌应用到g-recaptcha-response
       -> Playwright提交并等待页面
       -> 读取页面并判断是否通过
  -> 工具返回 {"accepted": ..., "message": ...}
  -> 代理报告accepted的结果

各组件职责如下:

组件 职责
OpenAI代理SDK 理解自然语言指令,决定何时调用工具,执行工具并整理响应
Composio 将标准Python函数注册为代理可调用的工具
Playwright 打开页面,应用结果,提交表单并读取结果页面状态
CapSolver SDK 通过单次solve()调用返回CAPTCHA结果

2. 快速开始

bash 复制代码
pip install composio composio-openai-agents openai-agents capsolver pydantic playwright
playwright install chromium

每个依赖项都有特定作用:

目的
composio 创建会话并注册或加载自定义工具
composio-openai-agents 将Composio工具转换为OpenAI代理可调用的对象
openai-agents 提供Agent、Runner和SQLite多轮记忆
capsolver 提供官方SDK并通过solve()返回结果
pydantic 定义工具输入模式
playwright 打开页面,应用结果,提交表单并读取响应

3. 配置

python 复制代码
# API密钥。
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..."          # 您的官方OpenAI API密钥。
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY   # OpenAI SDK从环境变量中读取密钥。

# 配置CapSolver和Composio。
capsolver.api_key = "CAP-..."
composio = Composio(
    api_key=COMPOSIO_API_KEY,
    provider=OpenAIAgentsProvider(),
)

配置说明: OPENAI_API_KEY必须写入环境变量,因为SDK从那里读取;OpenAIAgentsProvider使session.tools()返回的工具与Agent兼容;Composio密钥需要sessions: write权限,否则会话创建返回403。

当前Composio OpenAI提供者OpenAI代理SDK参考文档解释了此配置使用的提供者和代理边界。

领取您的CapSolver优惠码

立即提升您的自动化预算!
在充值CapSolver账户时使用优惠码CAP26,每次充值可获得5%的额外奖励——无限制。
现在在您的CapSolver仪表板中领取
优惠码

4. 核心实现

停止条件: 仅当页面包含预期的成功文本时,工具才报告成功。finally块在成功和失败路径中都关闭浏览器。

python 复制代码
import os
from typing import List, cast
import capsolver
from agents import Agent, Runner, SQLiteSession
from composio import Composio
from composio.core.models.custom_tool import CustomTool
from composio.core.models.tool_router import ToolRouterExperimentalConfig
from composio_openai_agents import OpenAIAgentsProvider
from playwright.sync_api import sync_playwright
from pydantic import BaseModel, Field

# API密钥。
COMPOSIO_API_KEY = "ak_..."
OPENAI_API_KEY = "sk-..."          # 您的官方OpenAI API密钥。
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

# 配置CapSolver和Composio。
capsolver.api_key = "CAP-..."
composio = Composio(
    api_key=COMPOSIO_API_KEY,
    provider=OpenAIAgentsProvider(),
)


# 自定义工具的输入模式;Composio要求此处为Pydantic BaseModel。
class CompleteRecaptchaInput(BaseModel):
    target_url: str = Field(
        default="https://www.google.com/recaptcha/api2/demo",
        description="包含reCAPTCHA v2演示的页面URL",
    )
    website_key: str = Field(
        default="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
        description="当前页面的reCAPTCHA v2网站密钥",
    )


# 将整个流程注册为一个Composio工具,代理可调用。
# 第一个参数的类型注解是Composio推断模式所必需的。
@composio.experimental.tool(preload=True)
def complete_recaptcha_v2(input: CompleteRecaptchaInput, _ctx):
    """使用Playwright打开页面,解决reCAPTCHA v2,提交并验证。"""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)  # 设置headless=True以隐藏窗口。
        page = browser.new_page()
        try:
            page.goto(input.target_url)
            # 请求CapSolver解决reCAPTCHA v2挑战。
            solution = capsolver.solve(
                {
                    "type": "ReCaptchaV2TaskProxyLess",
                    "websiteURL": input.target_url,
                    "websiteKey": input.website_key,
                }
            )
            token = solution.get("gRecaptchaResponse")
            page.evaluate(
                """
                (token) => {
                    const textarea = document.getElementById('g-recaptcha-response');
                    if (textarea) {
                        textarea.value = token;
                    }
                }
                """,
                token,
            )
            page.click("#recaptcha-demo-submit")
            page.wait_for_load_state("networkidle")
            result_page = page.content()
            # 仅当页面实际显示成功文本时才视为成功
            accepted = "Verification Success" in result_page
            return {
                "accepted": accepted,
                "message": (
                    "Verification Success"
                    if accepted
                    else "页面未报告Verification Success"
                ),
            }
        finally:
            browser.close()
def main():
    experimental: ToolRouterExperimentalConfig = {
        "custom_tools": cast(List[CustomTool], [complete_recaptcha_v2]),
    }
    session = composio.sessions.create(
        user_id="playwright-recaptcha-demo-user",
        experimental=experimental,
        sandbox={"enable": False},  # 在此进程中运行工具,而非沙箱。
    )
    agent = Agent(
        name="Playwright reCAPTCHA助手",
        instructions=(
            "当用户要求运行演示时,使用默认值调用complete_recaptcha_v2 "
            "。仅当accepted为true时报告成功。"
        ),
        model="gpt-5.2",
        tools=session.tools(),
    )
    # 多轮对话的内存
    memory = SQLiteSession("conversation")
    print("Composio + Playwright reCAPTCHA v2演示正在运行...")
    user_input = (
        "现在使用默认的target_url和website_key调用complete_recaptcha_v2 "
        "。不要询问确认。"
    )
    result = Runner.run_sync(
        starting_agent=agent,
        input=user_input,
        session=memory,
    )
    print(f"助手: {result.final_output}\n")
if __name__ == "__main__":
    main()

5. 使用ImageToTextTask的图片CAPTCHA识别

相同模式可以处理标准图片文本CAPTCHA,通过注册第二个Composio工具。此示例使用BotDetect CAPTCHA演示:图片元素为#demoCaptcha_CaptchaImage,输入为#captchaCode,验证按钮为#validateCaptchaButton

在浏览器中检查BotDetect CAPTCHA图片、输入和验证元素

ImageToTextTask请求通过body提交Base64图像。与基于令牌的任务不同,此任务直接返回识别文本,无需单独轮询循环。

5.1 将图片读取为Base64

python 复制代码
image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
if not image_src or "," not in image_src:
    raise RuntimeError("未找到有效的CAPTCHA图片Data URL")
base64_image = image_src.split(",", 1)[1]  # 去除"data:image/...;base64,"前缀。

5.2 自定义工具实现

python 复制代码
class CompleteImageCaptchaInput(BaseModel):
    target_url: str = Field(
        default="https://captcha.com/demos/features/captcha-demo.aspx",
        description="图片CAPTCHA演示页面URL",
    )
    module: str = Field(
        default="common",
        description="CapSolver ImageToTextTask识别模块",
    )

@composio.experimental.tool(preload=True)
def complete_image_captcha(input: CompleteImageCaptchaInput, _ctx):
    """使用Playwright打开页面,识别图片CAPTCHA,提交并验证。"""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        try:
            page.goto(input.target_url)
            page.wait_for_selector("#demoCaptcha_CaptchaImage", state="visible")

            # 图片src已经是数据URL;去除前缀以获取Base64。
            image_src = page.locator("#demoCaptcha_CaptchaImage").get_attribute("src")
            if not image_src or "," not in image_src:
                raise RuntimeError("未找到有效的CAPTCHA图片Data URL")
            base64_image = image_src.split(",", 1)[1]
            solution = capsolver.solve(
                {
                    "type": "ImageToTextTask",
                    "websiteURL": input.target_url,
                    "module": input.module,
                    "body": base64_image,
                }
            )
            captcha_text = solution.get("text")
            if not isinstance(captcha_text, str) or not captcha_text:
                raise RuntimeError("CapSolver未返回识别文本")
            page.fill("#captchaCode", captcha_text)      # 填写识别文本。
            page.click("#validateCaptchaButton")
            page.wait_for_load_state("networkidle")
            result_page = page.content()
            # 演示页面在成功时显示"Correct!",失败时显示"Incorrect!"。
            accepted = "Correct!" in result_page
            return {
                "accepted": accepted,
                "recognized_text": captcha_text,
                "message": "Correct!" if accepted else "页面未报告Correct!",
            }
        finally:
            browser.close()

流程概述:

text 复制代码
Playwright打开CAPTCHA页面
  -> 等待#demoCaptcha_CaptchaImage可见
  -> 读取src(数据URL)并去除前缀以获取Base64
  -> capsolver.solve(ImageToTextTask)返回文本
  -> page.fill将结果写入#captchaCode
  -> page.click激活#validateCaptchaButton
  -> page.content检查Correct!或Incorrect!
  -> finally关闭浏览器

5.3 选择适当的识别模型

module参数是可选的,默认为common。如果CAPTCHA仅包含数字,请使用number。特殊样式可在适当情况下使用文档记录的独立模型。

CapSolver ImageToTextTask独立模型示例和准确率

例如,以下源代码可直接用于纯数字识别:

python 复制代码
solution = capsolver.solve({
    "type": "ImageToTextTask",
    "module": "number",
    "images": [base64_image],
})

answers = solution["answers"]

number模型支持一次提交多个图像,images最多可包含九个Base64字符串。支持的模型名称和用例列在上述CapSolver ImageToTextTask页面中。

6. 故障排除

6.1 第一个工具参数必须是BaseModel

text 复制代码
experimental.tool: "complete_recaptcha_v2"的第一个参数必须
标注为Pydantic BaseModel子类。得到: <class 'inspect._empty'>

Composio从第一个参数的类型注解推断输入模式,因此input: CompleteRecaptchaInput不能省略。这是一个功能注解,而不是可选类型提示。Pydantic BaseModel参考文档描述了用于模式的模型类型。

6.2 Composio 返回 403

会话创建可能会返回以下错误:

text 复制代码
403 APIKey_InsufficientPermissions
此路由需要 "sessions" 写入权限

原因是 composio.sessions.create() 需要项目密钥的写入权限来处理会话,而当前密钥只有只读权限。密钥有效,但其作用域不足,因此返回 403 而不是 401。

解决步骤:

  1. 打开 Composio 仪表板,进入相关项目的 API 密钥设置。
  2. 将当前密钥的 sessions 权限从读取更改为写入。
  3. 如果无法编辑权限,请创建一个带有 sessions: write 的新密钥,并替换脚本顶部的 COMPOSIO_API_KEY
  4. 再次运行脚本。若交互流程不再出现 403 错误,说明权限已生效。

7. 结论与行动呼吁

此集成的核心是一个打包为 Composio 工具的完整业务流程:

text 复制代码
Composio 工具 = Playwright 页面操作 + CapSolver 结果 + 页面状态验证
  • Composio 将 Python 函数转换为代理可调用的自定义工具,并处理模式推断和执行。
  • Playwright 打开页面,应用结果,提交表单并读取最终状态。
  • CapSolver 为此特定工作流处理 reCAPTCHA v2 和图像 CAPTCHA 识别。

仅在您拥有或授权自动化的页面和进程中运行示例。使用环境变量或密钥管理器处理凭证,在页面未达到预期业务状态时停止操作,并审查重复失败情况而非无限重试。

对于需要专注 CAPTCHA 基础设施层的授权 Composio 代理工作流,使用您控制的页面测试 CapSolver,并在每次求解后验证应用结果。

常见问题

Composio 在此集成中处理什么?

Composio 将 Python 函数注册为代理可调用的自定义工具,创建会话,暴露工具模式,并从 OpenAI 代理路由执行。

为什么第一个工具参数必须是 Pydantic BaseModel?

Composio 使用该注解来推断工具的输入模式。省略它会阻止模式构建,并在浏览器工作流开始前引发验证错误。

reCAPTCHA v2 工具在 CapSolver 返回令牌后会停止吗?

不会。代码保持不变,应用令牌,提交演示表单,读取结果 HTML,并仅在页面包含预期的“Verification Success”文本时报告成功。

ImageToTextTask 是否需要单独的轮询循环?

不需要。在此工作流中,官方 SDK 会直接返回识别文本。工具随后填写输入,提交页面,并以“Correct!”作为停止条件进行检查。

此工作流能否用于任何网站?

不能。仅用于合法、合理、负责任且用户授权的自动化。尊重网站条款、适用法律、速率限制和数据最小化要求。

合规声明: 本博客提供的信息仅供参考。CapSolver 致力于遵守所有适用的法律和法规。严禁以非法、欺诈或滥用活动使用 CapSolver 网络,任何此类行为将受到调查。我们的验证码解决方案在确保 100% 合规的同时,帮助解决公共数据爬取过程中的验证码难题。我们鼓励负责任地使用我们的服务。如需更多信息,请访问我们的服务条款和隐私政策。

更多