基于NodeJs的Chrome脚本神器Puppeteer

本文主要介绍基于NodeJs的Chrome脚本神器Puppeteer

1功能

Puppeteer以headless启动Chrome,并控制Chrome的行为,执行一系列操作。
Headless Chrome用于在无界面的环境中运行 Chrome。

  • 网页截图或者生成 PDF
  • 爬取 SPA 或 SSR 网站
  • UI 自动化测试,模拟表单提交,键盘输入,点击等行为
  • 捕获网站的时间线,帮助诊断性能问题
  • 创建一个最新的自动化测试环境,使用最新的 js 和最新的 Chrome 浏览器运行测试用例
  • 测试 Chrome 扩展程序
1
2

npm install puppeteer // 安装puppeteer

2API

描述
puppeteer.launch 启动一个新的Chrome进程
puppeteer.connect 连接一个Chrome进程
browser.newPage 创建一个Page实例
browser.pages 获取所有打开的Page实例
browser.close 关闭Chrome进程
page.setViewport 设置页面视图大小
page.goto 打开指定的网页
page.goBack 回退到上一个页面(同浏览器回退)
page.goForward 前进到下一个页面(同浏览器前进)
page.reload 刷新页面(同浏览器刷新)
page.waitForNavigation 等待页面跳转
page.waitForXPath 等待 xPath 对应的元素出现,返回对应的 ElementHandle 实例
page.waitForSelector 等待选择器对应的元素出现,返回对应的 ElementHandle 实例
page.waitForResponse 等待某个响应结束,返回 Response 实例
page.waitForRequest 等待某个请求出现,返回 Request 实例
page.waitForFunction 等待在页面中自定义函数的执行结果,返回 JsHandle 实例
page.waitFor 设置等待时间
page.screenshot 对当前页面或某个元素截图
page.$(选择器) 获取页面某个元素,并返回对应的elementHandle
page.$(选择器) 获取页面多个元素,并返回对应的elementHandle
elementHandle.click 点击某个元素
elementHandle.tap 模拟手指触摸点击
elementHandle.focus 聚焦到某个元素
elementHandle.hover 鼠标 hover 到某个元素上
elementHandle.type 在输入框输入文本
page.setRequestInterception 开启拦截请求
page.on(‘close’) 页面关闭
page.on(‘console’) console API 被调用
page.on(‘error’) 页面出错
page.on(‘load’) 页面加载完
page.on(‘request’) 收到请求
page.on(‘requestfailed’) 请求失败
page.on(‘requestfinished’) 请求成功
page.on(‘response’) 收到响应
page.on(‘workercreated’) 创建 webWorker
page.on(‘workerdestroyed’) 销毁 webWorker
page.evaluate(pageFunction[, …args]) 在浏览器环境中执行函数
page.evaluateHandle(pageFunction[, …args]) 在浏览器环境中执行函数,返回 JsHandle 对象
page.$$eval(selector, pageFunction[, …args]) 把 selector 对应的所有元素传入到函数并在浏览器环境执行
page.$eval(selector, pageFunction[, …args]) 把 selector 对应的第一个元素传入到函数在浏览器环境执行
page.evaluateOnNewDocument(pageFunction[, …args]) 创建一个新的 Document 时在浏览器环境中执行,会在页面所有脚本执行之前执行
page.exposeFunction(name, puppeteerFunction) 在 window 对象上注册一个函数,这个函数在 Node 环境中执行,有机会在浏览器环境中调用 Node.js 相关函数库
Page.emulate 修改模拟器(客户端)运行配置,模拟设备,参数设备对象,比如 iPhone, Mac, Android 等

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

const puppeteer = require('puppeteer');
let axios = require('axios');

//使用 puppeteer.launch 启动 Chrome
(async () => {
const browser = await puppeteer.launch({
headless: false, //有浏览器界面启动
slowMo: 100, //放慢浏览器执行速度,方便测试观察
args: [ //启动 Chrome 的参数
'–no-sandbox',
'--window-size=1280,960'
],
});
const iPhone = puppeteer.devices['iPhone 6'];
const page = await browser.newPage();
await page.emulate(iPhone);
page.setViewport({
width: 1920,
height: 1080
});
await page.setRequestInterception(true); //开启请求拦截
page.on('request', request => {
const type = request.resourceType();
if(type=='image'){
//直接阻止请求
return request.abort();
}else{
//对请求重写
return request.continue({
//可以对 url,method,postData,headers 进行覆盖
headers: Object.assign({}, request.headers(), {
'puppeteer-test': 'true'
})
});
}
});

await page.goto('https://onlyloveacat.com');

// 等待1s
await page.waitFor(1000);

//对整个页面截图
await page.screenshot({
path: './assets/onlyloveacat.png', //图片保存路径
type: 'png',
fullPage: true, //边滚动边截图
clip: {x: 0, y: 0, width: 1920, height: 1080}
});

//对页面某个元素截图
let [element] = await page.$x('/html/body/div/div[2]');
await element.screenshot({
path: './files/element.png'
});

const usernameElement = await page.$('#username');
await usernameElement.type('onlyloveacat', {delay: 20});
const passwordElement = await page.$('#password', {delay: 20});
await passwordElement.type('123456');
//点击确定按钮进行登录
let okButtonElement = await page.$('#btn-ok');

await page.close();
await browser.close();
})();

//使用 puppeteer.connect 连接一个已经存在的 Chrome 实例
(async () => {
//通过 9222 端口的 http 接口获取对应的 websocketUrl
let version = await axios.post("localhost:8080");
//直接连接已经存在的 Chrome
let browser = await puppeteer.connect({
browserWSEndpoint: version.webSocketDebuggerUrl
});
const page = await browser.newPage();
await page.goto('https://www.baidu.com');
await page.close();
await browser.disconnect();
})();
扫一扫,请老师喝水