爬虫利器-Puppeteer初探

2019-04-13  本文已影响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();
});

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

性能数据获取

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();
});

返回结果包括:

相关代码:

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/#/

上一篇 下一篇

猜你喜欢

热点阅读