【问题标题】:Puppeteer keeps getting TimeoutError: Navigation timeout of 80000 ms exceededPuppeteer 不断收到 TimeoutError:超过 80000 毫秒的导航超时
【发布时间】:2020-06-18 21:55:58
【问题描述】:

我正在尝试抓取传递给抓取函数的任何网页,但无论在 page.goto() 中设置的超时时间如何,我都会不断收到超时错误,如果设置为 0,应用程序只会一直等待。

const express = require('express');
const cors = require('cors');
const MYPORT = process.env.PORT || 4001;


const app = express();
const puppeteer = require('puppeteer');

app.use(express.json());
app.use(cors());

const scrape = async (url) => {
    var body;
    try {
        const browser = await puppeteer.launch({
            headless: true,
            args: ['--no-sandbox'],
            timeout: 0
        });
        console.log('Browser launched');
        const page = await browser.newPage();
        console.log('Page opened');
        await page.goto(url, { waitUntil: 'load', timeout: 3 * 60000 });
        await page.waitForSelector('body', {waitUntil: 'load'})
        console.log('Link opened');
        await page.waitForNavigation({waitUntil: 'networkidle2', timeout: 3 * 60000});
        page.$eval('html', bdy => {
            console.log(bdy);
            body = bdy.innerHTML;
        });
        browser.close();
        return body;
    } catch (err) {
        console.log(err);
    }
};

scrape('http://google.com');

请问,我做错了什么?

我在 WSL(Linux 的 Windows 子系统)上使用 Ubuntu 18.04

【问题讨论】:

    标签: node.js express puppeteer ubuntu-18.04 windows-subsystem-for-linux


    【解决方案1】:

    您的脚本中的 timeout-waitfor 部分过于复杂了。我建议进行以下更改:

    1. 如果您不确定导致超时的原因,您应该设置headless: false,这样您就可以在 UI 上看到出了什么问题,您可以打开浏览器控制台等。
    2. 在脚本使用waitForSelector-s 完成您想要的操作之前不要设置超时。我从你的脚本中删除了它们。
    3. 如果你对每一个网络事件都不感兴趣(特别是对分析和跟踪请求不感兴趣),但你只需要DOM,那么使用waitUntil: 'domcontentloaded'而不是load或者最严格的networkidle2!在文档中查看它们之间的确切区别:[link]
    4. 在等待选择器后不要waitForNavigation。这就是脚本失败的主要原因:一旦<body> 出现在 DOM 中,您要求 puppeteer 等到导航完成,但此时您没有导航:您已经在页面上。请记住:

    page.waitForNavigation 在页面导航到新 URL 或重新加载时解析。当您运行将间接导致页面导航的代码时,它很有用。 [source]

    1. 您的page.$eval 缺乏异步特性,但它应该始终是异步的。无论如何,<body>innerHTML 可以通过以下方式更简单地检索:await page.evaluate(el => el.innerHTML, await page.$('body'))
    const scrape = async url => {
      try {
        const browser = await puppeteer.launch({
          headless: false,
          args: ['--no-sandbox']
        })
        console.log('Browser launched')
        const page = await browser.newPage()
        console.log('Page opened')
        await page.goto(url, { waitUntil: 'domcontentloaded' })
        await page.waitForSelector('body')
        console.log('Link opened')
        const body = await page.evaluate(el => el.innerHTML, await page.$('body'))
        console.log(body)
        browser.close()
        return body
      } catch (err) {
        console.log(err)
      }
    }
    

    【讨论】:

    • 感谢您的解释和解决方案。我在 Heroku 上运行了代码,它运行良好,但我在本地机器上的 Chromium 中收到 256 错误。但我认为问题已解决,我将不得不找到解决 256 错误的方法。再次感谢您!
    • 我明白了,我想如果它在 Heroku 上工作你已经添加了所需的构建包:github.com/puppeteer/puppeteer/blob/main/docs/…。错误 256 与 GPU 有关,如果您已修复代码 headless: true 可以再次重新启用(Heroku 不需要它)。如果您仍然遇到问题,--disable-gpu 启动参数可能会有所帮助。
    • 是的,我已经添加了构建包。我想我对 256 错误无能为力,因为 --disable-gpu 标志不适用于我的机器,所以我会在需要时从 Heroku 运行代码。非常感谢您的见解,非常感谢。
    猜你喜欢
    • 2023-03-04
    • 2022-12-29
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 2019-04-14
    • 2020-02-18
    • 2021-10-16
    相关资源
    最近更新 更多