【问题标题】:create new tab in puppeteer inside a loop cause Navigation timeout在循环内的 puppeteer 中创建新选项卡导致导航超时
【发布时间】:2021-02-25 05:36:09
【问题描述】:

最近我正在使用他们的文档学习 puppeteer,并尝试抓取一些信息。

第一种方法

首先我从主页收集了一个 url 列表。 第二次 我创建了一个新标签页,然后反复访问这些网址并收集一些数据。我怀疑当我进入循环时,新选项卡没有按我的预期工作,并且在没有提供任何数据的情况下冻结。最终我得到了一个错误TimeoutError: Navigation timeout of 30000 ms exceeded。有没有更好的办法?

(async () => {
  const browser = await puppeteer.launch({ headless: true });
  const mainpage = await browser.newPage();

  console.log('goto main page'.green);
  await mainpage.goto(mainURL);

  console.log('collecting some url'.green);
  const URLS = await mainpage.evaluate(() =>
    Array.from(
      document.querySelectorAll('.result-actions a'),
      (element) => element.href
    )
  );
  if (typeof URLS[0] === 'string') console.log('OK'.green);

  console.log('collecting finished'.green);

  const newTab= await browser.newPage();

  console.log('create new tab'.green);

  var data = [];

  for (let i = 0, n = URLS.length; i < n; i++) {
    //console.log(URLS[i]);

    // use this new tab to collect some data then close this tab
    // continue this process

    await newTab.waitForNavigation();
    await newTab.goto(URLS[i]);
    await newTab.waitForSelector('.profile-phone-column span a');
    console.log('Go each url using new tab'.green);

    // collecting data
    
    data.push(collected_data);
    // close this tab
    await collectNamePage.close();
    console.log(data);
  }
  await mainpage.close();
  await browser.close();
  console.log('closing browser'.green);
})();

第二种方法

这次我想跳过使用新标签收集这些数据的部分。因此,我使用page.$$() 收集我的网址并尝试使用for...of 迭代urls 并使用elementHandle.$(selector) 收集我的数据,但这种方法也失败了。

我越来越沮丧。是我做错了还是我不理解他们的文档?

【问题讨论】:

    标签: puppeteer


    【解决方案1】:
    1. 在您的脚本中,您根本不需要newTab.waitForNavigation();。通常,当导航是由某些事件引起时使用。当你只使用.goto()时,会自动等待页面加载。

    2. 即使你需要waitForNavigation(),在导航触发之前你通常也不要await它,否则你只会得到超时。你await它跟导航触发一起:

      await Promise.all([element.click(),  page.waitForNavigation()]);
      

    所以尝试删除await newTab.waitForNavigation();

    另外,不要关闭循环中的新标签,循环结束后将其删除。


    编辑脚本:

    const puppeteer = require('puppeteer');
    const mainURL = 'https://www.psychologytoday.com/us/therapists/illinois/';
    
    (async () => {
      const browser = await puppeteer.launch({ headless: false });
      const mainpage = await browser.newPage();
    
      console.log('goto main page');
      await mainpage.goto(mainURL);
    
      console.log('collecting urls');
      const URLS = await mainpage.evaluate(() =>
        Array.from(
          document.querySelectorAll('.result-actions a'),
          (element) => element.href
        )
      );
      if (typeof URLS[0] === 'string') console.log('OK');
      console.log('collection finished');
    
      const collectNamePage = await browser.newPage();
    
      console.log('create new tab');
    
      var data = [];
    
      for (let i = 0, totalUrls = URLS.length; i < totalUrls; i++) {
        console.log(URLS[i]);
    
        await collectNamePage.goto(URLS[i]);
        await collectNamePage.waitForSelector('.profile-phone-column span a');
        console.log('create new tab and go there');
    
        // collecting data
        const [name, phone] = await collectNamePage.evaluate(
          () => [
            document.querySelector('.profile-middle .name-title-column h1').innerText,
            document.querySelector('.profile-phone-column span a').innerText
          ]
        );
        data.push({ name, phone });
      }
    
      console.log(data);
      await collectNamePage.close();
    
      await mainpage.close();
      await browser.close();
      console.log('closing browser');
    })();
    
    

    【讨论】:

    • 感谢您的回复@vsemozhebuty。现在我得到新的错误 Execution context was destroyed, most likely because of a navigation. here 是完整的控制台日志。我猜当您尝试运行一个函数时会出现这个问题,但目标(选项卡)已经关闭。有什么建议吗?为什么await newTab.$('selector_thing').innerText; 似乎未定义?它不应该是我可以清楚地知道节点退出的愿望文本吗
    • 不幸的是,在您提供真实代码之前很难判断(目前您的示例有遗漏和编辑工件 - 例如,collectNamePage 是什么?)。
    • 至于await newTab.$('selector_thing').innerText; - 您不应将传统的 DOM 元素及其 API (.innerText) 与许多 puppeteer 函数返回的元素处理程序混淆。详情见:stackoverflow.com/questions/55388455/…
    • 那么here就是完整的代码@vsemozhebuty。如果你能帮我解决这个问题,那将是很大的帮助
    • 没关系@vsemozhebuty 我解决了这个问题也很抱歉问了太多事情。我接受了你的回答。干杯
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多