是什么?

就是我们平时用的浏览器,完整的浏览器,只是不显示界面(如果你需要也可以设置显示),完整的渲染html,js,css.启动速度快,通常用于测试或者爬虫工具.

有哪些?

无头浏览器很多,包括但不限于:

  • PhantomJS, 基于 Webkit
  • SlimerJS, 基于 Gecko
  • HtmlUnit, 基于 Rhnio
  • TrifleJS, 基于 Trident
  • Splash, 基于 Webkit

但是上边这些基本都不推荐使用,最新,最好用的应该是谷歌的无头浏览器(headless Chrome), 他基于 Chrome DevTools protocol 提供了不少高度封装的接口方便我们控制浏览器。

puppeteer

中文翻译:木偶,很形象的解释.
通过chrome的devTools 协议操作,调用谷歌浏览器,进行页面渲染或模拟人工操作.
使用nodejs语法做的api,方便快捷.因为nodejs本身就是js嘛,上手很容易.

快速上手

需要环境: nodejs v8版本以上
打开google.com,然后搜一个关键词

示例动图:
808030a25211446b8903281b9427c321 .gif

  1. /**
  2. * 在无头浏览器自动填写表单并提交
  3. */
  4. const puppeteer = require('puppeteer');
  5. const autoSubmitForm = async (url, path) => {
  6. // 启动浏览器
  7. const browser = await puppeteer.launch({
  8. // 关闭无头模式,方便我们看到这个无头浏览器执行的过程
  9. headless: false,
  10. });
  11. // 打开页面
  12. const page = await browser.newPage();
  13. // 设置浏览器视窗
  14. page.setViewport({
  15. width: 1376,
  16. height: 768,
  17. });
  18. // 地址栏输入网页地址
  19. await page.goto(url, {
  20. waitUntil: 'networkidle', // 等待网络状态为空闲的时候才继续执行
  21. });
  22. // await page.click('#lst-ib');
  23. await page.focus('#lst-ib');
  24. await page.type('辣子鸡', {
  25. delay: 1000, // 控制 keypress 也就是每个字母输入的间隔
  26. });
  27. await page.press('Enter');
  28. // 不关闭浏览器,看看效果
  29. // await browser.close();
  30. };
  31. module.exports = autoSubmitForm;
  32. if (require.main === module) {
  33. // for test
  34. autoSubmitForm('http://google.com');
  35. }

Puppeteer 官方文档

官方地址

概述

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer API 是分层次的,反映了浏览器结构。

注意:在下面的图表中,浅色框体内容目前不在 Puppeteer 中体现。

无头浏览器 Puppeteer - 图2

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

    一些概念和名词

    puppeteer vs puppeteer-core

    自 v1.7.0 以来的每个版本我们都发布了两个包:

  • puppeteer

  • puppeteer-core

puppeteer 是浏览器自动化的 产品。安装后,它会下载一个版本的 Chromium,然后使用puppeteer-core 驱动工作。作为最终用户产品,puppeteer 支持一堆方便的 PUPPETEER_* env 变量来调整行为。
puppeteer-core 是一个 来帮助驱动任何支持 DevTools 协议的东西。puppeteer-core 在安装时不会下载 Chromium。作为一个库,puppeteer-core 是完全是通过其编程接口驱动的并忽略所有PUPPETEER_* env 变量。
总结一下,puppeteer-corepuppeteer 不同的地方:

  • puppeteer-core 在安装时不会自动下载 Chromium。
  • puppeteer-core忽略所有的 PUPPETEER_* env 变量.

在大多数情况下,你可以使用 puppeteer 包。
然而, 如果是下面这些情况那你需要使用 puppeteer-core:

  • 你正在构建 DevTools 协议顶部的另一个最终用户产品或库。例如,可以使用 puppeteer-core 构建 PDF 生成器并编写下载 headless_shell 的自定义install.js脚本而不是 Chromium 来节省磁盘空间。
  • 你正在打包 Puppeteer 用在 Chrome 扩展应用或浏览器中以使用 DevTools 协议,因为下载额外的 Chromium 二进制文件不是必须的。

当使用 puppeteer-core 时,使用下面这行代替原来的使用方式:

  1. const puppeteer = require('puppeteer-core');

环境变量 Environment Variables

Puppeteer 寻找某些环境变量来帮助其操作。 如果 puppeteer 在环境中没有找到它们,这些变量的小写变体将从 npm 配置 中使用。

  • HTTP_PROXY, HTTPS_PROXY, NO_PROXY - 定义用于下载和运行 Chromium 的 HTTP 代理设置。
  • PUPPETEER_SKIP_CHROMIUM_DOWNLOAD - 请勿在安装步骤中下载绑定的 Chromium。
  • PUPPETEER_DOWNLOAD_HOST - 覆盖用于下载 Chromium 的 URL 的主机部分。
  • PUPPETEER_CHROMIUM_REVISION - 在安装步骤中指定一个你喜欢 puppeteer 使用的特定版本的 Chromium。
  • PUPPETEER_EXECUTABLE_PATH - 指定一个 Chrome 或者 Chromium 的可执行路径,会被用于 puppeteer.launch。具体关于可执行路径参数的意义,可参考puppeteer.launch([options])

    NOTE 在使用 puppeteer-core 时,上述环境变量中以 PUPPETEER_* 开头的会被忽略.

错误处理 Error handling

如果 Puppeteer 方法无法执行一个请求,就会抛出一个错误。例如,page.waitForSelector(selector[, options]) 选择器如果在给定的时间范围内无法匹配节点,就会失败。
对于某些类型的错误,Puppeteer 使用特定的错误类处理。这些类可以通过 require('puppeteer/Errors') 获得。
支持的类列表:

一个处理超时错误的例子:

  1. const {TimeoutError} = require('puppeteer/Errors');
  2. // ...
  3. try {
  4. await page.waitForSelector('.foo');
  5. } catch (e) {
  6. if (e instanceof TimeoutError) {
  7. // 如果超时,做一些处理。
  8. }
  9. }

测试浏览器的扩展 Working with Chrome Extensions

Puppeteer 可以用来测试 Chrome 扩展

注意 Chrome / Chromium 扩展当前只能在非无头模式下使用。

下面的代码用来处理扩展的 background page,该扩展的代码在 ./my-extension:

  1. const puppeteer = require('puppeteer');
  2. (async () => {
  3. const pathToExtension = require('path').join(__dirname, 'my-extension');
  4. const browser = puppeteer.launch({
  5. headless: false,
  6. args: [
  7. `--disable-extensions-except=${pathToExtension}`,
  8. `--load-extension=${pathToExtension}`
  9. ]
  10. });
  11. const targets = await browser.targets();
  12. const backgroundPageTarget = targets.find(target => target.type() === 'background_page');
  13. const backgroundPage = await backgroundPageTarget.page();
  14. // 像处理任何其他页面一样测试背景页面。
  15. await browser.close();
  16. })();

注意 目前还无法测试扩展弹出窗口或内容脚本。