使用Playwright测试Google登录时出现登录拒绝的问题
Google登录重定向至deniedsigninrejected的解决方法
出现这个问题核心原因是Google的反自动化机制识别到了Playwright的自动化环境,另外你的代码里的导航等待逻辑也存在问题,以下是具体解决步骤:
1. 启用持久化浏览器上下文
用持久化上下文保存登录状态,减少重复触发反爬检测的概率,同时让浏览器环境更接近真实用户的使用状态:
// 在测试中创建持久化上下文 import { test, expect, chromium } from '@playwright/test'; test('Entry', async () => { const browser = await chromium.launchPersistentContext('./user-data-dir', { headless: false, // 先以非无头模式测试,后续可按需调整 args: ['--disable-blink-features=AutomationControlled'] }); const page = await browser.newPage(); // 后续测试逻辑... await browser.close(); });
2. 模拟真实浏览器环境
添加启动参数隐藏自动化标识,同时设置真实的User-Agent:
// 可在playwright.config.ts中全局配置,或创建上下文时单独添加 use: { userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', launchOptions: { args: [ '--disable-blink-features=AutomationControlled', '--disable-dev-shm-usage', '--no-sandbox' ] } }
3. 修复导航等待逻辑
原代码中navigationPromise的使用有误,点击按钮后应该等待对应的导航完成,而不是提前创建后重复等待,修改后的登录流程:
// 输入邮箱并点击下一步 await page.getByLabel('电子邮箱或电话').fill('office.skylord@gmail.com'); await Promise.all([ page.waitForNavigation(), // 等待点击后的页面跳转 page.getByRole('button', { name: '下一步' }).click() ]); // 输入密码并点击下一步 await page.getByLabel('输入您的密码').fill('yourpassword'); await Promise.all([ page.waitForNavigation(), page.getByRole('button', { name: '下一步' }).click() ]);
4. 使用更稳定的元素定位方式
避免依赖固定的ID或属性,改用Playwright的语义化定位方法,比如getByLabel、getByRole,这些定位方式更不容易受页面更新影响。
修改后的完整测试代码
import { test, expect, chromium } from '@playwright/test'; test('Entry', async () => { const browser = await chromium.launchPersistentContext('./user-data-dir', { headless: false, args: ['--disable-blink-features=AutomationControlled'], userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' }); const page = await browser.newPage(); console.log('Opening Asos.com') await page.goto('https://www.asos.com/'); console.log('Hovering action menu') await page.hover('[data-testid=myAccountIcon]'); console.log('clicking on Join') await page.locator('[data-testid=signup-link]').click(); console.log('Opening registration page') await expect(page).toHaveURL(/.*identity\/register.*/); console.log('Clicking sign up by google') // 等待新标签页打开,Google登录通常会在新窗口启动 const [googlePage] = await Promise.all([ page.waitForEvent('popup'), page.locator('#signup-google').click() ]); console.log('Opening google registration page') await expect(googlePage).toHaveURL(/.*accounts.google.com.*/); console.log('Filling email') await googlePage.getByLabel('电子邮箱或电话').fill('office.skylord@gmail.com'); console.log('Clicking next') await Promise.all([ googlePage.waitForNavigation(), googlePage.getByRole('button', { name: '下一步' }).click() ]); console.log('Filling password') await googlePage.getByLabel('输入您的密码').fill('yourpassword'); console.log('Login with google') await Promise.all([ googlePage.waitForNavigation(), googlePage.getByRole('button', { name: '下一步' }).click() ]); console.log('Success') // 验证是否跳转到Asos的目标页面 await expect(page).toHaveURL(/.*asos.com.*/); await browser.close(); });
注意:第一次运行时建议用非无头模式,手动完成可能出现的人机验证(比如滑块、验证码),后续持久化上下文会保存登录状态,再次运行时就不需要重复验证了。
内容的提问来源于stack exchange,提问作者Toma Tomov
相关产品推荐
相关产品推荐

