Javascript 木偶演员不';不要关闭浏览器
我在express/node/ubuntu上运行Puppeter,如下所示:Javascript 木偶演员不';不要关闭浏览器,javascript,express,async-await,puppeteer,Javascript,Express,Async Await,Puppeteer,我在express/node/ubuntu上运行Puppeter,如下所示: var puppeteer = require('puppeteer'); var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { (async () => { headless = tr
var puppeteer = require('puppeteer');
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
(async () => {
headless = true;
const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});
const page = await browser.newPage();
url = req.query.url;
await page.goto(url);
let bodyHTML = await page.evaluate(() => document.body.innerHTML);
res.send(bodyHTML)
await browser.close();
})();
});
多次运行此脚本会留下数百个僵尸:
$ pgrep chrome | wc -l
133
这会阻塞srv
我该如何解决这个问题
从Express JS脚本运行kill
可以解决这个问题吗
除了《木偶演员》和《无头铬合金》之外,还有更好的方法获得同样的效果吗 我用
像这样用try-catch包装您的代码,看看是否有帮助
headless = true;
const browser = await puppeteer.launch({headless: true, args:['--no-sandbox']});
try {
const page = await browser.newPage();
url = req.query.url;
await page.goto(url);
let bodyHTML = await page.evaluate(() => document.body.innerHTML);
res.send(bodyHTML);
await browser.close();
} catch (error) {
console.log(error);
await browser.close();
} finally {
await browser.close();
}
在发送响应之前,请尝试关闭浏览器
var puppeteer = require('puppeteer');
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
(async () => {
headless = true;
const browser = await puppeteer.launch({headless: true});
const page = await browser.newPage();
url = req.query.url;
await page.goto(url);
let bodyHTML = await page.evaluate(() => document.body.innerHTML);
await browser.close();
res.send(bodyHTML);
})();
});
啊!这是一个简单的疏忽。如果出现错误,并且您的
等待browser.close()
从未执行,从而留下僵尸,该怎么办
使用shell.js
似乎是解决这个问题的一种黑客方法
更好的做法是使用try..catch..finally
。原因是您希望关闭浏览器,而不管是否有愉快的流或抛出错误。
与其他代码片段不同,您不必在catch
块和finally
块中尝试关闭浏览器<无论是否抛出错误,始终执行代码>最终块
因此,您的代码应该如下所示:
const puppeteer = require('puppeteer');
const express = require('express');
const router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
(async () => {
try {
headless = true;
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox'],
});
const page = await browser.newPage();
url = req.query.url;
await page.goto(url);
const bodyHTML = await page.evaluate(() => document.body.innerHTML);
res.send(bodyHTML);
} catch (e) {
console.log(e);
} finally {
await browser.close();
}
})();
});
希望这有帮助 我遇到了同样的问题,虽然您的shelljs解决方案确实有效,但它会杀死所有chrome进程,这可能会中断仍在处理请求的进程。这里有一个更好的解决方案,应该是可行的
var puppeteer = require('puppeteer');
var express = require('express');
var router = express.Router();
router.get('/', function (req, res, next) {
(async () => {
await puppeteer.launch({ headless: true }).then(async browser => {
const page = await browser.newPage();
url = req.query.url;
await page.goto(url);
let bodyHTML = await page.evaluate(() => document.body.innerHTML);
await browser.close();
res.send(bodyHTML);
});
})();
});
根据我的经验,在调用close之后,浏览器关闭过程可能需要一些时间。无论如何,您可以检查browser process属性以检查它是否仍然未关闭,并强制终止它
if (browser && browser.process() != null) browser.process().kill('SIGINT');
我还在下面发布我的木偶资源经理的完整代码。看看bw.on('disconnected',async()=>{
const puppeter=require('puppeter-extra'))
const randomUseragent=require('random-useragent');
const StealthPlugin=require('puppeter-extra-plugin-steavy')
const USER_AGENT='Mozilla/5.0(麦金塔;英特尔Mac OS X 10_14_1)AppleWebKit/537.36(KHTML,像Gecko)Chrome/73.0.3683.75 Safari/537.36';
木偶演员。使用(StealthPlugin())
功能资源管理器(loadImages){
让browser=null;
常数this=这个;
设重试次数=0;
让isReleased=false;
this.init=async()=>{
isReleased=false;
重试次数=0;
browser=等待runBrowser();
};
this.release=async()=>{
isReleased=真;
if(browser)等待browser.close();
}
this.createPage=异步(url)=>{
如果(!browser)browser=等待runBrowser();
返回等待创建页面(浏览器、url);
}
异步函数runBrowser(){
const bw=wait puppeter.launch({
无头:是的,
devtools:false,
ignoreHTTPSErrors:是的,
slowMo:0,
参数:['--disable gpu','--no sandbox','--no zygote','--disable setuid sandbox','--disable-accelerated-2d-canvas','--disable dev shm usage',“--proxy server='direct://',“--proxy pass list=*”]
});
on('disconnected',async()=>{
如果(被删除)返回;
console.log(“浏览器崩溃”);
如果(重试){
如果(req.resourceType()='stylesheet'| | req.resourceType()=='font'| | req.resourceType()=='image'){
请求中止();
}否则{
请求继续();
}
});
}
等待页面。评估onnewdocument(()=>{
//通过webdriver检查
Object.defineProperty(导航器,“webdriver”{
get:()=>false,
});
});
等待页面。评估onnewdocument(()=>{
//通过镀铬检查
window.chrome={
运行时:{},
//等等。
};
});
等待页面。评估onnewdocument(()=>{
//通过插件检查
const originalQuery=window.navigator.permissions.query;
return window.navigator.permissions.query=(参数)=>(
parameters.name==“通知”?
Promise.resolve({state:Notification.permission}):
原始查询(参数)
);
});
等待页面。评估onnewdocument(()=>{
//覆盖'plugins'属性以使用自定义getter。
Object.defineProperty(导航器,'插件'{
//对于当前测试,它只需要'length>0',
//但如果必要的话,我们也可以模仿插件。
获取:()=>[1,2,3,4,5],
});
});
等待页面。评估onnewdocument(()=>{
//覆盖'plugins'属性以使用自定义getter。
Object.defineProperty(导航器,'语言'{
获取:()=>['en-US','en'],
});
});
wait page.goto(url,{waitUntil:'networkidle2',超时:0});
返回页面;
}
}
module.exports={ResourceManager}
我使用以下基本设置来运行木偶演员:
const puppeter=require(“木偶演员”);
让浏览器;
(异步()=>{
browser=wait puppeter.launch();
const[page]=wait browser.pages();
/*使用页面*/
})()
.catch(err=>console.error(err))
.finally(异步()=>等待browser.close())
;
在这里,finally
块保证浏览器将正确关闭,无论是否抛出错误。错误会被记录(如果需要)。我喜欢.catch
和。finally
作为链接调用,因为主线木偶程序代码更平坦一层,但这实现了同样的功能:
const puppeter=require(“木偶演员”);
(异步()=>{
让浏览器;
试一试{
browser=wait puppeter.launch();
const[page]=wait browser.pages();
/*使用页面*/
}
捕捉(错误){
if (browser && browser.process() != null) browser.process().kill('SIGINT');