Puppeteer 无法单击 Google 同意页面中的“允许”按钮

Puppeteer unable to click on the Allow button in Google consent page

我正在尝试使用 puppeteer 登录 Google 授权页面。到目前为止,我能够让 puppeteer 成功输入用户名、密码和 2FA。然后我被重定向到这个 Google 同意页面

但是 puppeteer 无法点击允许按钮并抛出以下错误:

typing email...
clicking next button...
waiting for password field...
typing password...
clicking next button...
waiting for consent approval...
clicking Allow button...
(node:87043) UnhandledPromiseRejectionWarning: Error: No node found for selector: #submit_approve_access
    at assert (/Users/mohamed/projects/googleAuth/api/src/test/resources/dev-tools/node_modules/puppeteer/lib/helper.js:278:11)
    at Frame.click (/Users/mohamed/projects/googleAuth/api/src/test/resources/dev-tools/node_modules/puppeteer/lib/FrameManager.js:736:5)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
  -- ASYNC --
    at Frame.<anonymous> (/Users/mohamed/projects/googleAuth/api/src/test/resources/dev-tools/node_modules/puppeteer/lib/helper.js:144:27)
    at Page.click (/Users/mohamed/projects/googleAuth/api/src/test/resources/dev-tools/node_modules/puppeteer/lib/Page.js:973:29)
    at doLogin (/Users/mohamed/projects/googleAuth/api/src/test/resources/dev-tools/routes/index.js:177:16)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
(node:87043) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:87043) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

下面是我写的Node.js代码:

async function doLogin(authorizeUrl) {
    const browser = await puppeteer.launch({headless: false});
    const page = await browser.newPage();
    await page.goto(authorizeUrl);
    await page.mainFrame().waitForSelector('#identifierId');
    console.log('typing email...');
    await page.type('#identifierId', googleCredentials.username);
    await page.mainFrame().waitForSelector('#identifierNext');
    console.log('clicking next button...');
    await page.click('#identifierNext');
    console.log('waiting for password field...');
    await page
        .mainFrame()
        .waitForSelector('#password input[type="password"]', {visible: true});
    console.log('typing password...');
    await page.type('#password input[type="password"]', googleCredentials.password, {
        delay: 100,
    });
    console.log('clicking next button...');
    await page.click('#passwordNext', {delay: 100});
    console.log('waiting for consent approval...');
    console.log('clicking Allow button...');
    await page.click('#submit_approve_access', {delay: 100});
    return browser;
}

当您点击该按钮时,该按钮还不可用。可能是这种情况,因为当您单击 #passwordNext 按钮时,页面将执行一个可能需要几毫秒的异步操作,可能是网络请求,也可能只是一些计算。因此,无需等待,当您调用 page.click 时,没有按钮可单击。

解决方案

您可以在调用 page.click 之前添加以下行以确保该按钮实际出现在页面上:

await page.waitForSelector('#submit_approve_access');