我正在尝试选择表单中的选项。表单中的select元素没有id,但是具有name属性。但是我无法选择该选项,而是选择了它。代码如下。
const puppeteer = require('puppeteer');
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
(async () => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select');
await sleep(5000);
await page.select('select[name=cars]', 'Saab');
await sleep(15000);
await browser.close();
})();
它抛出了如下异常。
(节点:15904)UnhandledPromiseRejectionWarning:错误:错误:未能 查找与选择器匹配的元素“ select [name = cars]” 在ElementHandle。$ eval(/home/austin/nodejs/node_modules/puppeteer/lib/JSHandle.js:435:13) 在 在process._tickCallback(内部/进程/next_tick.js:188:7)-ASYNC- 在ElementHandle。 (/home/austin/nodejs/node_modules/puppeteer/lib/helper.js:111:15) 在DOMWorld。$ eval(/home/austin/nodejs/node_modules/puppeteer/lib/DOMWorld.js:156:21) 在 在process._tickCallback(内部/进程/next_tick.js:188:7)(节点:15904)UnhandledPromiseRejectionWarning:未处理的承诺 拒绝。
请让我知道为什么Puppeteer page.select在这里不起作用。
答案 0 :(得分:2)
您的选择器是正确的,很遗憾,您选择进行练习的目标网站比普通网站要复杂一些,因为它会在iframe中显示您要关注的内容以及该方法:
await page.select('select[name=cars]', 'Saab');
仅在主框架中查找元素。
因此,我们需要先找到具有演示HTML的iframe(并可能等待其首先加载,因为它是由脚本生成的,并且在页面加载后立即不可用)。我们可以等待任意一段时间(例如page.waitFor(5000)
),但它太不稳定了-谁知道在实际刮削中需要多少时间?
我将在更正的脚本中作为注释提供进一步的描述:
const puppeteer = require('puppeteer');
// this utility's from [1]
function waitForFrame(page) {
let fulfill;
const promise = new Promise(x => fulfill = x);
checkFrame();
return promise;
function checkFrame() {
// either find an existing iframe
// note that we know the name of that iframe
const frame = page.frames().find(f => f.name() === 'iframeResult');
if (frame)
fulfill(frame);
else
// or wait for the event when it will have been created
page.once('frameattached', checkFrame);
}
}
(async () => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('https://www.w3schools.com/html/tryit.asp?filename=tryhtml_elem_select');
// Wait for an iframe with demo HTML
const frame = await waitForFrame(page);
// Now wait for the element we need to appear, we won't rely on a fixed timeout
// Note that we're waiting on the previously discovered "frame", not the usual "page"
await frame.waitForSelector('select[name=cars]');
// Set the desired value, note that it is lowercase, as in option's value
await frame.select('select[name=cars]', 'saab');
// Confirm we did it right
await page.screenshot({path : "screen.jpg"});
await browser.close();
})();
[1] https://github.com/GoogleChrome/puppeteer/issues/1361#issuecomment-343748051