puppeteer
puppeteer 是一个通过 DevTools 协议提供高级 API 来控制 chrome,chromium 的 NODE 库; puppeteer 默认运行在 headless 模式, 也可配置后运行在全模式 (non-headless).
puppeteer 可以做什么
大部分在浏览器里手动执行的动作都可以通过 puppeteer 实现! 这里有几个列子来让你开始.
生成页面截图和 PDF.
爬取单页面应用生成提前渲染的内容 (例如 SSR).
自动提交表单, UI 测试, 键盘输入等.
创建最新的自动化的测试环境, 在最新的 chrome 里使用 js 和浏览器的最新特性来运行你的测试.
捕获网站的跟踪时间线以帮助诊断性能问题.
开始
安装
为了在你的项目里使用 puppeteer, 执行:
- npm i puppeteer
- # 或者 yarn add puppeteer
提示: 安装 puppeteer 是, 会下载最新版本的 chromium(Mac 下 170 M, Windows 下 282M)) 以保证 API 正常工作. 要跳过这一步, 请参阅环境变量 ().
例子
提示: puppeteer 需要 Node V6.4.0 及以上版本, 但以下例子中使用了在 Node V7.60 及以上版本中的 async/await .
使用过其它浏览器测试框架的人对 puppeteer 也会熟悉. 创建 Browser 实列, 打开页面, 然后使用 puppeteer API 操作页面.
Example - 导航到 https://example.com 截图后保存为 example.png.
保存如下文件为 example.js
- const puppeteer = require('puppeteer');
- (async () => {
- const browser = await puppeteer.launch();
- const page = await browser.newPage();
- await page.goto('https://example.com');
- await page.screenshot({path: 'example.png'});
- await browser.close();
- })();
执行下面命令 node example.js
puppeteer 设置出时页面尺寸为 800 x 600px , 截图尺寸也是这个. 通过 Page.setViewport() 设置个性化页面尺寸.
Example - 创建 PDF
文件保存为 hn.js
- const puppeteer = require('puppeteer');
- (async () => {
- const browser = await puppeteer.launch();
- const page = await browser.newPage();
- await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
- await page.pdf({path: 'hn.pdf', format: 'A4}');
- await browser.close();
- })();
执行如下命令 node hn.js, 查看 Page.pdf() API 寻找更多关于创建 PDF 的信息.
Example - 在页面上下文中执行 js
保存为 get-dimensions.js
- const puppeteer = require('puppeteer');
- (async () => {
- const browser = await puppeteer.launch();
- const page = await browser.newPage();
- await page.goto('https://example.com');
- const dimensions = await page.evaluate(() => {
- return {
- width: document.documentElement.clientWidth,
- height: document.documentElement.clientHeight,
- deviceScaleFactor: window.devicePixelRatio
- }
- })
- })()
执行如下命令
node get-dimensions.js
, 查看 Page.evaluate() API 获取关于 evaluate 和相关方法 (如: evaluateOnNewDocument, exposeFunction) 的详细信息.
运行时的默认设置
使用无头浏览器模式 (headless)
puppeteer 运行 chromium 在 headless 模式下. 当运行浏览器时设置'headless' 选项使 chromium 运行在全模式下.
const browser = await puppeteer.launch({headless: false});
绑定特定版本的 chromium
默认情况下, puppeteer 下载使用指定版本的 chromium 以保证所有的 API 正常工作. 创建 Browser 实例时指定 executablePath 值来以使用不同浏览器.
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'})
查看 puppeteer.launch() API 了解更多信息.
阅读这篇文章 https://www.howtogeek.com/202825/what’s-the-difference-between-chromium-and-chrome/ 了解 chromium 和 Chrome 的不同, 描述了 Chrome 和 chromium 在 Linux 下的不同.
创建一个新用户
puppeteer 每次运行时先创建一个 chromium 用户, 运行结束后就清除用户信息.
API 文档
探索 API 文档和例子来学习更多.
调试技巧
关闭无头模式 - 有时观看浏览器的显示是有用的. 使浏览器运行在全模式而不是无头模式下, 使用 headless: false:
const browser = await puppeteer.launch({headless: false,})
慢下来 - slowMo 选项减慢 puppeteer 执行速度, 减慢指定的总毫秒数. 这是帮助观察发生什么的另一个途径.
- const browser = await puppeteer.launch({
- headless: false,
- slowMo: 250 // 减慢 puppeteer 250ms
- });
捕获控制台输出 - 监听 console 事件. 当调试 page.evaluate() 内部代码时比较便利.
- page.on('console', msg => console.log('页面 log', msg.text()));
- await page.evaluate(() => console.log(`url is ${location.href}`))
停止执行测试, 在浏览器内使用 debugger
运行 puppeteer 时使用 {devtools: true}:
const browser = await puppeteer.launch({devtools: true});
改变测试超时时间:
- jest:
- jest.setTimeout(100000);
- jasmine:
- jasmine.DEFAULT_TIME_INTERVAL = 100000;
- mocha:
- this.timeout(100000);
- (改变测试时使用 function 不能使用箭头函数)
在 evaluate 内部使用 debugger 语句, 在已存在的 evaluate 环境中添加 debugger
- await page.evaluate(() => {
- debugger;
- });
puppeteer 测试将会停止在上面这条语句, chromium 也将停留在 debugger 模式.
打开详细记录 - 调用所有公共 API 和内部传输协议将会被 puppeteer 命名空间下的 debug 模块记录
- # 基本的详细记录
- env DEBUG="puppeteer:*" node script.js
- # 调试输出可通过命名空间来开关
- env DEBUG="puppeteer:*,-puppeteer:protocol" node script.js # 记录除了协议信息的所有信息
- env DEBUG="puppeteer:session" node script.js # 记录会话协议 (protocol messages)
- env DEBUG="puppeteer:mouse,puppeteer:keyboard" node script.js # 只记录鼠标和键盘 API 调用
- # 传输协议记录的比较繁杂. 下面例子过滤所有网络信息.
- env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
为 puppeteer 贡献
查看贡献指南 https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md 以了解 puppeteer 开发概述
FAQ(常见问题)
谁维护 puppeteer?
Chrome DevTools 团队维护这个库, 同时欢迎大家的参与!
puppeteer 的目标和职责是什么?
这个项目的目标是:
提供一个精简和权威的库以突出 DevTools Protocol 的能力
为类似的测试库提供实现参考. 最终其它框架可以采用 puppeteer 作为基础层.
发展采用 无头, 自动化 浏览器测试.
帮助 DevTools Protocol 新特性做 dogfood 测试, 捕获 bug
寻找浏览器自动化测试的痛点, 然后帮助解决这些差别.
我们采用 chromium 职责来帮助我们驱动产品做决定:
快速: puppeteer 在一个自动化测试页面的性能开销几乎为 0.
安全: puppeteer 在 Chromium 操作过程中, 自动使潜在的恶意页面安全.
稳定: puppeteer 不是脆弱的, 也不会有内存泄漏
简易: puppeteer 提供易用易理解和调试的高级 API.
Puppeteer 是用来取代 Selenium/webDriver 的吗?
不是, 这两个项目因为一些不同的原因都是有价值的.
Selenium/WebDriver 集中于自动跨浏览器; 它的价值在于提供一个在所有主要浏览器里工作的单一标准 API.
Puppeteer 专注于 Chromium; 它的价值在于丰富的功能和高可靠性.
也就是说, 你可以使用 puppeteer 在非 Chromium 浏览器里运行测试. 例如使用 community-driver jest-puppeteer. 虽然 puppeteer 不是你唯一可用的解决方案, 但确实有几分比 web Driver 好的特点:
puppeteer 可以零设置, 附带特定版本的 chromium 是其更好的工作, puppeteer 开始使用非常容易, 在一天结束时只在 chromium 上运行几个测试比不测试好.
puppeteer 是事件驱动架构, 移除大量潜在脆弱环节. 不需要在 puppeteer 脚本调用邪恶的 "sleep(1000)"
puppeteer 默认运行在 headless 模式下, 使得启动非常快. puppeteer V1.5.0 也暴露出浏览器上下文, 使高效的并行执行测试成为可能.
puppeteer 在调试时高亮: 翻转 headless 位 false , 设置 slowMo 选项, 将会看到浏览器的行为. 甚至可以打开 Chrome DevTools 来检查测试环境.
为什么 puppeteer V.xxx 不能和 Chromium V.yyy 一同工作?
puppeteer 作为 chromium 不可分割的一部分. 每个版本的 puppeteer 绑定于一个特定版本的 chromium 以保证 puppeteer 工作.
着并不是通过人工来约束, 许多 puppeteer 工作确实在 chromium 仓库里. 下面时典型故事:
puppeteer bug 报告 https://github.com/GoogleChrome/puppeteer/issues/2709
这原本是 DevTools protocol 的 issue, 然后在 chromium 里修复 https://chromium-review.googlesource.com/c/chromium/src/+/1102154
当 bug 修复后, 滚动更新 chromium 到 puppeteer
然而, 通常人们更愿意将 puppeteer 和官方的 Google Chrome 一同使用. 这种情况下需要选择特定版本的 puppeteer 以使 chromium 版本接近 chrome.
puppeteer 使用哪个版本的 chromium?
在 puppeteer 相关版本的 package.json 文件里查看.
什么是导航 (navigation)?
在 puppeteer 观点中, '导航 (navigation)' 是所有改变页面 URL 的事物. 除了常规的导航外, 在浏览器中点击网络从 web 服务器中获取新文档, 包含 a 标签导航和 history API
在这个 navigation 定义中, puppeteer 和单页面应用无缝衔接.
信任的和不信任的输入事件有什么不同?
在浏览器中输入事件被分为两大类: 信任的和不被信任的.
信任事件: 通过页面的用户接口产生. 例如使用鼠标和键盘.
非信任事件: 通过 web API 产生. 例如 document.createEvent 或者 element.click() 方法.
网站能够区分这两类事件:
使用 Event.isTrusted 事件标志.
嗅探伴随事件. 例如每一个可信任的点击事件之前都是'moussedown' 和'mouseup'事件.
为了自动化的目的, 生成可信任事件是比较重要的. 通过 puppeteer 生成的输入事件都是可信任事件和触发适当的伴随事件. 如果需要非信任事件, 需要通过 page.evaluate 在页面上下文中生成模拟事件:
- await page.evaluate(() => {
- document.querySelector('button[type=submit]').click();
- })
puppeteer 不支持什么特性?
你也许会发现当 puppeteer 控制包含 audio 和 video 的页面时一些行为不是预期的.(例如, 视频播放时截图会失败 https://github.com/GoogleChrome/puppeteer/issues/291 ), 这有以下两个原因:
Puppeteer 是和 chromium 绑定的, 并不是 chrome, 所以 puppeteer 继承了 chromium 所有限制. 这意味着 puppeteer 不支持一些许可格式例如: AAC 和 H.264(然而也可能强制 puppeteer 使用, 当 通过 executablePath 选项使用 chrome 替代 chromium 时. 只有在官方发布的 chrome 支持这些媒体格式时才能使用这些配置)
自从 puppeteer 控制 chromium/chrome 的桌面版后, 只在手机版本里的 chrome 特性不被支持. 这意味着 puppeteer 不支持 http Live Streaming(HLS).
在测试环境中安装运行 puppeteer 时存在问题?
我们有一份针对不同操作系统的排错指南 https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md 需求列表.
如何使用 puppeteer 的提前版本?
npm i --save puppeteer@next
提示: 提前版本可能不稳定和包含 bugs.
还有更多问题, 到哪里寻求帮助?
这里有许多关于 puppeteer 帮助的路径:
- bugtracker https://github.com/GoogleChrome/puppeteer/issues
- stackoverflowh ttps://stackoverflow.com/questions/tagged/puppeteer
- slack channel https://join.slack.com/t/puppeteer/shared_invite/enQtMzU4MjIyMDA5NTM4LTM1OTdkNDhlM2Y4ZGUzZDdjYjM5ZWZlZGFiZjc4MTkyYTVlYzIzYjU5NDIyNzgyMmFiNDFjN2UzNWU0N2ZhZDc
确保在提交你的问题之前在这些频道里搜索问题.
来源: http://www.bubuko.com/infodetail-2733635.html