基本介绍
Puppeteer 是一个 node 库,他提供了一组通过 DevTools Protocol
用来操纵 Chrome 和 Chromium 的高层次 API。
Puppeteer 可以用来做几乎所有可以手动在浏览器里面做的事情,目前主要用来做如下工作:
- 利用网页生成 PDF、图片
- 爬取SPA应用,并生成预渲染内容(即“SSR” 服务端渲染)
- 自动化表单提交、UI测试、键盘输入等
- 创建一个最新的自动化测试环境。可以直接在最新版 Chrome 中测试最新的 JavaScript 和 浏览器功能。
- 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题
- 测试 Chrome 插件
Puppeteer 是 Chrome 官方团队进行维护的,因此相较于其他竞品例如 PhantomJS 有着更好的稳定性和前景。
安装
Puppeteer 需要 NodeJS 版本不低于6.4.0,但是为了使用 async / await 机制,NodeJS 版本建议不低于 7.6.0。
npm install puppeteer --save
通过如上命令安装 Puppeteer 时同时会下载最新版 Chromium。
生成 PDF
使用 Puppeteer 生成 PDF 只需要几行代码。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.pdf({path: 'example.pdf'});
await browser.close();
})();
大概解读一下上面几行代码:
- 通过 puppeteer.launch() 创建一个浏览器实例 Browser 对象
- 通过 Browser 对象创建页面 Page 对象
- 调用 page.goto() 跳转到指定的页面
- 调用 page.pdf() 生成 PDF 文件
- 关闭浏览器
大部分方法都可以通过设定参数来来达到定制化效果
- puppeteer.launch() 方法可以通过设定 executablePath 来指定运行的 Chrome 或 Chromium 路径。
- page.goto() 方法跟浏览器一样可以指定一个网页 url 或者本地文件。
- page.pdf() 可以指定打印格式,自定义页头页尾等。
每个方法的详细 API 可以通过官方 API 文档进行查询。
不难发现,通过 Puppeteer 生成 PDF 的步骤跟手动使用 Chrome 浏览器把网页打印成 PDF 格式的步骤几乎一样。可见其设计哲学更符合人类的使用习惯,更自然。
在 Docker 中使用
在 Docker 中使用 Puppeteer 稍显复杂,因为其 node 库中自带的 Chromium 缺少一些依赖。这些依赖在桌面环境中一般都已自带,但是在 Docker 的 node 源镜像例如 node-alpine 或者 node-slim 是缺失的。所以,在 Docker 中使用 Puppeteer 需要首先安装这些缺失的依赖。
以 node-aipine 源镜像为例
FROM node:9-alpine
RUN apk update && apk upgrade && \
echo http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories && \
echo http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories && \
apk add --no-cache \
zlib-dev \
xvfb \
xorg-server \
dbus \
ttf-freefont \
chromium \
nss \
ca-certificates \
dumb-init
这些命令会安装 Chromium 以及其必要的依赖。安装 Chromium 是因为可以以 node-alpine 或者 node-slim 镜像为基础,安装好 Chromium 和其他依赖以后打包新的 image 作为项目中使用的 docker 源。这样可以极大的减少 docker build 的时间。
加入下面环境变量可以使得 Puppeteer 跳过下载自带的 Chromium。
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
程序使用 Puppeteer 时需要加入如下参数
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium-browser',
args: ['--disable-dev-shm-usage', '--no-sandbox']
});
executablePath 参数指定的是 aipine 版 Chromium 的启动路径。
args 参数中的 --disable-dev-shm-usage
是为了解决 Docker 中 /dev/shm
共享内存太小不足以支持 Chromium 运行的问题,详见 TIPS。
args 参数中的 --no-sandbox
是为了避免 Chromium 在 Linux 内核中由 sandbox 导致的启动问题。
网友评论