大家好,我是来富!一个致力于使用nodejs实现办公自动化的家伙。
上期给大家分享了使用nodejs+e小天实现微信聊天机器人的功能,其中e小天临时授权只有一天的授权时间,所以对于新用户而言就需要每一天都去点击一次临时授权按钮,但是对于会自动化的nodejs程序猿来说,闲来无事我就自己用puppeteer做了个自动化操作微信授权功能,正所谓用魔法战胜魔法。
声明:文章仅供参考,请不要用作非法用途,建议大家通过贡献项目来换取永久名额,同时,使用微信连接e小天建议使用小号来操作,避免被投诉封禁,一切后果本人概不负责
实现效果
先来看看演示结果,无图言屌!
由于涉及到授权按钮的点击响应,时间比较长,请大家耐心看完下方gif图
授权流程
采用nodejs的puppeteer包实现自动化授权。
前提:已经临时授权微信,且授权时间暂未过期
1、拿到e小天临时授权的过期时间
首先参考上一篇文章安装完成e小天之后,打开“管理面板”->“个人中心” ,进行代码审查。
如下图
找到 “http://127.0.0.1:8203/api?json&key=您的key值” 这个ajax请求,我们需要拿到key后面的内容,后面需要使用axios直接请求该路径获取到微信的授权到期时间(如果授权已经过期了,暂时无法通过本程序进行操作)
2、分析dom结构
进入“临时授权”页面
路径为:“http://127.0.0.1:8203/tmp/wxext/www/wxext-master/docs/home/auth_ls.html?key=你的key值”
查看“授权”按钮 如下图:
点击之后会出现 验证码验证弹窗
注意圈出来的class类,后面做自动化需要使用到。
选择正确的按钮,点击后会弹出“授权成功,到期时间为xxx”提示
实现思路
1、使用axios包请求“http://127.0.0.1:8203/api?json&key=您的key值”路径,获取到当前登录的微信信息,及相应的授权到期时间。
2、使用puppeteer 进入“http://127.0.0.1:8203/tmp/wxext/www/wxext-master/docs/home/auth_ls.html?key=你的key值”页面,点击“授权”按钮,选择正确的验证码点击。
难点:授权验证码非普通的验证码,使用的是安德富验证,认知中目前没有办法去识别破解
解决办法:随机点击其中一个按钮,验证错误后会更换验证码,继续点击,直到正确为止!
代码实现
代码实现思路就是授权流程的实现,主要看 init主方法,注释基本都已经写清楚了。注意变更key为个人的key值。
const puppeteer = require("puppeteer");
const {TimeoutError} = puppeteer.errors;
const {Util} = require("../../utils/util");
const util = new Util();
const axios = require("axios");
const qs = require("qs");
let logger = null;
class WxRobotAuth {
constructor() {
//当前登录微信列表
this.loginUrl = "http://127.0.0.1:8203/tmp/wxext/www/wxext-master/docs/home/auth_ls.html?key=";
this.userCenterUrl = "http://127.0.0.1:8203/api?json&key=";
this.key = "你的key值"; //自己的key
/**
* 进入http://127.0.0.1:8203/tmp/wxext/www/wxext-master/docs/home/i.html
* 个人中心页面代码审查查看key值
*/
}
async init(index=0) {
const browser = await puppeteer.launch({
headless:false, //无头部
product:"chrome",
slowMo: 30,
timeout: 20000,
args: [
"--ignore-certificate-errors",
"--no-sandbox",
"--disable-gpu"
],
})
const page = await browser.newPage();
// page.setDefaultTimeout(0); //无头浏览器 timeout超时报错,
try {
logger = await util.getLogger();
this.loginUrl = this.loginUrl + this.key; //新的授权地址
this.userCenterUrl = this.userCenterUrl + this.key; //用户中心请求接口
const {data:userData} = await axios({
method: 'post',
url: this.userCenterUrl,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data : qs.stringify({method:"list"})
})
logger.info("获取用户个人中心信息为:" + JSON.stringify(userData))
if(userData &&userData.method== "list_Recv" && userData.count >= 1){
const filterData = userData.data.filter(item=>item.isLogin == 1);
if(filterData == 0){
throw new Error("微信未在127.0.0.1:8203中连接");
}
const authTime = filterData[0].authTime;
if(!authTime){
throw new Error("个人中心授权时间为空!");
}else{
logger.info(this.loginUrl);
//进入授权页面
await page.goto(this.loginUrl,{waitUntil: "networkidle2"}); //无头浏览器 timeout超时报错,
logger.info("进来了")
await page.click("#show");//点击授权按钮
await page.waitForSelector("#adfortest_plugin_ask .vd_ckbox"); //等待验证码选项加载完成。
const click = async ()=>{
//点击下方验证码第二个选项(测试多次发现第二个验证的成功率稍微高一点)
await page.click("#adfortest_plugin_ask .vd_ckbox:nth-of-type(2)");
//等待两秒
await page.waitForTimeout(2000);
//使用puppeteer evaluate 查看弹窗是否已经隐藏
//隐藏 -> 授权成功 未隐藏 -> 授权失败
const isHide = await page.evaluate(()=>{
return document.querySelector("#adfortest_plugin").style.display == "none";
})
logger.info(`此次点击弹窗${isHide?"隐藏了":"未隐藏"}`)
if(!isHide){//识别失败后等待几秒钟后重试点击
await page.waitForTimeout(7000);//等待预定时间
await click();//重试
}
}
await click(); //循环执行点击
await page.waitForTimeout(20000);
}
await page.close(); //关闭页面
await browser.close();//关闭浏览器
}else{
throw new Error("获取用户授权列表异常" + JSON.stringify(userData))
}
} catch (e) {
logger.error(e)
if (e instanceof TimeoutError) {
logger.info("等待超时,重试");
// await page.close();
// await browser.close()
// await this.init();
} else {
logger.info(e)
logger.info("异常错误");
// await page.close();
// await browser.close();
// await this.init()
}
}
}
}
// module.exports = {
// WxRobotAuth
// }
new WxRobotAuth().init()
核心代码就是上面这些, 不要使用pm2来部署代码,puppeteer会出现无法识别元素的bug,可以使用windows定时任务,定时执行js文件。
代码只是辅助,主要是自动化操作的思路,希望能帮助到你。
觉得有帮助的话,给个关注吧,谢谢各位大佬啦!