CAPSOLVER
博客
如何将 CapSolver 集成到 Playwright | 2025年完整指南

如何将CapSolver与Playwright集成 | 2025年完整指南

Logo of CapSolver

Ethan Collins

Pattern Recognition Specialist

04-Sep-2025

什么是Playwright?

Playwright是一个由微软开发的现代浏览器自动化测试框架。它支持Chromium、Firefox和WebKit(分别对应Chrome、Firefox和Safari)的自动化。它提供了一个强大的API用于浏览器控制、元素选择、表单交互、网络拦截等等——使其成为需要与网页进行深度交互的任务的理想选择。

Playwright的核心功能

任何浏览器,任何平台,一个API

  • **跨浏览器:**Playwright支持所有现代渲染引擎,包括Chromium、WebKit和Firefox。
  • **跨平台:**在Windows、Linux和macOS上运行测试——本地或在CI中——无头或有头。
  • **跨语言:**使用TypeScript、JavaScript、Python、.NET或Java使用Playwright API。
  • **测试移动网页:**原生模拟Android版Google Chrome和移动版Safari。相同的渲染引擎在你的桌面和云端运行。

典型用例

  • **抓取动态内容:**提取通过JavaScript渲染的数据。
  • **处理复杂的交互:**适用于需要登录或多步骤工作流程才能访问数据的页面。
  • **从SPA应用中提取数据:**抓取使用Vue或React等框架构建的页面。
  • **自动化测试:**在收集数据的过程中验证页面功能。
  • **无头模式自动化:**在没有GUI的情况下执行所有操作,适用于服务器环境。

Playwright的基本用法

在Node.js中使用Playwright:

bash 复制代码
npm i playwright  
npx playwright install  # 安装所有浏览器(Chromium、Firefox、WebKit)

示例:获取CapSolver的所有博客标题

在下面的示例中,我们使用Playwright导航到CapSolver博客并获取页面上的所有<h5>博客文章标题

javascript 复制代码
const { chromium } = require('playwright');

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
    });

    const [page] = context.pages();
    await page.goto('https://www.capsolver.com/blog/All');

    const h5Titles = await page.evaluate(() => {
        const headings = Array.from(document.querySelectorAll('h5'));
        return headings.map(heading => heading.textContent.trim());
    });

    console.log(h5Titles);
    await context.close();
})();

如何将CapSolver扩展程序与Playwright集成

Playwright功能强大,可以像普通浏览器一样加载浏览器扩展程序。

  1. 官方GitHub下载并解压最新的CapSolver扩展程序ZIP文件。
  2. 使用--disable-extensions-except--load-extension在Playwright启动参数中指定扩展程序路径。
javascript 复制代码
const { chromium } = require('playwright');

const extensionPath = 'path/to/capsolver extension';

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: [
            `--disable-extensions-except=${extensionPath}`,
            `--load-extension=${extensionPath}`,
        ],
    });
    
    const [page] = context.pages();
    await page.goto('https://www.capsolver.com/blog/All');
    await browser.close();
})();

使用CapSolver扩展程序解决reCAPTCHA v2

reCAPTCHA v2/v3Cloudflare TurnstileAWS WAF这样的CAPTCHA类型广泛应用于数千个网站。尽管它们很流行,但这些CAPTCHA通常具有稳定且可检测的DOM结构。这就是CapSolver扩展程序的作用——它自动检测并解决这些CAPTCHA,无需手动交互。

让我们以reCAPTCHA v2为例,演示如何使用Playwright中的CapSolver扩展程序来解决它。
**注意:**除非另有说明,否则以下示例使用点击模式(/assets/config.js -> reCaptchaMode: 'click')。

⚠️ 不要忘记解压扩展程序zip文件并在/assets/config.js中配置你的apiKey

javascript 复制代码
const { chromium } = require('playwright');

