Puppeteer page.waitForNavigation() 超时错误处理

Puppeteer page.waitForNavigation() timeout error handling

使用 puppeteer,我在输入值时打开一个页面 - 它输出结果。

await page.click('button[class="button form-button rs-gcbalance-btn"]')

await page.waitForSelector('div[class="small-4 large-4 rs-gcbalance-result-num-col').catch(err => console.log(err))

await page.evaluate((card) => {
    console.log(card + " - " + document.querySelectorAll('div[class="small-4 large-4 rs-gcbalance-result-num-col"]')[1].querySelector('span').innerHTML)
}, card)

但只有当输入的值有效时才能正常工作。如果不是,它会抛出错误,但没有任何网络 activity 或加载事件。
这意味着,如果值不正确,我正在等待的元素将不会出现并将抛出错误,关闭程序。

Navigation Timeout Exceeded: 30000ms exceeded

问题是:如何处理错误,所以如果它抛出超时错误,我可以捕获它并调用另一个函数?

只需将其包装在 try catch 块中:

try {
  await page.waitForSelector('#element', { timeout: 1000 });
  // do what you have to do here
} catch (e) {
    console.log('element probably not exists');
}

这是一个完整的示例:

const puppeteer = require('puppeteer');

const html = `
<html>
    <body>
        <div id="element">element inner html</div>
    </body>
</html>`;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(`data:text/html,${html}`);

  try {
    await page.waitForSelector('#element-not-exists', { timeout: 1000 });
    const element = await page.$('#element-not-exists');
    console.log(await (await element.getProperty('innerHTML')).jsonValue());
  } catch (e) {
    console.log('element probably not exists');
  }
  await browser.close();
})();

尝试使用它可以解决您的问题。 page.waitForNavigation({ 超时: 1000, waitUntil: 'domcontentloaded' });

当我试图抓取一些页面时,我遇到了类似的问题,因为默认超时为 30000 毫秒,即 30 秒,页面加载时间超过 30 秒,所以基本上有 2 个主要问题。

  1. 脚本在 nodejs 抛出后没有被杀死 page.waitForNavigation() 超时错误,所以一直保持 mysql 与服务器的连接处于活动状态并且正在建立新连接 由 cronjob 创建,它们都处于睡眠状态。
  2. 页面未被抓取,因此需要增加超时时间。

这是我的最终代码。

const puppeteer = require('puppeteer');
var mysql = require('mysql');


var mysql_con = mysql.createConnection({
  host: "",
  user: "",
  password: "",
  database: ""

});

//connect to mysql
mysql_con.connect(function(err) {
  if (err) throw err;
  console.log("Connected! to MySQL");
});


(async () => {

    const args = [
        '--no-sandbox', 
        '--disable-setuid-sandbox',
        '--disable-infobars',
        '--window-position=0,0',
        '--ignore-certifcate-errors',
        '--ignore-certifcate-errors-spki-list',
        '--ignoreHTTPSErrors=true',
        '--user-agent="Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/W.X.Y.Z‡ Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"' 
    ];

    const browser = await puppeteer.launch({ args });
    const page = await browser.newPage();

    // Configure the navigation timeout to 2 minutes, becuase sometimes site is too busy
    await page.setDefaultNavigationTimeout(120000);

  try {

    // Now you can go wherever you want
    const response = await page.goto('https://www.example.com/');

    //print http status code 
    console.log(response.status());

    //do mysql related stuff here

    //close mysql connection
    mysql_con.end();

  } catch (e) {

    console.log('cant load the page, maybe server is busy : ' + e);

    //close mysql connection
    mysql_con.end();

    await browser.close();

    //double tap to die script
    process.exit();
  }



    // Then when you're done, just close
    await browser.close();
})();

这里我们解决了 2 个问题。

  1. 第一个问题是使用 try 和 catch 块并在 catch 块中终止 script/ending mysql 连接。
  2. 将页面超时从默认的 30 秒增加到 2 分钟。

    page.setDefaultNavigationTimeout(120000);

try catch块是一个解决方案。

但是,在已接受的答案上 所有错误都已消除!!

您应该只捕获 Puppeteer TimeOut 错误。

try {
  await page.waitForSelector('.foo');
} catch (e) {
  if (e instanceof puppeteer.errors.TimeoutError) {
    // Do something if this is a timeout.
  }
}

参考文献:https://devdocs.io/puppeteer/

您可以在单击按钮后使用 waitForNavigation 方法并附加如下所示的 catch 块来处理导航超时错误,以防输入的值不正确并且导航没有发生

page.waitForNavigation({waitUntil:"domcontentloaded"}).catch(error => {
    // handler code here
});