puppeteer循环遍历cpu飙升99%导致服务器无响应假死
问题描述
是这样,由于业务需要,在一个国外网站上爬取数据,服务器CentOS,数据库MySQL
由于擅长js所以选择的是谷歌的puppeteer无头浏览器爬取数据.业务要求爬取数据的即时性在两分钟左右,所以爬取频率较高(循环按序爬取4-5个页面检查更新存入数据库,30秒一个页面)
我的处理是心跳每隔30秒抓取一个页面数据进行处理,国外网站较慢所以常常超时故增加了超时处理(30秒自动取消本次访问但仍然能抓取到目标数据,当然这些不重要)
_getHtmls方法是心跳循环执行的
相关代码
const fs = require("fs");
const puppeteer = require('puppeteer');
const {TimeoutError} = require('puppeteer/Errors');
async function _getHtmls(url,callback){
if( !url ){
console.log("url有问题",url);
return false;
}
console.log("_getHtmls url", url);
let htmlsName = url.match( /[^/]+(?!.*\/)/ )[0];
console.log("htmls文件名:" , htmlsName );//作为htmls文件名
//拉取url的htmls 写入log文件
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
headless: false,
timeout: 30000
});
const page = await browser.newPage();
try {
await page.goto(url, {});
await page.waitForSelector("[dir='ltr']");//#leaderboard+script
await page.waitForSelector("#leaderboard+script");
domInnerHTML = await page.$eval("html", dom => dom.innerHTML);
// await console.log(domInnerHTML);
console.log("未超时");
} catch (e) {
if (e instanceof TimeoutError) {
await page.waitForSelector("[dir='ltr']");
await page.waitForSelector("#leaderboard+script");
domInnerHTML = await page.$eval("html", dom => dom.innerHTML);
// await console.log(domInnerHTML);
console.log("超时了");
}
}
}
问题描述
在服务器top观察,大概几分钟,cpu飙升99%导致服务器无响应假死,此bug100%稳定重现,吃内存的进程就是chrome(即puppeteer)
最终的解决办法是用npm-request+cherrio进行数据爬取和分析,但是这不是我想规避问题的初衷,问题一直困扰着我.
希望大神帮忙指导一下我问题出在哪里?别的代码不重要如有需要我再贴出来,我只想指导puppeteer为什么内存飙升那么严重,是不是我不断puppeteer.launch导致?正确的处理方式是不是puppeteer.launch一次然后循环browser.newPage()?
希望写一个小小的实例,我真的是查了好些好些资料也找不到关于多个newPage详细的操作,几乎都是操作一个页面而且也不循环抓取数据.
望不吝赐教,感激不尽!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果没有特殊需求, 可以尝试只 puppeteer.launch() 一次, 打开一个 browser 实例, 然后循环 browser.newPage() 抓取数据.
另外,也可以检查一下代码是否有正确 browser.close() 退出不需要的 browser 实例, 看你代码没贴出来, 不知道你有没有写.
换成循环打开 page 效果如何?
这么久了楼主解决了嘛,最近我也试着用
puppeteer
写爬虫。我是
lauch
一个实例,然后循环生成page
,并在结束时close
掉。但是,发现一开始还挺快的,后面
cpu
占用极高,速度也变得非常缓慢起来。我试了两种方式都会这样:
new
一个page
,然后循环goto
;new
很多个page
,然后结束关掉。都会卡顿...
我目前做个事打开两个浏览器作为连接池,不用关闭,一直开启,每次事打开一个tab页面,然后执行完关闭,但是我这个服务是一直跑,数量多了cpu也是飙升,有啥好的解决办法嘛?