// 步骤1:从GitHub下载扩展程序:https://github.com/capsolver/capsolver-browser-extension/releases
// 步骤2:解压扩展程序文件并在/assets/config.js中设置你的apiKey
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: [
            `--disable-extensions-except=${extensionPath}`,
            `--load-extension=${extensionPath}`,
            '--lang=en-US'
        ],
    });

    const [page] = context.pages();
    await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
    await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');

    // 扩展程序将自动检测并解决reCAPTCHA。
    await page.waitForTimeout(15000); // 等待解决
    await page.click('button[type="submit"]');
    await page.waitForTimeout(5000);
    await context.close();
})();

⚠️ CapSolver扩展程序还支持许多有用的配置选项。以下是一些常见的示例(注意:所有配置都在/assets/config.js中设置)

配置选项:solvedCallback

你可能已经注意到,在之前的代码中,我们在加载页面后等待了15秒,然后才点击提交按钮。此延迟是为了给CapSolver扩展程序足够的时间来自动解决reCAPTCHA。但是,这种方法并不理想——有时CAPTCHA解决得更快,在网络状况较差的情况下,它可能需要超过15秒。

这就是solvedCallback的作用。它通过在CAPTCHA解决后触发回调来提供更好的解决方案,通知你验证已完成。你可以在/assets/config.js中配置solvedCallback,方法是定义一个自定义函数名——默认情况下,它是captchaSolvedCallback。然后,在Playwright中使用page.exposeFunction在浏览器上下文中公开此函数。

现在让我们使用这种方法改进之前的代码。

javascript 复制代码
const { chromium } = require('playwright');

const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: [
            `--disable-extensions-except=${extensionPath}`,
            `--load-extension=${extensionPath}`,
            '--lang=en-US'
        ],
    });

    const [page] = context.pages();
    await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
    await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');

    await page.exposeFunction('captchaSolvedCallback', async () => {
        console.log('Captcha solved!');

        const iframe = await page.$('iframe[src*="recaptcha"]');
        if (iframe) {
            const frame = await iframe.contentFrame();
            const finished = await frame.evaluate(() => {
                const element = document.querySelector('.recaptcha-checkbox-border');
                return element && window.getComputedStyle(element).display === 'none';
            });

            if (finished) {
                console.log('Verification completed!');
                await page.click('button[type="submit"]');
                await page.waitForTimeout(3000);
                await context.close();
            } else {
                console.log('Verification not complete. Retrying...');
            }
        }
    });
})();

对于reCAPTCHA v2,有时可能会出现多个图像挑战。因此,在每次挑战之后,我们检查“我不是机器人”复选框是否已选中——如果它消失了,则验证被认为已完成。

配置选项:manualSolving

在之前的示例中,CAPTCHA解决会在页面加载后立即开始。但是,在某些情况下,你可能需要先执行其他任务——例如输入用户名/密码——然后再触发CAPTCHA解决。过早开始可能会导致令牌过期。

要处理此问题,请在/assets/config.js中设置manualSolving: true,这允许你手动触发CAPTCHA解决过程。

有两种方法可以触发解决:

  1. 模拟点击扩展程序中的CapSolver按钮。
  2. 执行:window.postMessage({ type: 'capsolverSolve' });

⚠️ 注意:此功能仅在v1.16.0以上版本的扩展程序中受支持!

示例:

javascript 复制代码
const { chromium } = require('playwright');

