node.js - Puppeteer 不断收到 TimeoutError:超过 80000 毫秒的导航超时
问题描述
我正在尝试抓取传递给抓取函数的任何网页,但是无论在 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
解决方案
您使脚本的 timeout-waitfor 部分过于复杂。我建议进行以下更改:
- 如果您不确定是什么原因导致您应该设置超时,
headless: false
以便您可以在 UI 上看到出了什么问题,您可以打开浏览器控制台等。 waitForSelector
在脚本使用-s完成您想要的操作之前,不要设置超时。我从你的脚本中删除了它们。- 如果你对每个网络事件都不感兴趣(尤其是对分析和跟踪请求不感兴趣),但你只需要 DOM,那么使用
waitUntil: 'domcontentloaded'
而不是load
或最严格的networkidle2
!在文档中查看它们之间的确切区别:[链接] waitForNavigation
在您已经等待选择器之后不要这样做。这就是您的脚本失败的主要原因:一旦<body>
出现在 DOM 中,您要求 puppeteer 等到导航完成,但此时您没有导航:您已经在页面上。记住:page.waitForNavigation
当页面导航到新 URL 或重新加载时解析。当您运行将间接导致页面导航的代码时,它很有用。[资源]- 你
page.eval$
缺乏它的异步性质,而它应该总是异步的。无论如何innerHTML
,<body>
可以用更简单的方法来检索ofawait 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)
}
}
推荐阅读
- python - 将两个列表的笛卡尔积作为列表列表
- python - 如何从网址保存图像并将其保存在特定文件夹中
- jupyter-lab - 在 Jupyterlab 中将 Altair 输出居中(包括导出为 HTML 时)
- curl - Google Drive - Api V3 - CURL - 创建文件夹、子文件夹 - Parends ID
- javascript - 如何将位数组作为字符串转换为 ArrayBuffer
- c# - 如何在不使用 Nullable 的情况下使用可选值类型(即结构)参数
在 WebApi 2 中? - reactjs - 带有 React.forwardRef 功能组件的 VSCode TS 错误
- spring-boot - 在 Spring Boot 中使用 Jackson 反序列化 Date 对象
- amazon-web-services - 我可以在更新用户之前使用 aws amplify 验证电话号码吗?
- python - (Discord.py) 如何获取整个嵌入内容?