gpt4 book ai didi

node.js - Puppeteer - 协议(protocol)错误(Page.navigate): Target closed

转载 作者:搜寻专家 更新时间:2023-10-31 22:42:45 31 4
gpt4 key购买 nike

正如您在下面的示例代码中看到的,我将 Puppeteer 与 Node 中的一组工作人员一起使用,以通过给定的 URL 运行多个网站截图请求:

const cluster = require('cluster');
const express = require('express');
const bodyParser = require('body-parser');
const puppeteer = require('puppeteer');

async function getScreenshot(domain) {
let screenshot;
const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] });
const page = await browser.newPage();

try {
await page.goto('http://' + domain + '/', { timeout: 60000, waitUntil: 'networkidle2' });
} catch (error) {
try {
await page.goto('http://' + domain + '/', { timeout: 120000, waitUntil: 'networkidle2' });
screenshot = await page.screenshot({ type: 'png', encoding: 'base64' });
} catch (error) {
console.error('Connecting to: ' + domain + ' failed due to: ' + error);
}

await page.close();
await browser.close();

return screenshot;
}

if (cluster.isMaster) {
const numOfWorkers = require('os').cpus().length;
for (let worker = 0; worker < numOfWorkers; worker++) {
cluster.fork();
}

cluster.on('exit', function (worker, code, signal) {
console.debug('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
Cluster.fork();
});

cluster.on('message', function (handler, msg) {
console.debug('Worker: ' + handler.process.pid + ' has finished working on ' + msg.domain + '. Exiting...');
if (Cluster.workers[handler.id]) {
Cluster.workers[handler.id].kill('SIGTERM');
}
});
} else {
const app = express();
app.use(bodyParser.json());
app.listen(80, function() {
console.debug('Worker ' + process.pid + ' is listening to incoming messages');
});

app.post('/screenshot', (req, res) => {
const domain = req.body.domain;

getScreenshot(domain)
.then((screenshot) =>
try {
process.send({ domain: domain });
} catch (error) {
console.error('Error while exiting worker ' + process.pid + ' due to: ' + error);
}

res.status(200).json({ screenshot: screenshot });
})
.catch((error) => {
try {
process.send({ domain: domain });
} catch (error) {
console.error('Error while exiting worker ' + process.pid + ' due to: ' + error);
}

res.status(500).json({ error: error });
});
});
}

一些解释:

  1. 每次请求到达时,worker 都会处理它并在最后杀死自己
  2. 每个工作人员创建一个包含单个页面的新浏览器实例,如果页面加载时间超过 60 秒,它将重试重新加载它(在同一页面中,因为可能已经加载了一些资源)超时为 120 秒
  3. 完成后页面和浏览器都将关闭

我的问题是某些合法域出现我无法解释的错误:

Error: Protocol error (Page.navigate): Target closed.
Error: Protocol error (Runtime.callFunctionOn): Session closed. Most likely the page has been closed.

我在一些 git 问题(我现在找不到)上读到,当页面重定向并在开头添加“www”时可能会发生这种情况,但我希望这是错误的...有什么我想念的吗?

最佳答案

“目标关闭”是什么意思

当您通过 puppeteer.launch 启动浏览器时,它会启动浏览器并连接到它。从那里开始,您在打开的浏览器上执行的任何功能(如 page.goto)都将通过 Chrome DevTools Protocol 发送到浏览器。在此上下文中,目标表示选项卡。

当您尝试运行函数但目标(选项卡)已关闭时,将引发目标已关闭异常。

类似的错误信息

最近更改了错误消息以提供更有意义的信息。它现在给出以下消息:

Error: Protocol error (Target.activateTarget): Session closed. Most likely the page has been closed.


为什么会这样

发生这种情况的原因有多种。

  • 您使用了一个已经关闭的资源

    很可能,您看到此消息是因为您关闭了选项卡/浏览器并仍在尝试使用该资源。举个简单的例子:

    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    await browser.close();
    await page.goto('http://www.google.com');

    在这种情况下,浏览器已关闭,之后调用了 page.goto,导致了错误消息。大多数时候,它不会那么明显。可能错误处理程序已经在清理任务期间关闭了页面,而您的脚本仍在抓取。

  • 浏览器崩溃或无法初始化

    我也每隔几百个请求就会遇到这种情况。有一个 issue about this在 puppeteer 存储库上也是如此。当您使用大量内存或 CPU 能力时,情况似乎就是如此。也许你产生了很多浏览器?在这些情况下,浏览器可能会崩溃或断开连接。

    我没有找到解决此问题的“ Elixir ”。但您可能想查看图书馆 puppeteer-cluster (免责声明:我是作者)处理此类错误情况,让您在错误发生时重试 URL。它还可以管理浏览器实例池并简化您的代码。

关于node.js - Puppeteer - 协议(protocol)错误(Page.navigate): Target closed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51629151/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com