简介

Chrome 59版本之后开始搭载Headless Chrome,Headless Chrome 是 Chrome 浏览器的无界面形态,在不使用UI界面的情况下,可以访问并运行网页。通过Headless,就可以很方便的在服务器上测试网页和爬虫了~
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer API 是分层次的,反映了浏览器结构。来源
image.png

  • Puppeteer 使用 DevTools 协议 与浏览器进行通信。
  • Browser 实例可以拥有浏览器上下文。
  • BrowserContext 实例定义了一个浏览会话并可拥有多个页面。
  • Page 至少有一个框架:主框架。 可能还有其他框架由 iframe框架标签 创建。
  • frame 至少有一个执行上下文 - 默认的执行上下文 - 框架的 JavaScript 被执行。 一个框架可能有额外的与 扩展关联的执行上下文。
  • Worker 具有单一执行上下文,并且便于与 WebWorkers 进行交互。

安装和使用

安装puppeteer模块:

  1. npm install puppeteer --save

在安装puppeteer模块的时候,会自动安装Chromium,但是还不能直接使用,还需要安装一些依赖项:

  1. #依赖库
  2. yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y
  3. #字体
  4. yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y

到这里,我们来运行官方给的demo:

  1. const puppeteer = require('puppeteer');
  2. (async () => {
  3. const browser = await puppeteer.launch();
  4. const page = await browser.newPage();
  5. await page.goto('https://example.com');
  6. await page.screenshot({path: 'example.png'});
  7. await browser.close();
  8. })();

发现还是不能正常运行,原因是Chrome为了保护主机环境不受不受信任的Web内容的影响,使用了多层沙盒。为了使其正常工作,应该首先在主机配置好沙盒。如果没有好的沙盒供Chrome使用,它将崩溃,并出现错误:没有可用的沙盒!
启动的时候可以通过参数来让Chrome不使用沙盒:

  1. const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});

我们再运行程序,发现可以正常运行了。我们修改一下代码,来解析一个出一个视频播放页的播放地址:

  1. const puppeteer = require('puppeteer');
  2. (async function() {
  3. const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
  4. const page = await browser.newPage();
  5. // 设置浏览器 Viewport 和 UA
  6. await page.setViewport({
  7. width: 375,
  8. height: 667
  9. });
  10. await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1');
  11. // 视频播放页地址
  12. let page_url = 'http://hztv.hangzhou.com.cn/video.php?video_id=40202';
  13. await page.goto(page_url).catch((err) => {
  14. console.log('get page err', page_url, err);
  15. });
  16. // 延迟1秒~让页面的js完全执行
  17. await dalay(1000);
  18. const data = await page.evaluate(() => {
  19. // 注意,这里写的js代码运行在浏览器端
  20. let videoUrl = '';
  21. let video = document.getElementsByTagName('video')[0];
  22. if (video && video.src) {
  23. videoUrl = video.src;
  24. } else {
  25. let source = document.getElementsByTagName('source')[0];
  26. videoUrl = source && source.src;
  27. }
  28. return {
  29. title: document.title,
  30. videoUrl: videoUrl,
  31. };
  32. }).catch((err) => {
  33. console.log('catch err', err);
  34. });
  35. // 输出信息
  36. console.log(data);
  37. // 关闭页面和浏览器
  38. await page.close();
  39. await browser.close();
  40. })();
  41. async function dalay(time) {
  42. return new Promise((resolve, reject) => {
  43. setTimeout(() => {
  44. resolve();
  45. }, time);
  46. });
  47. }

运行之后解析成功,输出如下:

  1. { title: '杭网宽频-车祸现场停车看热闹 司机被罚款400元 记18分',
  2. videoUrl: 'http://hzwsp.hangzhou.com.cn/hztv/transcode/2018/11/27/5bfc99f5b99f3_fluency.mp4' }

API:https://github.com/GoogleChrome/puppeteer/blob/v1.15.0/docs/api.md
中文API:https://zhaoqize.github.io/puppeteer-api-zh_CN/