UnhandledPromiseRejectionWarning: Error: Page crashed! While using puppeteer
UnhandledPromiseRejectionWarning: Error: Page crashed! While using puppeteer
所以我使用了一个 while 循环,所以我的测试将 运行 持续循环,直到我的后端崩溃。
我已经实现了一个 try and catch(error) 所以任何前端崩溃自动化都会刷新并保持 运行ning
while(true){
try{
await page.waitFor(selector)
await page.click(selector)
}
catch(error){
console.log("FE crashed with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
await page.reload(page);
continue;
}}
所以实际上任何超时错误自动刷新页面并继续循环。
但我收到了不同的崩溃错误
(node:6535) UnhandledPromiseRejectionWarning: Error: Page crashed!
at Page._onTargetCrashed (/home/raymond/node_modules/puppeteer/lib/Page.js:170:24)
at CDPSession.Page.client.on.event (/home/raymond/node_modules/puppeteer/lib/Page.js:125:56)
at CDPSession.emit (events.js:182:13)
at CDPSession._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:200:12)
at Connection._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:112:17)
at _tickCallback (internal/process/next_tick.js:43:7)
at listOnTimeout (timers.js:294:7)
at processTimers (timers.js:268:5)
(node:6535) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
我该如何处理这个错误?如果我手动刷新页面,一切正常。
谢谢
您假设错误的发生是因为页面导航失败。可能是这种情况,但它也可能是一个不同的错误,如 。在这种情况下,您不能只重用 page
对象,而是必须先重新启动浏览器。
前段时间,我crawled roughly 400k pages for testing purposes。总共,我经历了 34 次这些木偶操纵者崩溃,其中一些意外错误导致整个浏览器崩溃。要针对此类崩溃强化您的代码,您需要一种可靠的方式来重新启动浏览器。
代码示例
let browser = await puppeteer.launch(/* .. */);
let page = await browser.newPage();
while(true) {
try {
// your code that might crash
} catch (err) {
try {
await page.reload(); // soft fix
} catch (recoveringErr) {
// unable to reload the page, hard fix
try {
await browser.close();
} catch (err) { // browser close was not necessary
// you might want to log this error
}
browser = await puppeteer.launch(/* .. */);
page = await browser.newPage();
}
}
}
虽然这段代码包含三个嵌套的 try..catch
块可能看起来很可怕,但它可以很好地保持代码 运行ning.
首先,执行您的原始代码。如果最初的问题发生,将尝试调用 page.reload
来解决问题。如果这有效,循环将继续 运行ning。如果这不起作用,将重新启动浏览器。
重启浏览器,我建议先尝试关闭旧浏览器。尽管这可能会失败,但它会清除所有内存并正确处理浏览器对象。根据您的用例,您可能想要记录错误或干脆忽略它。处理旧的浏览器对象后,您可以重新启动浏览器,循环可能会继续。
备选
作为替代方案,您可以使用我的库 puppeteer-cluster,它内置了错误处理功能。如果页面不再可用,该库会自动重新启动浏览器。此外,该库可以 运行 多个并行页面(因为您正在尝试对我假设的服务器进行压力测试)。
根据官方文档,当页面崩溃时会发出一个 'error' 事件,可用于根据应用程序执行某些操作。
page.on('error', err => { /*custom logic to handle the crash*/ });
对于上述特定用例,您可以这样做:
let browser = await puppeteer.launch();
let page = await getNewPage(browser);
while(true){
try{
if (page.isClosed()) {
page = await getNewPage(browser);
}
await page.waitFor(selector)
await page.click(selector)
}
catch(error){
console.log("FE error with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
await page.reload();
continue;
}}
async function getNewPage(browser) {
let page = await browser.newPage();
page.on('error', err => {
if (!page.isClosed()) {
//Close page if not closed already
page.close();
}
}
return page;
}
所以我使用了一个 while 循环,所以我的测试将 运行 持续循环,直到我的后端崩溃。 我已经实现了一个 try and catch(error) 所以任何前端崩溃自动化都会刷新并保持 运行ning
while(true){
try{
await page.waitFor(selector)
await page.click(selector)
}
catch(error){
console.log("FE crashed with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
await page.reload(page);
continue;
}}
所以实际上任何超时错误自动刷新页面并继续循环。 但我收到了不同的崩溃错误
(node:6535) UnhandledPromiseRejectionWarning: Error: Page crashed!
at Page._onTargetCrashed (/home/raymond/node_modules/puppeteer/lib/Page.js:170:24)
at CDPSession.Page.client.on.event (/home/raymond/node_modules/puppeteer/lib/Page.js:125:56)
at CDPSession.emit (events.js:182:13)
at CDPSession._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:200:12)
at Connection._onMessage (/home/raymond/node_modules/puppeteer/lib/Connection.js:112:17)
at _tickCallback (internal/process/next_tick.js:43:7)
at listOnTimeout (timers.js:294:7)
at processTimers (timers.js:268:5)
(node:6535) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
我该如何处理这个错误?如果我手动刷新页面,一切正常。 谢谢
您假设错误的发生是因为页面导航失败。可能是这种情况,但它也可能是一个不同的错误,如 page
对象,而是必须先重新启动浏览器。
前段时间,我crawled roughly 400k pages for testing purposes。总共,我经历了 34 次这些木偶操纵者崩溃,其中一些意外错误导致整个浏览器崩溃。要针对此类崩溃强化您的代码,您需要一种可靠的方式来重新启动浏览器。
代码示例
let browser = await puppeteer.launch(/* .. */);
let page = await browser.newPage();
while(true) {
try {
// your code that might crash
} catch (err) {
try {
await page.reload(); // soft fix
} catch (recoveringErr) {
// unable to reload the page, hard fix
try {
await browser.close();
} catch (err) { // browser close was not necessary
// you might want to log this error
}
browser = await puppeteer.launch(/* .. */);
page = await browser.newPage();
}
}
}
虽然这段代码包含三个嵌套的 try..catch
块可能看起来很可怕,但它可以很好地保持代码 运行ning.
首先,执行您的原始代码。如果最初的问题发生,将尝试调用 page.reload
来解决问题。如果这有效,循环将继续 运行ning。如果这不起作用,将重新启动浏览器。
重启浏览器,我建议先尝试关闭旧浏览器。尽管这可能会失败,但它会清除所有内存并正确处理浏览器对象。根据您的用例,您可能想要记录错误或干脆忽略它。处理旧的浏览器对象后,您可以重新启动浏览器,循环可能会继续。
备选
作为替代方案,您可以使用我的库 puppeteer-cluster,它内置了错误处理功能。如果页面不再可用,该库会自动重新启动浏览器。此外,该库可以 运行 多个并行页面(因为您正在尝试对我假设的服务器进行压力测试)。
根据官方文档,当页面崩溃时会发出一个 'error' 事件,可用于根据应用程序执行某些操作。
page.on('error', err => { /*custom logic to handle the crash*/ });
对于上述特定用例,您可以这样做:
let browser = await puppeteer.launch();
let page = await getNewPage(browser);
while(true){
try{
if (page.isClosed()) {
page = await getNewPage(browser);
}
await page.waitFor(selector)
await page.click(selector)
}
catch(error){
console.log("FE error with\n\n" + error + "\n\nRefreshing page and continuing profile switching")
await page.reload();
continue;
}}
async function getNewPage(browser) {
let page = await browser.newPage();
page.on('error', err => {
if (!page.isClosed()) {
//Close page if not closed already
page.close();
}
}
return page;
}