const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: [
            `--disable-extensions-except=${extensionPath}`,
            `--load-extension=${extensionPath}`,
            '--lang=en-US'
        ],
    });

    const [page] = context.pages();
    await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
    await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');

    // 模拟填写凭据
    await page.evaluate(() => {
        const inputA = document.querySelector('input[name="ex-a"]');
        inputA.value = 'username';
        const inputB = document.querySelector('input[name="ex-b"]');
        inputB.value = 'password';
    });

    // 模拟其他延迟或用户活动
    for (let i = 1; i <= 5; i++) {
        await page.waitForTimeout(1000);
        console.log(`Waited ${i} seconds...`);
    }

    console.log('Start solving CAPTCHA...');

    // 方法1:模拟点击CapSolver按钮
    await page.evaluate(() => {
        document.querySelector('#capsolver-solver-tip-button').click();
    });

    // 方法2:使用postMessage触发
    // await page.evaluate(() => {
    //     window.postMessage({ type: 'capsolverSolve' });
    // });

    await page.exposeFunction('captchaSolvedCallback', async () => {
        console.log('Captcha solved!');

        const iframe = await page.$('iframe[src*="recaptcha"]');
        if (iframe) {
            const frame = await iframe.contentFrame();
            const finished = await frame.evaluate(() => {
                const element = document.querySelector('.recaptcha-checkbox-border');
                return element && window.getComputedStyle(element).display === 'none';
            });

            if (finished) {
                console.log('Verification completed!');
                await page.click('button[type="submit"]');
                await page.waitForTimeout(3000);
                await context.close();
            } else {
                console.log('Verification not complete. Try again.');
            }
        }
    });
})();

配置选项:reCaptchaMode

reCaptchaMode设置支持两种模式:“click”和“token”。

  • click模式模拟人工交互——点击图像挑战。
  • token模式直接使用CapSolver API获取解决方案令牌,无需UI交互。

如果你在使用“click”模式时遇到多轮图像选择,这可能是由于浏览器指纹分数较低。建议切换到“token”模式以获得更好的可靠性。

点击模式 令牌模式

配置选项:showSolveButton

showSolveButton设置为false(默认为true)时,CapSolver按钮将不再显示在页面上。但是,这不会影响正常的CAPTCHA解决功能。

配置选项:useProxy

设置useProxy: true后,你可以指定以下参数:proxyTypehostOrIpportproxyLoginproxyPassword。通过此设置,我们将使用你的自定义代理来解决CAPTCHA。你应该在什么情况下使用你自己的代理?通常在以下情况下:

  1. 你的代理提供更好的质量(例如,使用你的代理生成的reCAPTCHA令牌获得更高的分数)或更快的解决速度;
  2. 在某些情况下,用于解决CAPTCHA的IP必须与用于提交令牌的IP相同。

以上是一些常用的配置选项。你可以根据实际需要调整其他设置。如有任何疑问,请联系我们的客户支持

使用CapSolver扩展程序解决ImageToText CAPTCHA

与reCAPTCHA、Cloudflare Turnstile、AWS WAF或GeeTest等第三方CAPTCHA不同,还有一种类型的CAPTCHA需要识别图像中的字母或数字。我们称之为ImageToText CAPTCHA。它们通常如下所示:

ImageToText是由网站管理员自己实现的CAPTCHA。与第三方CAPTCHA不同,ImageToText CAPTCHA是由网站所有者定制的。由于这些CAPTCHA在不同网站和页面的位置各不相同,因此CapSolver扩展程序无法自动检测哪些图像是CAPTCHA。因此,你必须在代码中明确告知CapSolver扩展程序。以下是操作方法:

  1. 向CAPTCHA的图像元素添加一个值为0capsolver-image-to-text-source属性;
  2. 向应填写结果的输入字段添加一个值为0capsolver-image-to-text-result属性。

这些属性——capsolver-image-to-text-sourcecapsolver-image-to-text-result——可以在/assets/config.js中使用字段textCaptchaSourceAttributetextCaptchaResultAttribute分别进行配置。

让我们来看一个使用该网站的示例:
https://captcha.com/demos/features/captcha-demo.aspx

首先,检查页面源代码以找到CAPTCHA图像元素和结果输入字段。在本例中:

  • CAPTCHA图像元素ID:demoCaptcha_CaptchaImage
  • 结果的输入字段ID:captchaCode
    (如下面的屏幕截图所示)

现在,让我们使用 Playwright 自动化解决此验证码,方法是相应地标记这些元素:

javascript 复制代码
const { chromium } = require('playwright');

