---
title: 微信读书自动阅读
layout: post
cover: 'https://upyun.thatcdn.cn/myself/typora/202309151542253.jpg'
tags: ['Tencent']
categories: ['堆栈']
poster:
headline: ''
caption: ''
color: 'white'
description: '实现微信读书自动阅读, 增加阅读时长, 打卡阅读天数'
date: 2023-09-14 20:00:00
前言
本文章实现需要服务器, 无可视化界面亦可。
使用的Cookie获取上一篇文章有介绍, 顺手写了这篇。
每日一问: 我为什么要实现这个功能???
{% link https://blog.thatcoder.cn/Tencent-WxRead-Cookies/ 微信读书Cookie续活 %}
机制分析
网页版状态下阅读, 每分钟左右会有一个read请求, 通过回执可以判断是否阅读成功。
具体参数我不想耗费时间去逆向, 但是可以通过模拟浏览阅读页面来等待read响应进行read重播,进而轻易实现自动阅读。
稳定性
服务器测试了24小时, 阅读时间也是相应增加24。
有趣的是, 经测试, 每次程序运行5min, 增加的时长可能是 5min、6min、8min、11min、13min 甚至是 21min。
但是总时长是稳定的, 也就是说会回归一天能拉满的时间24h。
实现代码
虽说是浏览器模拟事件, 到了python的表演时间, 但是我采用了JS去写, 辅佐包是 Playwright 。
总体是一次有趣的尝试。
准备事项
开始吧, 安装 Playwright
# 先创建一个文件夹
mkdir /server/auto/wxread && cd /server/auto/wxread
# 安装 playwright
npm install playwright
npx playwright install
# 下面这个可能需要点时间
# 因为有浏览器的下载
npx playwright install-deps
# 当然少不了 axios
npm install axios
# 好的, 一切准备就绪, 创建代码吧
代码
const { firefox } = require('playwright');
const axios = require('axios');
// 获取命令行参数
const args = process.argv.slice(2);
const params = {};
args.forEach((arg) => {
const [key, value] = arg.split('=');
if (key && value) {
params[key] = value;
}
});
const url1 = 'https://weread.qq.com/web/reader/8f5329e0813ab7d1eg012feake4d32d5015e4da3b7fbb1fa';
const url2 = 'https://weread.qq.com/web/book/read';
let capturedResponse = null;
let browser = null;
const scrollInterval = 10000; // 上下滑动间隔时间 单位毫秒
const totalTime = 400000; // 单次阅读时间 单位毫秒
const getXHR = async () => {
console.log("Success: 启动 Playwright 浏览器");
browser = await firefox.launch({
headless: true,
});
const page = await browser.newPage();
await page.setExtraHTTPHeaders({
cookie: (await axios.get("https://sijnzx.laf.thatcoder.cn/tencent-weread-refcookie?key="+params['key'])).data["data"]["cookies"]
});
await page.goto(url1, {
waitUntil: 'networkidle',
});
console.log("Success: 打开内容页面");
page.on('response', async (response) => {
if (response.url() === url2) {
const data = await response.json();
if (data['succ'] === 1) {
console.log("Success: 目标URL响应成功");
} else {
console.log("Error: 目标URL响应失败");
}
capturedResponse = data['succ'] === 1 ? response : null;
await repeatXHR(100);
// 不要关闭浏览器
}
});
// 定期上下滑动
let scrollCount = 0; // 计数器
let scrollDirection = 1; // 1表示向下滑动,-1表示向上滑动
setInterval(async () => {
await page.evaluate((scrollDirection) => {
const windowHeight = window.innerHeight;
window.scrollBy(0, scrollDirection * windowHeight); // 向上或向下滑动一个屏幕高度
}, scrollDirection);
scrollCount++;
// 如果达到了五次滑动,切换方向并重置计数器
if (scrollCount === 5) {
scrollDirection *= -1; // 切换方向
scrollCount = 0; // 重置计数器
}
}, scrollInterval);
// 设置浏览器关闭定时器
setTimeout(async () => {
console.log("Success: 关闭浏览器");
await browser.close();
}, totalTime);
};
const repeatXHR = async (count) => {
if (!capturedResponse) {
console.log("Failed: 没有捕获到响应,无法重放");
return;
}
const request = capturedResponse.request();
for (let i = 0; i < count; i++) {
try {
const response = await axios({
method: request.method(),
url: request.url(),
headers: request.headers(),
params: request.params,
data: request.postData(),
});
if (response.data.succ !== 1) {
console.log(`Failed: 重放响应 ${i + 1}: 失败, succ!==1`);
return;
}
} catch (error) {
console.error(`Failed: 重放响应 ${i + 1}: 失败, ${error.message}`);
}
}
console.log(`Success: 重放响应 ${count} 次完毕`)
};
(async () => {
await getXHR();
})();
运行
代码会启动一个无头浏览器, 所以没有可视化也不需要担心。
个人测试24小时, 无任何问题, 使用的内存为300MB左右, CPU占用率为0.1%左右。
对了, 带上key参数是我接口的鉴权, 也就是上一篇文章的参数(个人有所修改)。
你实现了上一篇文章的获取可以使用你的接口。保证cookie是有效的即可。
node wxread.js key=xxxx
# 成功运行大概输出如下
# Success: 启动 Playwright 浏览器
# Success: 打开内容页面
# Success: 目标URL响应成功
# Success: 重放响应 100 次完毕
# Success: 目标URL响应成功
# Success: 重放响应 100 次完毕
# Success: 浏览器关闭 (400秒后)
浙公网安备 33010602011771号