puppeteer循环遍历cpu飙升99%导致服务器无响应假死

发布于 2022-09-11 19:46:24 字数 2210 浏览 19 评论 0

问题描述

是这样,由于业务需要,在一个国外网站上爬取数据,服务器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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

饮湿 2022-09-18 19:46:24

如果没有特殊需求, 可以尝试只 puppeteer.launch() 一次, 打开一个 browser 实例, 然后循环 browser.newPage() 抓取数据.

另外,也可以检查一下代码是否有正确 browser.close() 退出不需要的 browser 实例, 看你代码没贴出来, 不知道你有没有写.

空‖城人不在 2022-09-18 19:46:24

换成循环打开 page 效果如何?

如若梦似彩虹 2022-09-18 19:46:24

这么久了楼主解决了嘛,最近我也试着用puppeteer写爬虫。
我是lauch一个实例,然后循环生成page,并在结束时close掉。
但是,发现一开始还挺快的,后面cpu占用极高,速度也变得非常缓慢起来。
我试了两种方式都会这样:

  1. new一个page,然后循环goto
  2. 遍历new很多个page,然后结束关掉。
    都会卡顿...
意中人 2022-09-18 19:46:24

我目前做个事打开两个浏览器作为连接池,不用关闭,一直开启,每次事打开一个tab页面,然后执行完关闭,但是我这个服务是一直跑,数量多了cpu也是飙升,有啥好的解决办法嘛?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文