Playwright无头模式下DevOps流水线Captcha绕过方案咨询
问题描述
当将headless mode设置为false时,以下登录代码可正常执行,但在DevOps流水线的headless模式下运行时,会遇到Captcha验证界面,导致流程中断执行失败。需要解决在headless模式下绕过Captcha的问题。
复现代码
import { expect, chromium } from "playwright/test"; module.exports = async () => { const browser = await chromium.launch(); await browser.newContext(); const page = await browser.newPage(); await page.goto(process.env.VITE_BASE_URL ?? "https://photondev.sgsco.com/"); const origin = await page.evaluate(() => window.location.origin); await page.goto(`${origin}/dashboard`); await page.getByRole("button", { name: "Login As A Client" }).click(); await page.getByRole("link", { name: "Google" }).click(); await page .getByLabel("Email or phone") .fill(process.env.VITE_PLAYWRIGHT_GMAIL_USERNAME ?? "test"); await page.getByRole("button", { name: "Next" }).click(); await page .getByLabel("Enter your password") .fill(process.env.VITE_PLAYWRIGHT_GMAIL_PASSWORD ?? "test@123"); await page .locator("#passwordNext") .getByRole("button", { name: "Next" }) .click(); await page.waitForURL( `${origin}/dashboard?period=last+3+months&status=4&toggle=true`, ); expect(page).toHaveURL( `${origin}/dashboard?period=last+3+months&status=4&toggle=true`, ); await page.goto( `my page`, ); await page.goto(`${origin}/dashboard`); await page.goto( `${origin}/dashboard?period=last+3+months&status=4&toggle=true`, ); await page.context().storageState({ path: "state.json" }); await browser.close(); };
解决方案
1. 优化Headless模式配置,模拟真实浏览器环境
Playwright旧无头模式易被检测,改用新无头模式并添加真实浏览器参数,降低被识别为自动化工具的概率:
const browser = await chromium.launch({ headless: "new", // 使用Playwright新无头模式,更接近真实浏览器 args: [ "--disable-blink-features=AutomationControlled", // 禁用自动化检测标志 "--start-maximized" ], slowMo: 100, // 模拟人类操作速度,避免触发反爬规则 }); const context = await browser.newContext({ userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", viewport: { width: 1920, height: 1080 }, locale: "en-US", });
2. 复用已登录存储状态,跳过登录流程
先在本地非无头模式下运行代码生成state.json,流水线中直接加载该状态,从根本上避开Captcha:
// 流水线执行代码,直接加载预先生成的登录状态 const context = await browser.newContext({ storageState: "state.json", // 跳过登录,直接使用已验证的会话 }); const page = await context.newPage(); // 直接访问目标页面,无需重复登录 await page.goto(`${origin}/dashboard?period=last+3+months&status=4&toggle=true`);
3. 添加随机延迟,模拟人类操作节奏
在表单填写、按钮点击之间加入随机延迟,避免操作过于机械化:
// 填写邮箱后随机延迟500-1000ms await page.getByLabel("Email or phone").fill(process.env.VITE_PLAYWRIGHT_GMAIL_USERNAME ?? "test"); await page.waitForTimeout(Math.floor(Math.random() * 500) + 500); await page.getByRole("button", { name: "Next" }).click(); await page.waitForTimeout(Math.floor(Math.random() * 800) + 300);
4. 请求网站管理员添加测试白名单
如果是内部系统,直接联系管理员将DevOps流水线IP或测试账号加入反爬白名单,这是最稳定可靠的解决方案,无需额外修改代码。
5. 补充必要请求头与权限
部分网站会检查特定请求头或权限,可在context中补充相关配置:
const context = await browser.newContext({ extraHTTPHeaders: { "Accept-Language": "en-US,en;q=0.9", "Referer": `${origin}/`, }, permissions: ["geolocation"], // 若网站需要地理位置权限可添加 });
内容的提问来源于stack exchange,提问作者Ahila .B
相关产品推荐
相关产品推荐

