Puppeteer入门教程
Puppeteer 简介
Puppeteer 是一个node库,他提供了很多操纵Chrome的API, 让我们可以通过 javascript
模拟人工操作浏览器。既然是浏览器,那么我们在浏览器上做的事情, 都可以通过 Puppeteer切换成自动操作;具体 Puppeteer 可以做
- 生成网页截图或者 PDF
- 高级爬虫,可以爬取大量异步渲染内容的网页
- 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试
- 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题
运行环境
查看 Puppeteer 的官方 API 你会发现满屏的 async, await 之类,这些都是 ES7 的规范,所以你需要:
Nodejs 的版本不能低于 v7.6.0, 需要支持 async, await.
需要最新的 chrome driver
chrome driver 在通过 npm 安装 Puppeteer 的时候会自动跟着下载;
安装puppeteer
通过 npm 可以直接安装
npm i puppeteer
基本用法
直接用官网的入门 Demo 演示
const puppeteer = require(' puppeteer');
(async () => {
// 创建一个浏览器实例 Browser 对象
const browser= await puppeteer.launch();
// 通过 Browser 对象创建页面 Page 对象
const page = await browser.newPage();
// page.goto() 跳转到指定的页面
await page.goto('https://example.com’);
// 对当前页面截图
await page.screenshot({path: 'example.png'});
// 关闭浏览器
await browser.close();
})();
创建浏览器方法详解(puppeteer.launch(options))
使用 puppeteer.launch() 运行 puppeteer,它会 return 一个 promise,使用 then 方法获取 browser 实例, 当然高版本的 的 nodejs 已经支持 await 特性了,所以上面的例子使用 await 关键字,这一点需要特殊说明一下,Puppeteer 几乎所有的操作都是 异步的, 为了方便代码维护和阅读,我们优先使用await 将异步操作转成同步操作;本文所有 demo 代码都是用 async, await 方式实现。这个 也是 Puppeteer 官方推荐的写法。
options 参数详解
参数名称 | 参数类型 | 参数说明 |
---|---|---|
ignoreHTTPSErrors | boolean | 在请求的过程中是否忽略 Https 报错信息,默认为 false |
headless | boolean | 是否以"无头"的模式运行 chrome, 也就是不显示 UI, 默认为 true |
executablePath | string | 可执行文件的路径,Puppeteer 默认是使用它自带的 chrome webdriver, 如果你想指定一个自己的 webdriver 路径,可以通过这个参数设置 |
slowMo | number | 使 Puppeteer 操作减速,单位是毫秒。如果你想看看 Puppeteer 的整个工作过程,这个参数将非常有用 |
args | Array(String) | 传递给 chrome 实例的其他参数,比如你可以使用"--ash-host-window-bounds=1024x768" 来设置浏览器窗口大小。更多参数参数列表可以参考这里 |
handleSIGINT | boolean | 是否允许通过进程信号控制 chrome 进程,也就是说是否可以使用 CTRL+C 关闭并退出浏览器 |
timeout | number | 等待 Chrome 实例启动的最长时间。默认为30000(30秒)。如果传入 0 的话则不限制时间 |
dumpio | boolean | 是否将浏览器进程 stdout 和 stderr 导入到 process.stdout 和 process.stderr 中。默认为 false |
userDataDir | string | 设置用户数据目录,默认linux 是在 ~/.config 目录,window 默认在 C:\Users{USER}\AppData\Local\Google\Chrome\User Data, 其中 {USER} 代表当前登录的用户名 |
env | Object | 指定对 Chromium 可见的环境变量。默认为 process.env。 |
devtools | boolean | 是否为每个选项卡自动打开 DevTools 面板,这个选项只有当 headless 设置为 false 的时候有效 |
Browser 对象详解
构建Browser对象有两个方法:Puppeteer.launch
和 Puppeteer.connect
; Puppeteer.launch
上面案例中有演示,接下来我们看下 Puppeteer.connect
的用法:
const puppeteer = require(' puppeteer');
(async () => {
const browser= await puppeteer.launch();
// 保存浏览器的链接对象
const browserWSEndpoint = browser.wsEndpoint();
// 手动断开链接
browser.disconnect();
// 重新建立连接,并创建新的 Browser 实例
const browser2 = await puppeteer.connect({browserWSEndpoint});
// 关闭 浏览器
await browser2.close();
})();
Browser 对象 API
方法名称 | 返回值 | 说明 |
---|---|---|
browser.close() | Promise | 关闭浏览器 |
browser.disconnect() | void | 断开浏览器连接 |
browser.newPage() | Promise(Page) | 创建一个 Page 实例 |
browser.pages() | Promise(Array(Page)) | 获取所有打开的 Page 实例 |
browser.targets() | Array(Target) | 获取所有活动的 targets |
browser.version() | Promise(String) | 获取浏览器的版本 |
browser.wsEndpoint() | String | 返回浏览器实例的 socket 连接 URL, 可以通过这个 URL 重新连接 chrome 实例 |
完整的API请插件官网文档:https://pptr.dev/api/puppeteer.browser
Page 对象Api
Page 提供了与浏览器中的单个选项卡或扩展程序后台页面进行交互的方法。
一个浏览器实例可能有多个页面实例。也就是多个标签页
Page 实例属性
属性 | 修饰符 | 类型 | 描述 |
---|---|---|---|
accessibility | readonly | Accessibility | Accessibility 类提供了检查浏览器的可访问性树的方法。辅助功能树由屏幕阅读器或开关等辅助技术使用。 |
coverage | readonly | Coverage | Coverage 类提供了一些方法来收集有关页面使用的部分 JavaScript 和 CSS 的信息。 |
keyboard | readonly | Keyboard | Keyboard 提供了一个用于管理虚拟键盘的 API。高级 API 是 Keyboard.type(),它接受原始字符并在页面上生成正确的 keydown、keypress/input 和 keyup 事件。 |
mouse | readonly | Mouse | Mouse 类在主框架 CSS 像素相对于视口左上角操作。 |
touchscreen | readonly | Touchscreen | Touchscreen 类公开触摸屏事件。 |
tracing | readonly | Tracing | Tracing 类公开跟踪审核接口。 |
Page 实例方法
这里列举出常用的几个
方法 | 修饰符 | 描述 |
---|---|---|
$(selector) | 在页面内部运行 document.querySelector。如果没有元素与选择器匹配,则返回值解析为 null。 | |
$$(selector) | 该方法在页面内运行 document.querySelectorAll,如果没有元素与选择器匹配,则返回值解析为[]。 | |
$$eval(selector, pageFunction, args) | 该方法在页面内运行 Array.from(document.querySelectorAll(selector)) 并将结果作为第一个参数传递给 pageFunction。 | |
$eval(selector, pageFunction, args) | 该方法在页面内运行 document.querySelector,并将结果作为第一个参数传递给 pageFunction。 | |
$x(expression) | 该方法将 XPath 表达式相对于页面文档作为上下文节点进行评估。如果不存在此类元素,则该方法解析为空数组。 | |
addScriptTag(options) | 向页面添加具有所需 URL 或内容的 <script> 标记。 | |
addStyleTag(options) | 将带有所需 URL 的 <link rel="stylesheet"> 标记或带有内容的 <style type="text/css"> 标记添加到页面中。这是page.mainFrame().addStyleTag(options) 的快捷方式。 | |
authenticate(credentials) | 为 HTTP 验证提供凭据。 | |
bringToFront() | 将页面置于前台(激活选项卡)。 | |
browser() | 获取页面所属的浏览器。 | |
browserContext() | 获取页面所属的浏览器上下文。 | |
click(selector, options) | 该方法使用选择器获取元素,如果需要,将其滚动到视图中心,然后使用 Page.mouse 单击元素的中心。如果没有与选择器匹配的元素,则该方法会抛出错误。 | |
close(options) | 关闭页面。 |
完整的方法查看官网文档: https://pptr.dev/api/puppeteer.page
Keyboard 对象API
Keyboard提供了一个用于管理虚拟键盘的API。高级API是Keyboard.type(),它接受原始字符并在页面上生成正确的keydown、keypress/input和keyup事件。
使用案例
一个 shift + a的组合按键例子
await page.keyboard.down('Shift');
await page.keyboard.press('KeyA');
await page.keyboard.up('Shift');
Keyboard 实例方法
方法 | 修饰符 | 描述 |
---|---|---|
down(key, options) | 触发一个 keydown 事件。 | |
press(key, options) | 快捷方式,等同于 Keyboard.down() 和 Keyboard.up()。 | |
sendCharacter(char) | 触发一个 keypress 和 input 事件。这不会触发 keydown 或 keyup 事件。 | |
type(text, options) | 对文本中的每个字符发送一个 keydown、keypress/input 和 keyup 事件。 | |
up(key) | 触发一个 keyup 事件。 |
Mouse 对象 API
Mouse类在相对于视口左上角的主框架CSS像素中操作。
每个page对象都有自己的Mouse,可以通过[page.mouse]访问。
Mouse 使用案例
await page.mouse.move(0, 0);
await page.mouse.down();
await page.mouse.move(0, 100);
await page.mouse.move(100, 100);
await page.mouse.move(100, 0);
await page.mouse.move(0, 0);
await page.mouse.up();
Mouse 实例方法
方法 | 修饰符 | 描述 |
---|---|---|
click(x, y, options) | 鼠标单击事件的快捷方式,相当于 mouse.move、mouse.down 和 mouse.up。 | |
down(options) | 模拟鼠标按下事件。 | |
drag(start, target) | 发送一个拖动事件。 | |
dragAndDrop(start, target, options) | 依次执行拖动、拖入、悬停和放置操作。 | |
dragEnter(target, data) | 发送一个拖入事件。 | |
dragOver(target, data) | 发送一个悬停事件。 | |
drop(target, data) | 依次执行拖入、悬停和放置操作。 | |
move(x, y, options) | 将鼠标移动到指定坐标。 | |
reset() | 将鼠标重置为默认状态:没有按下任何按钮;位置在 (0,0)。 | |
up(options) | 释放鼠标按钮。 | |
wheel(options) | 发送一个鼠标滚轮事件。 |
JSHandle 对象
表示对JavaScript对象的引用。可以使用 Page.evaluateHandle()
创建队列。
句柄防止引用的JavaScript对象被垃圾收集,除非句柄被故意释放。JSHandle在其关联的框架被导航离开或父上下文被破坏时自动释放。
句柄可以用作任何求值函数(如Page.$)的参数eval()、Page.evaluate()和Page.evaluateHandle()。它们被解析为其引用的对象。
方法 | 修饰符 | 描述 |
---|---|---|
asElement() | 如果句柄是 ElementHandle 的实例,则返回该句柄本身,否则返回 null。 | |
dispose() | 释放句柄引用的对象,以便进行垃圾回收。 | |
evaluate(pageFunction, args) | 使用当前句柄作为其第一个参数,评估给定函数。 | |
evaluateHandle(pageFunction, args) | 使用当前句柄作为其第一个参数,评估给定函数。 | |
getProperties() | 获取表示当前句柄属性的句柄映射。 | |
getProperty(propertyName) | 从引用对象中获取单个属性。 | |
jsonValue() | 表示引用对象可序列化部分的普通对象。 | |
remoteObject() | 提供对支持此句柄的 Protocol.Runtime.RemoteObject 的访问。 | |
toString() | 返回 JSHandle 的字符串表示形式。 |
ElementHandle 对象
ElementHandle表示页面的DOM元素。
如果要点击某个Dom元素,必须将对象转换成 ElementHandle 类型。只有 ElementHandle 类型才有 点击方法
JSHandle 转 ElementHandle 类型使用: asElement() 方法
方法 | 修饰符 | 描述 |
---|---|---|
$(selector) | 在当前元素中查找与给定选择器匹配的元素。 | |
$$(selector) | 为所有匹配给定选择器的元素返回当前元素。 | |
$$eval(selector,pageFunction,args) | 在当前元素中与给定选择器匹配的元素数组上执行给定函数。如果给定的函数返回一个promise,那么这个方法将等待promise解析。 | |
click(this,options) | 如果需要,此方法将元素滚动到视图中,然后使用Page.mouse单击元素的中心。如果元素从DOM分离,则该方法抛出错误。 |
更多内容请查看官方文档: https://pptr.dev/api/puppeteer.elementhandle
后记
官网文档非常详细,强烈建议将文档阅读一遍再上手;
文档地址: https://pptr.dev/