无法使用 Puppeteer 通过选择器进行选择

Unable to choose by selectors using Puppeteer

我在通过选择器获取元素时遇到问题。

我挣扎的页面是:http://html5.haxball.com/。 我成功的是登录,但那是一种 hack,因为我使用了这样一个事实,即我需要填写的字段已经被选中。

输入 nick 并进入大厅后,我想单击按钮 'Create room'。它的选择器: 正文 > div > div > div > div > div.buttons > button:nth-child(3)

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
    args: ['--no-sandbox'], headless: false, slowMo: 10
});
const page = await browser.newPage();
await page.goto('http://html5.haxball.com/index.html');
await page.keyboard.type(name);
await page.keyboard.press('Enter');
//at this point I am logged in.

let buttonSelector = 'body > div > div > div > div > div.buttons > button:nth-child(3)';

await page.waitForSelector('body > div > div');
await page.evaluate(() => {
    document.querySelector(buttonSelector).click();
});

browser.close();
})();

在 运行 宁这样的代码之后我得到错误:

UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: Cannot read property 'click' of null

我最初的方法是: 等待page.click(buttonSelector); 而不是 page.evaluate 但它也失败了。

最让我沮丧的是,当我在 Chromium 控制台中 运行 时: document.querySelector(buttonSelector).click(); 它工作正常。

注意几点:

  • 您用来检索按钮的选择器比需要的更复杂。尝试更简单的方法,例如:'button[data-hook="create"]'.
  • 游戏在 iframe 内进行,因此您最好使用 iframedocument 对象调用 document.querySelector 而不是包含 window 的 document

  • 传递给 evaluate 的函数在与您 运行 节点脚本不同的上下文中执行。出于这个原因,您必须显式地将节点脚本中的变量传递给 window 脚本,否则 buttonSelector 将是未定义的:

进行上述更改,您的代码将输入您的姓名并成功点击"Create Room":

const puppeteer = require('puppeteer');

(async () => {

    const browser = await puppeteer.launch({
        args: ['--no-sandbox'], headless: false, slowMo: 10
    });

    const page = await browser.newPage();
    await page.goto('http://html5.haxball.com/index.html');
    await page.keyboard.type('Chris');
    await page.keyboard.press('Enter');
    //at this point I am logged in.

    let buttonSelector = 'button[data-hook="create"]';

    await page.waitForSelector('body > div > div');

    await page.evaluate((buttonSelector) => {

        var frame = document.querySelector('iframe');

        var frameDocument = frame.contentDocument;

        frameDocument.querySelector(buttonSelector).click();

    }, buttonSelector);

    browser.close();

})();