我希望我的程序这样做:
第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);
})
答案 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()