I have a nodejs script which use Puppeteer and works well. The code is basically this :
//Load href to visit into each tab
tabs = [];
var idxTab=0;
for(let hrefToVisit of hrefsToVisit) {
tabs.push(await browser.newPage());
await tabs[idxTab].goto(hrefToVisit, {waitUntil: 'domcontentloaded'});
idxTab ;
}
while (true) {
...
//Refresh all tabs
var promises = [];
for (let tab of tabs ) {
promises.push(tab.reload());
}
await Promise.all(promises);
try{
let allNews = '';
let firstNews = '';
let pseudo = '';
//Get the first news on the page
allNews = await tab.$$("article.news");
await tab.waitForTimeout(5000);
firstNews = allNews[0];
//Get the pseudo of this first news
pseudo = await firstNews.$eval('.user.userInfo span', s => s.textContent.trim());
console.log(new Date(), 'Pseudo : ', pseudo, '...');
//Log HTML content for debug
console.log('html when all ok : ');
let bodyHTML = await tab.evaluate(() => document.body.innerHTML);
console.log(bodyHTML);
await tab.screenshot({path: 'ok.png'});
}catch (err){
console.log('html when not ok : ');
let bodyHTML = await tab.evaluate(() => document.body.innerHTML);
console.log(bodyHTML);
await tab.screenshot({path: 'ko.png'});
console.log(err);
}
...
}
The problem is, I have 30% of time this error :
TypeError: Cannot read properties of undefined (reading '$eval')
at main (script.js:327:40)
Sometimes it runs ok, sometimes don't.
So I logged html when it's ok and when it's not. I also made a screenshot.
Both HTML and screenshot are the same, the page is loaded and the elements are present in the html, so why I can't "eval" them ?
The part :
await tab.waitForTimeout(5000);
make the things a little better sometimes, but not enough. I tried to use other strategy, like using :
await waitForSelector('article.news');
Before evaluate anything, but it doesn't change anything, it's even worth because it doesn't wait a lot (the element is quickly displayed so it passed true). Waiting 5s each time seems a little better, but even if I put 10s, sometimes it failed anyway...
How can I debug this, to find the problem ?
CodePudding user response:
Weirdly, after fixing some little thing with ESLINT help (thx to ggorlen), it seems to work better.
I used "destructuring" to get the first news, and put back the "await tab.waitForSelector..." instead of waiting 5000ms :
let firstNews;
let otherNews;
let pseudo = '';
...
await tab.waitForSelector('article.news', { timeout: 5000 });
[firstNews, ...otherNews] = await tab.$$('article.news');