puppeteer 微信公众平台为小程序批量添加成员

2019-05-06  本文已影响0人  回调的幸福时光

一、puppeteer 基础入门

完整源码请移步 github

  1. 新建项目
mkdir puppeteer
  1. 安装依赖

2-1 安装 puppeteer ( shadowsocks 切换到全局模式)

yarn add puppeteer 

2-2 下载 chromium ,解压至项目根目录

  1. 运行一个最简单的 🌰
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
  1. 自定义一些全局配置
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 元素 “添加成员” 开始是隐藏的,无法获取到。

解决方案:

  1. 绕过
    我直接拼接出添加成员页面的 url,跳转过去了。
  2. 笨一点的方法
    先点击下拉箭头,延时200ms,等添加成员显示出来后,再点击次元素
UI dom 结构
4. 拦截请求的用法

公众平台添加项目成员,管理员扫码通过后,路由并没有发生变化,所以这里不能再去监听路由变化了,但是 puppeteer 提供了对请求和响应的拦截。

dialog

4-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);

参考

github puppeteer
puppeteer 中文文档

上一篇 下一篇

猜你喜欢

热点阅读