如果尝试以下简单示例,您会发现它可以正常工作:
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const response = await page.goto(`https://finance.yahoo.com/chart/TSLA`, {waitUntil: 'networkidle2'});
console.log(await response.text());
let selector = `div#chart-toolbar ul > li`
page.waitForSelector(selector)
selector = `div#chart-toolbar ul > li:nth-child( 7 ) > button` // > span > span
page.click(selector)
const inputElement = await page.$('div#fin-chartiq')
await inputElement.screenshot({path: 'yahoo-finance.png'})
await browser.close();
})();
yahoo-finance.png
文件如下所示:
但是,如果仔细查看保存的页面源,您会发现关键字chart-toolbar
根本不在文件中。
使用这样的“不存在” 元素,上面的代码如何工作?
我要问的原因是,这是我复杂的剪贴程序中的精简版本,其中puppeteer
,browser
,page
和selector
所有这些都来自不同级别的类层次结构,我正在其中:
TimeoutError: waiting for selector "div#chart-toolbar ul > li" failed: timeout 30000ms exceeded
代码在本质上是相同的,但是只是在不同的类文件中,我已经耗尽了为什么一个神秘地工作而其他却不工作的想法。请帮忙。谢谢。
答案 0 :(得分:2)
不存在“不存在”元素。该元素位于最终DOM中,response.text()
仅提供原始HTML内容。对于最终的DOM,请使用page.content()
:
const response = await page.goto(`https://finance.yahoo.com/chart/TSLA`, {waitUntil: 'networkidle0'});
console.log(await page.content());
关于超时,可能是导航和等待元素出现之间的竞争条件。发生这种情况的原因可能很多,如果不查看代码就很难查明问题。我建议将headless设置为false,导航到该页面,然后查看导航是否完成,并且可以找到所需的元素。
我还指出,您没有await
使用waitForSelector
和click
。使用以下命令可获得预期的结果:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try{
const page = await browser.newPage();
//HERE change networkidle2 to networkidle0
const response = await page.goto(`https://finance.yahoo.com/chart/TSLA`, {waitUntil: 'networkidle0'});
let selector = `div#chart-toolbar ul > li`
await page.waitForSelector(selector)
selector = `div#chart-toolbar ul > li:nth-child( 7 ) > button` // > span > span
await page.click(selector)
const inputElement = await page.$('div#fin-chartiq')
await inputElement.screenshot({path: 'yahoo-finance.png'})
}catch(err) {console.log(err.message);}
finally{
await browser.close();
}
})()