// 步骤 1:从 GitHub 获取扩展程序 (https://github.com/capsolver/capsolver-browser-extension/releases)
// 步骤 2:解压扩展程序 zip 文件并在 /assets/config.js 中配置您的 apiKey
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: [
            `--disable-extensions-except=${extensionPath}`,
            `--load-extension=${extensionPath}`,
            '--lang=en-US'
        ],
    });

    const [page] = context.pages();
    await page.goto('https://captcha.com/demos/features/captcha-demo.aspx');
    await page.waitForSelector('#demoCaptcha_CaptchaImage');

    // 告诉 CapSolver 扩展程序验证码图像位于何处
    await page.evaluate(() => {
        const imgElement = document.querySelector('#demoCaptcha_CaptchaImage');
        if (imgElement) {
            imgElement.setAttribute('capsolver-image-to-text-source', '0');
        }
    });

    // 告诉 CapSolver 扩展程序应在何处输入识别结果
    await page.evaluate(() => {
        const resultElement = document.querySelector('#captchaCode');
        if (resultElement) {
            resultElement.setAttribute('capsolver-image-to-text-result', '0');
        }
    });

    // 等待验证码被解决并提交表单
    await page.exposeFunction('captchaSolvedCallback', async () => {
        console.log('验证码已解决!');
        await page.waitForTimeout(3000);
        await page.click('#validateCaptchaButton');
        await page.waitForTimeout(3000);
        await context.close();
    });
})();

结果:

如何将 CapSolver API 与 Playwright 集成

使用 CapSolver 扩展程序 方便快捷,但如果您是一位经验丰富的开发者,我们强烈建议您改用 API 集成。与基于扩展程序的方法相比,API 方法具有以下几个主要优势:

  1. 更多可自定义的参数 – 您可以微调您的请求,以更好地适应几乎所有验证码场景。
  2. 更强的控制力 – 您可以准确决定何时以及如何解决验证码。
  3. 更详细的错误消息 – 这有助于开发人员进行有针对性的优化。

在我们深入研究代码演示之前,以下是使用 CapSolver API 的简要概述:

要创建任务,您需要向 CapSolver 发送一个 JSON 对象。此 JSON 包括您的clientKeywebsiteURLwebsiteKey以及其他数据。这些字段会根据验证码类型和网站而有所不同。
👉 有关详细信息,请参阅我们的文档:documentation

使用 CapSolver API 解决 reCAPTCHA v2

在解决 reCAPTCHA v2 之前,请阅读此处的文档:
📖 ReCaptchaV2

本指南说明了创建任务时要包含哪些 JSON 参数。
此外,您可以使用 CapSolver 扩展程序 快速生成 API 请求的 JSON 数据。
请参阅此博客以获得帮助:
🔗 获取 JSON 数据


让我们以以下示例为例:
🔗 https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php

此页面创建任务所需的 JSON 为:

json 复制代码
{
    "type": "ReCaptchaV2TaskProxyLess",
    "websiteKey": "6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9",
    "websiteURL": "https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php"
}

我们还在我们的文档中提供了使用 API 的 JavaScript 代码示例:

在 Playwright 中集成:

javascript 复制代码
const { chromium } = require('playwright');
const axios = require('axios');

// 将其替换为您的 API 密钥
const api_key = 'YOUR_API_KEY';
const captcha_type = 'ReCaptchaV2TaskProxyLess';
const site_key = '6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9';
const site_url = 'https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php';

