操纵者和操纵up中的waitForSelector()超时错误,与超时值无关

时间:2020-06-28 20:32:06

标签: node.js timeout puppeteer

我希望我的程序这样做:

  1. 打开网页
  2. 单击按钮以转到新页面
  3. 获取新页面的屏幕截图。

第1步和第2步工作正常,但第3步遇到超时错误。基于对StackOverflow上类似问题的回答,我使用了具有较大超时跨度(最多2分钟)的waitForNavigation(),但是仍然出现相同的错误。使用waitForSelector()而不是waitForNavigation()也会产生相同的错误。如果同时删除了两者,则puppeteer会在步骤1中截取该网页的屏幕快照。我还尝试对waitUntil使用其他选项,例如“ domcontentloaded”,“ loaded”,“ networkidle0”和“ newtorkidle2”,但没有任何效果。 这是我在puppeteer中的第一个程序,我在这个问题上困扰了很长时间。

这是我的代码:

 await page.waitForSelector('#featured > c-wiz > div.OXo54d > div > div > div > span > span > span.veMtCf');
         
 // await navigation;
 await page.screenshot({path: 'learnmore.png'});
 console.log('GOT THIS FAR:)');
 //await page.close();
 await browser.close();
 return 0;

这是完整的程序:

const puppeteer = require('puppeteer');
(async () => {
    try{
        const browser = await puppeteer.launch({headless: false});
        const page = await browser.newPage();
       // const navigationPromise = page.waitForNavigation({waitUntil: "load"});

        //google.com
        await page.goto('https://google.com');
        await page.type('input.gLFyf.gsfi',"hotels in london");
        await page.keyboard.press('Enter');
        //search results
       // await navigationPromise;
        await page.waitForSelector('#rso > div:nth-child(2) > div > div > div > g-more-link > a > div');
        await page.click('#rso > div:nth-child(2) > div > div > div > g-more-link > a > div'); 
        //list of hotels
       // await navigationPromise;
        await page.waitForSelector('#yDmH0d > c-wiz.zQTmif.SSPGKf > div > div.lteUWc > div > c-wiz > div > div.gpcwnc > div.cGQUT > main > div > div.Hkwcrd.Sy8xcb.XBQ4u > c-wiz > div.J6e2Vc > div > div > span > span');
        await page.click("#yDmH0d > c-wiz.zQTmif.SSPGKf > div > div.lteUWc > div > c-wiz > div > div.gpcwnc > div.cGQUT > main > div > div.Hkwcrd.Sy8xcb.XBQ4u > c-wiz > div.l5cSPd > c-wiz:nth-child(3) > div > div > div > div.kCsInf.ZJqrAd.qiy8jf.G9g6o > div > div.TPQEac.qg10C.RCpQOe > a > button > span");
        //"learn more"
       // await navigationPromise;   
       
        //This is where timeout error occurs:
        await page.waitForSelector('#featured > c-wiz > div.OXo54d > div > div > div > span > span > span.veMtCf');             
       // await navigation;
        await page.screenshot({path: 'learnmore.png'});
        console.log('GOT THIS FAR:)');

        //await page.close();
        await browser.close();
        return 0;
    }
    catch(err){
       console.error(err);
    }
})()
.then(resolvedValue => {
    console.log(resolvedValue);
})
.catch(rejectedValue => {
    console.log(rejectedValue);
})

1 个答案:

答案 0 :(得分:1)

您超时是因为页面上不存在您要等待的选择器。 (如果要打开脚本所卡住的浏览器控制台并启动$(selector),它将返回null

Google使用动态的class和id值,正是为了防止(或使其变得更难)通过脚本检索数据,每次访问该页面时,选择器将具有不同的值。

如果您确实需要抓取其内容,则可以使用XPath selectors,它比动态更改选择器名称的脆弱性小:

例如:

await page.waitForXpath('//h3[contains(text(), "The Best Hotels in London")]')

const link = await page.$x('//h3[contains(text(), "The Best Hotels in London")]')
await link[0].click()

文档参考: