美文网首页
爬虫利器-Puppeteer初探

爬虫利器-Puppeteer初探

作者: 懒癌程序员 | 来源:发表于2019-04-13 22:49 被阅读0次

    模拟浏览器操作神器Puppeteer初探

    介绍

      刚接触到puppeteer,并不是用来做爬虫,只是想做一个后台数据推送及性能数据抓取的功能,需要模拟登陆内部系统爬取数据截图。一开始想到利用很多方案,像wkhtmltopdf, phantomjs等等,他们都是类浏览器的环境,因为之前使用过,都知道他们或多或少都存在些问题。再后来发现了headless,谷歌的无头浏览器服务,这个最接近真实浏览器的东西(应该说就是个浏览器吧),然后决定采用headless,网上最多的是采用lighthouse作为操作headless的nodejs接口工具,后来看到puppeteer,和lighthouse差不多,但毕竟是谷歌团队自己维护的工具,当然就选择了它,后来看了看,果然还是它用起来比较方便。

      官方对于puppeteer的介绍(翻译过来):

    puppeteer由Chrome团队开发的Node库。它提供了一个高级API来控制无头(或完整)Chrome。它与Phantom和NightmareJS等其他自动化测试库类似,但它只适用于最新版本的Chrome。
    除此之外,Puppeteer还可用于轻松截取屏幕截图,创建PDF,导航页面以及获取有关这些页面的信息。如果您想快速自动化浏览器测试,我建议使用该库。它隐藏了DevTools协议的复杂性,并负责启动Chrome的调试实例等冗余任务>

      看起来很强大对不对,实时上除了无头模式,Puppeteer也可以操作真实浏览器进行工作,你会发现它除了可以做完美的爬虫之外,对于自动化的ui测试也是利器。目前也有了中文文档,使用起来也是极其方便的

    截图

    让我们先来看一下它的api,首先是puppteer对象,用于启动一个Chromium实例,例子:

    const puppeteer = require('puppeteer');
    
    puppeteer.launch().then(async browser => {
      const page = await browser.newPage();
      await page.goto('https://www.google.com');
      // 其他操作...
      await browser.close();
    });
    

      上图实际是打开了一个浏览器应用,lauch方法支持一个对象类型的参数,其中可以指定headless为true还是false,当指定为true是,可以观察到实际行为,在我们测试的时候还是很有用处的,当我们设置为true是可以观察到,browser对象针对的是整个浏览器窗口,而page对象针对的是每个tab页签,当关闭browser对象时,所有page对象都会被销毁,如果想要单独销毁page对象可以调用page.close();
      在实际应用中,page对象是我们最常用的对象,下面是使用page对象打开一个页面并进行截图的例子:

    const puppeteer = require('puppeteer');
    puppeteer.launch().then(async browser => {
      const page = await browser.newPage();
      await page.goto('https://www.baidu.com');
      // 截图...
      await page.screenshot({path:'xx/xx.png',type:'png',quality:100,fullPage:true});
      await browser.close();
    });
    

    这里介绍下截图的几个参数:

    • path:图片存储路径
    • type: 图片格式,默认png
    • quality: 图片质量0-100的值,png格式无效
    • fullpage: 是否截取整个页面,如果不设置,截取的是窗口打开部分,并不是全页面,默认打开的窗口是800x600大小,如果想截取更完美的大小需要调整视窗大小,通过设置launch的defaultViewport参数。

    性能数据获取

    puppteer也支持我们在打开页面时进行一些性能数据的采集,page.metrics()方法可以帮我们获取到页面打开过程中的性能参数:

    puppeteer.launch().then(async browser => {
      const page = await browser.newPage();
      await page.goto('https://www.target.com');
      // 获取页面性能数据...
      const result = await  page.metrics();
      console.log(result);
      await browser.close();
    });
    

    返回结果包括:

    • Timestamp <number> 时间点(when the metrics sample was taken)
    • Documents <number> 页面的documents数量。
    • Frames <number> 页面的iframe数量。
    • JSEventListeners <number> 页面的js事件数量。
    • Nodes <number> 页面的dom节点数量。
    • LayoutCount <number> 整页面或部分页面的布局数量。
    • RecalcStyleCount <number> 页面样式重新计算数量。
    • LayoutDuration <number> 页面布局总时间。
    • RecalcStyleDuration <number> 页面样式重新计算总时间。
    • ScriptDuration <number> 页面js代码执行总时间。
    • TaskDuration <number> 页面任务执行总时间。
    • JSHeapUsedSize <number> 页面占用堆内存大小。
    • JSHeapTotalSize <number> 总的页面堆内存大小。
      还有另外一个api,用于获取我们平时利用浏览器观察页面加载性能的performance视图,它会生成和谷歌浏览器中profile.json一样的一个json数据,我们可以导入浏览器中查看


      屏幕快照 2019-04-13 22.14.01.png

    相关代码:

    puppeteer.launch().then(async browser => {
      const page = await browser.newPage();
      await page.tracing.start({path: 'trace.json'});
      await page.goto('https://www.target.com');
      await page.tracing.stop();
      await browser.close();
      
    });
    

    我们拿到.json文件后也可以访问DevTools Timeline Viewer导入去查看页面加载的详细信息。

    那么对于性能数据来说,我们最常用的手机api就是performance.timing这个对象了,那么我们如果在puppteer中去获取并收集数据呢?下面看一个例子:

    puppeteer.launch().then(async browser => {
      const page = await browser.newPage();
      await page.goto('https://www.target.com',{
      waitUntil:'networkidle0'
      });
      const timing = await page.evaluate(() => (window.performance.timing.toJSON()));
      console.log(timing);
      await browser.close();
      
    });
    

    上面的goto方法内我加了一个参数networkidle0,意思是不再有任何网络连接时触发(至少500毫秒后)后才算页面跳转完成,这么做是为了等页面完全加载结束,获得最准确的数据,在evaluate方法内可以使用page对象内的上下文,也就是当前页面的dom对象都是可以使用的,这样就拿到了timing数据。

    最后

    除此之外,也可以利用puppteer的Coverage对象获取js以及css的代码覆盖率,这里就不做过多介绍了,感兴趣的同学可以自行研究。
    参考文章:https://developers.google.com/web/updates/2017/04/headless-chrome
           https://zhaoqize.github.io/puppeteer-api-zh_CN/#/

    相关文章

      网友评论

          本文标题:爬虫利器-Puppeteer初探

          本文链接:https://www.haomeiwen.com/subject/qyamuqtx.html