Puppeteer keeps getting TimeoutError: Navigation timeout of 80000 ms exceeded
Puppeteer keeps getting TimeoutError: Navigation timeout of 80000 ms exceeded
我正在尝试抓取任何传递给抓取函数的网页,但无论 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 上使用 Ubuntu 18.04(Windows Linux 的子系统)
您将脚本的超时等待部分复杂化了一点。我建议进行以下更改:
- 如果您不确定导致超时的原因,您应该设置
headless: false
这样您就可以在 UI 上看到哪里出了问题,您可以打开浏览器控制台等
- 在脚本使用
waitForSelector
-s 执行您想要的操作之前不要设置超时。我从你的脚本中删除了它们。
- 如果您对每个网络事件都不感兴趣(尤其是对分析和跟踪请求不感兴趣),但您只需要 DOM,那么请使用
waitUntil: 'domcontentloaded'
而不是 load
或者最严格networkidle2
!在文档中查看它们之间的确切区别是什么:[link]
- 在等待选择器之后不要
waitForNavigation
。这是您的脚本失败的主要原因:一旦 <body>
出现在 DOM 中,您要求 puppeteer 等待导航完成,但此时您没有导航:您已经在这一页。请记住:
page.waitForNavigation
resolves when the page navigates to a new URL or reloads. It is useful for when you run code which will indirectly cause the page to navigate. [source]
- 您的
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)
}
}
我正在尝试抓取任何传递给抓取函数的网页,但无论 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 上使用 Ubuntu 18.04(Windows Linux 的子系统)
您将脚本的超时等待部分复杂化了一点。我建议进行以下更改:
- 如果您不确定导致超时的原因,您应该设置
headless: false
这样您就可以在 UI 上看到哪里出了问题,您可以打开浏览器控制台等 - 在脚本使用
waitForSelector
-s 执行您想要的操作之前不要设置超时。我从你的脚本中删除了它们。 - 如果您对每个网络事件都不感兴趣(尤其是对分析和跟踪请求不感兴趣),但您只需要 DOM,那么请使用
waitUntil: 'domcontentloaded'
而不是load
或者最严格networkidle2
!在文档中查看它们之间的确切区别是什么:[link] - 在等待选择器之后不要
waitForNavigation
。这是您的脚本失败的主要原因:一旦<body>
出现在 DOM 中,您要求 puppeteer 等待导航完成,但此时您没有导航:您已经在这一页。请记住:
page.waitForNavigation
resolves when the page navigates to a new URL or reloads. It is useful for when you run code which will indirectly cause the page to navigate. [source]
- 您的
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)
}
}