无法使用 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
内进行,因此您最好使用 iframe
的 document
对象调用 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();
})();
我在通过选择器获取元素时遇到问题。
我挣扎的页面是: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
内进行,因此您最好使用iframe
的document
对象调用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();
})();