github 地址:
https://github.com/GoogleChrome/puppeteer
文档地址:
https://pptr.dev/
中文文档地址:
https://zhaoqize.github.io/puppeteer-api-zh_CN/#/
简单说下这个东西是啥:
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行 non-headless 模式。
所谓的 headless 就是,以命令行接口的方式,chrome 应该是给我们暴露出了一些接口方法,我们可以通过命令行来控制浏览器的一些操作了。
headless 模式:
https://developers.google.com/web/updates/2017/04/headless-chrome
我们可以用来做什么:
1) 生成网页截图或者 PDF
2) 高级爬虫,可以爬取大量异步渲染内容的网页
3) 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试
4) 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题
参考别人的文档,提到了:
PhantomJS 和 selenium-webdriver
之前记得想做网页截图,html 生成图片,好像好多教程说的就是这个 PhantomJS,一直没用过。他们应该和 puppeteer 是一类,但是 puppeteer 应该是具有更大的优势,谷歌开发团队维护,而且支持各种 CSS3 和 HTML5 特性吧。
好了,不说废话了,大家百度一下,就能搜到大量的 puppeteer 介绍,比我说的都好,开始笔记:
1.安装:
npm i puppeteer/yarn add puppeteer
注意:
安装同时,会根据我们的操作系统,下载最新版本的 Chromium,来确保可以使用这些 API。(下载异常缓慢,可能因为被墙)
如果想跳过下载 Chromium,可以查看 『环境变量』来设置。(应该是:PUPPETEER_SKIP_CHROMIUM_DOWNLOAD)
/*
环境变量:
Puppeteer 根据某些环境变量来辅助其操作。在安装期间,如果 Puppeteer 没有在环境中找到这些变量,将会从 npm config 文件中,来使用的这些变量(npm 中的配置变量是环境变量的小写形式)。
HTTP_PROXY, HTTPS_PROXY, NO_PROXY - 定义用于下载和运行 Chromium 的 HTTP 代理设置
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD - 安装期间,不下载绑定的 Chromium
PUPPETEER_DOWNLOAD_HOST - 重新指定下载 Chromium 的 URL 地址
PUPPETEER_CHROMIUM_REVISION - 指定我们想要使用的 Chromium 版本,确保路径有效
PUPPETEER_EXECUTABLE_PATH - 应该是全局设置 'puppeteer.launch' 的启动路径
注意:
PUPPETEER_* 的环境变量,在 puppeteer-core 包中都无效
*/
2.puppeteer-core
1.7.0 版本开始,发布一个 puppeteer-core 包,这个包默认不会下载 Chromium
npm i puppeteer-core/yarn add puppeteer-core
puppeteer-core 是一个轻量级的 Puppeteer,用于启动现有浏览器安装,或链接一个远程浏览器
/*
puppeteer vs puppeteer-core
puppeteer 是一个浏览器自动化产品。安装时,它会下载一个指定版本的 Chromium,该 Chromium 之后会被 puppeteer-core 来驱动。作为一个用户端产品,puppeteer 提供了一系列的 PUPPETEER_* 环境变量,来调整行为。
puppeteer-core 是一个类库,用来帮助驱动任何支持 DevTools 协议的软件。puppeteer-core 安装时,不会下载 Chromium。作为一个类库,puppeteer-core 完全通过其编程接口驱动,并忽略所有的 PUPPETEER_* 环境变量。
总而言之,puppeteer 和 puppeteer-core 的区别是:
puppeteer-core 安装时,不自动下载 Chromium
puppeteer-core 忽略所有的 PUPPETEER_* 环境变量
在大多数的情况下,使用 puppeteer 包就足够了。
然而,以下情况,我们可以使用 puppeteer-core:
当我们正在构建 DevTools 协议顶部的另一个用户端产品或类库。例如:可以使用 puppeteer-core 来构建 PDF 生成器,并编写一个自定义的 install.js 脚本来下载 headless_shell,而不用下载 Chromium 以节省磁盘空间。
你正在捆绑 Puppeteer 以在 Chrome 扩展/浏览器 中使用 DevTools 协议,不需要下载额外的 Chromium 二进制文件
当使用 puppeteer-core,记得修改 'include' 引入:
const puppeteer = require('puppeteer-core');
*/
3.使用
Puppeteer 至少需要 Node v6.4.0,下面示例中的 async/await,仅在 Node v7.6.0 之后的版本被支持
Puppeteer 使用起来和其他测试框架类似。创建一个 Br owser 示例,打开页面,然后使用 Puppeteer API
示例1 - 跳转到 https://example.com 并保存截图至 example.png
vim example.js
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com');
await page.screenshot({
path: 'example.png'
});
await browser.close();
})();
注意:
Puppeteer 初始化的屏幕大小默认为 800px x 600px。但是这个尺寸可以通过 Page.setViewport() 设置。
node example.js
示例2 - 创建一个 PDF
vim pdf.js
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com', {
waitUntil: 'networkidle2'
});
await page.pdf({
path: 'example.pdf',
format: 'A4',
});
await browser.close();
})();
node pdf.js
示例3 - 在页面中执行脚本,获取页面 viewport 的尺寸
vim get-dimensions.js
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com');
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio,
}
});
console.log('Dimensions:', dimensions);
await browser.close();
})();
node get-dimensions.js
4.默认运行时设置
1>使用 Headless 模式
Puppeteer 默认以 headless 模式启动 Chromium。为了启动完全版本的 Chromium,当启动浏览器时,设置 'headless' 选项:
const browser = await puppeteer.launch({
headless: false, // 默认是 true
});
2>运行一个指定版本的 Chromium
默认情况下,Puppeteer 下载并使用特定版本的 Chromium 以及其 API 保证开箱即用。 如果要将 Puppeteer 与不同版本的 Chrome 或 Chromium 一起使用,在创建Browser实例时传入 Chromium 可执行文件的路径即可
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
/*
Chrome 和 Chromium 的区别:
官方推荐的文章:
https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/
随便搜了个:
https://www.cnblogs.com/EasonJim/p/8076507.html
*/
3>创建一个新的用户配置文件
Puppeteer 会创建自己的 Chromium 用户配置文件,它会在每次运行时清理。
5.调试建议
1>关闭 headless 模式 - 有时候查看浏览器展示的内容很有帮助。
const browser = await puppeteer.launch({headless: false});
2>执行慢一点 - 通过设置 slowMo 选项,可以让 Puppeteer 操作慢下来,单位为:毫秒。这是帮助我们查看运行时发生了什么的另一种方式。
const browser = await puppeteer.launch({
headless: false,
slowMo: 250 // slow down by 250ms
});
3>捕获 console 控制台输出 - 可以监听 console 事件。当在 page.evaluate() 调试代码时,这也很方便:
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
await page.evaluate(() => console.log(`url is ${location.href}`));
4>停止测试执行并在浏览器中使用调试器
1)当启动 Puppeteer 使用 {devtools: true}
const browser = await puppeteer.launch({devtools: true});
2)改变默认测试超时时间:
jest: jest.setTimeout(100000);
jasmine: jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
mocha: this.timeout(100000);(别忘记改变测试来使用 function and not '=>')
3)添加一条包含 'debugger' 的 evaluate 语句,或在一个已存在的语句中添加 debugger
await page.evaluate(() => {debugger;});
现在,测试将在上面的evaluate语句中停止执行,并且chrome将在调试模式下停止。
5.启用详细日志记录 - 通过 puppeteer 命名空间下的 debug 模块,内部的 DevTools 协议流量,将会被记录下来
# 基本的详细日志记录
env DEBUG="puppeteer:*" node script.js
# 通过命名空间可以启用/禁用 debug 输出
env DEBUG="puppeteer:protocol" node script.js // 记录协议 connenct 信息
env DEBUG="puppeteer:session" node script.js // 记录协议 session 信息
# 协议流量可能相当烦人。该示例会过滤掉所有的网络域名信息
env DEBUG="puppeteer:session" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
6.使用 ndb,轻松调试我们的 Puppeteer(node) 代码
npm install -g ndb(或者甚至更好,使用 npx)
在我们的 Puppeteer(node) 代码中,添加 'debugger'
在运行测试命令前,添加 'ndb'(或 npx ndb),例如:
ndb jest / ndb mocha(或 npx ndb jest / npx ndb mocha)
可算是 看文档+翻译 大体完成,接着,开始安装并测试使用:
1.安装,下载 Chromium 非常慢,可能也下载不下来,应该是被墙了,需要 NPM 配置成国内镜像源。
https://github.com/GoogleChrome/puppeteer/issues/1597
淘宝镜像
好像还有一个软件,可以切换 NPM 镜像源,叫做:
nrm
我参考的上面链接,设置的:
npm config set puppeteer_download_host=https://npm.taobao.org/mirrors
2.只是使用上面最基础的示例,进行测试了下,发现图片和 PDF 的样式,有点问题啊,可能是没有好好熟悉 API,进行配置吧。
现在的效果,还不如之前的 laravel-snappy 生成的效果好,有时间这个东西,需好好研究下!