爬虫利器-Puppeteer初探

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

介绍

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

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

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

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

截图

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

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对象打开一个页面并进行截图的例子:git

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();
});
复制代码

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

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

性能数据获取

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

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();
});
复制代码

返回结果包括:chrome

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

相关代码:json

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的代码覆盖率,这里就不作过多介绍了,感兴趣的同窗能够自行研究。 参考文章:developers.google.com/web/updates…        zhaoqize.github.io/puppeteer-a…

相关文章
相关标签/搜索