木偶waitForSelector和“不存在”元素

时间:2020-01-18 20:08:50

标签: javascript puppeteer

如果尝试以下简单示例,您会发现它可以正常工作:

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文件如下所示:

enter image description here

但是,如果仔细查看保存的页面源,您会发现关键字chart-toolbar根本不在文件中。

使用这样的“不存在” 元素,上面的代码如何工作?

我要问的原因是,这是我复杂的剪贴程序中的精简版本,其中puppeteerbrowserpageselector所有这些都来自不同级别的类层次结构,我正在其中:

TimeoutError: waiting for selector "div#chart-toolbar ul > li" failed: timeout 30000ms exceeded

代码在本质上是相同的,但是只是在不同的类文件中,我已经耗尽了为什么一个神秘地工作而其他却不工作的想法。请帮忙。谢谢。

1 个答案:

答案 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使用waitForSelectorclick。使用以下命令可获得预期的结果:

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();
    }
})()