async function capSolver() {
    const payload = {
        clientKey: api_key,
        task: {
            type: captcha_type,
            websiteKey: site_key,
            websiteURL: site_url
        }
    };

    try {
        const res = await axios.post('https://api.capsolver.com/createTask', payload);
        const task_id = res.data.taskId;
        if (!task_id) {
            console.log('创建任务失败:', res.data);
            return;
        }
        console.log('获取 taskId:', task_id);

        while (true) {
            await new Promise(resolve => setTimeout(resolve, 1000)); // 延迟 1 秒

            const getResultPayload = { clientKey: api_key, taskId: task_id };
            const resp = await axios.post('https://api.capsolver.com/getTaskResult', getResultPayload);
            const status = resp.data.status;

            if (status === 'ready') {
                return resp.data.solution.gRecaptchaResponse;
            }
            if (status === 'failed' || resp.data.errorId) {
                console.log('解决失败!响应:', resp.data);
                return;
            }
        }
    } catch (error) {
        console.error('错误:', error);
    }
}

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: ['--lang=en-US'],
    });

    const [page] = context.pages();
    await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
    await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');

    const token = await capSolver();
    console.log("Token:", token);

    // 设置 token 值
    await page.evaluate((token) => {
        const textarea = document.getElementById('g-recaptcha-response');
        if (textarea) {
            textarea.value = token;
        }
    }, token);

    await page.click('button[type="submit"]');
    await page.waitForTimeout(5000);
    await context.close();
})();

使用 CapSolver API 解决 ImageToText

我们仍然使用 https://captcha.com/demos/features/captcha-demo.aspx 的示例,其中验证码图像元素的 id 为demoCaptcha_CaptchaImage,结果输入元素的 id 为captchaCode,如下图所示:

对于 ImageToTextTask,我们需要将验证码图像的 base64 值传递给 CapSolver。示例代码如下:

javascript 复制代码
const { chromium } = require('playwright');
const axios = require('axios');

// 将其替换为您的 API 密钥
const api_key = 'YOUR_API_KEY';
const captcha_type = 'ImageToTextTask';
const site_url = 'https://captcha.com/demos/features/captcha-demo.aspx';

async function capSolver(base64Image) {
    const payload = {
        clientKey: api_key,
        task: {
            type: captcha_type,
            websiteURL: site_url,
            body: base64Image,
        }
    };

    try {
        const res = await axios.post('https://api.capsolver.com/createTask', payload);

        const status = res.data.status;
        if (status === 'ready') {
            return res.data.solution.text;
        }
        if (status === 'failed' || res.data.errorId) {
            console.log('解决失败!响应:', res.data);
            return "";
        }
    } catch (error) {
        console.error('错误:', error);
    }
}

(async () => {
    const context = await chromium.launchPersistentContext('', {
        headless: false,
        viewport: { width: 1920, height: 1080 },
        args: ['--lang=en-US'],
    });

    const [page] = context.pages();
    await page.goto('https://captcha.com/demos/features/captcha-demo.aspx');
    await page.waitForSelector('#demoCaptcha_CaptchaImage');

    // 获取验证码图像的 base64 值
    const captchaImage = await page.evaluate(() => {
        const img = document.querySelector('img[id="demoCaptcha_CaptchaImage"]');
        return img ? img.getAttribute('src') : null;
    });
    const base64Image = captchaImage.split(',')[1];

    const text = await capSolver(base64Image);
    console.log("文本:", text);

    // 设置已解决的验证码文本
    await page.evaluate((text) => {
        document.getElementById('captchaCode').value = text;
    }, text);

    await page.click('#validateCaptchaButton');
    await page.waitForTimeout(5000);
    await context.close();
})();

此外,对于某些特殊的 ImageToText 类型,您可以指定不同的模型以提高准确性。有关详细信息,请参阅我们的文档:https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/

有用的参考

包含 CapSolver 扩展程序的演示视频:

此外,CapSolver 还提供 开发者收入分成计划,允许开发者和合作伙伴通过集成或推广 CapSolver 解决方案来赚取佣金。这是一种在帮助他人高效解决验证码的同时,将您的工作货币化的绝佳方式。有关完整详细信息,请查看:CapSolver 开发者计划

结论

Playwright 的强大功能与 CapSolver 处理验证码的能力相结合,为 Web 自动化提供了全面的解决方案。无论是为了方便使用 CapSolver 扩展程序,还是为了获得更大的控制力而使用 API,这种集成都可以简化复杂的任务并增强自动化工作流程。除了解决验证码之外,请记住 CapSolver 还提供了一个开发者收入分成计划,这为通过集成或推广其解决方案来赚取佣金提供了绝佳机会。

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

更多