一、puppeteer 基础入门
完整源码请移步 github
- 新建项目
mkdir puppeteer
- 安装依赖
2-1 安装 puppeteer ( shadowsocks 切换到全局模式)
yarn add puppeteer
2-2 下载 chromium ,解压至项目根目录
- 运行一个最简单的 🌰
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://mp.weixin.qq.com/');
})();
yarn start
- 自定义一些全局配置
const browser = await puppeteer.launch({
headless: false, // 打开浏览器
executablePath: './chrome-mac/Chromium.app/Contents/MacOS/Chromium' // 指定Chromium路径
});
设置窗口大小
await page.setViewport({
width: 1200,
height: 800
});
二、微信公众平台为小程序批量添加成员
目的:利用 puppeteer 实现自动化操作,减少人工劳动。
主要流程1. 模拟表单登录
输入字符
page.type('#mytextarea', 'World', {delay: 100}); // 输入变慢,像一个用户
点击事件
page.click(selector, clickOptions)
Puppeteer:模拟浏览器操作行为的利器
中文api:page.type()
2. 循环判断是否扫码成功
难点:微信公众平台的登录,除了表单输入外,还需要管理员/运营者使用微信扫码验证,这个过程可以理解成是异步地,那么如何才能准确判断什么时候扫码成功了呢???
思路:扫码验证成功后页面会跳转到 home 页面,所以可以通过监听路由变化来判断是否进入 home 页。
// 遍历判断是否二维码扫描成功
while (true) {
// 监听路由
await page.waitForNavigation({
waitUntil: 'load'
})
const url = page.url();
if (url.includes('https://mp.weixin.qq.com/wxopen/initprofile?action=home')) {
token = url.split("token=")[1]; // 获取 token
console.log('登录成功:', token);
break;
}
}
说明:因为登录后会先跳转到二维码扫描页面,所以监听一次路由变化是不够的。
puppeteer(headless chrome)实现网站登录 -- 验证码
中文api:page.waitForNavigation()
3. 点击添加成员
dom 元素 “添加成员” 开始是隐藏的,无法获取到。
解决方案:
- 绕过
我直接拼接出添加成员
页面的 url,跳转过去了。 - 笨一点的方法
先点击下拉箭头,延时200ms,等添加成员显示出来后,再点击次元素
4. 拦截请求的用法
公众平台添加项目成员,管理员扫码通过后,路由并没有发生变化,所以这里不能再去监听路由变化了,但是 puppeteer 提供了对请求和响应的拦截。
dialog4-1. 首先,千万记得启用请求拦截器
await page.setRequestInterception(true);
4-2. 封装拦截方法
// 拦截响应
function getResponse(page, url) {
return new Promise((resolve) => {
page.on('request', request => {
// 只监听 和 url 相关的请求
if (request.url().includes(url)) {
page.on('response', response => {
const req = response.request();
// 只监听和 url 相关的响应
if (req.url().includes(url)) {
if (response.status() === 200) {
resolve()
}
}
});
request.continue();
} else { // 其他请求
request.continue();
}
});
}).catch();
}
用法:
const res = getResponse(page, 'mp.weixin.qq.com/wxopen/waqrcode?action=ask');
res.then(async () => {
// do something
})
Resolve promise on specific event at puppeteer
Puppeteer拦截某条url并返回其响应内容(场景和方法) API RequestInterception拦截器的使用
三、过程中遇到的 issue
UnhandledPromiseRejectionWarning on Navigation Timeout Exceeded
并没有太好的解决方案,适当使用延时。
await page.waitFor(100);
网友评论