前言
本文章实现需要服务器, 无可视化界面亦可。
使用的Cookie获取上一篇文章有介绍, 顺手写了这篇。
每日一问: 我为什么要实现这个功能???
机制分析
网页版状态下阅读, 每分钟左右会有一个read请求, 通过回执可以判断是否阅读成功。
具体参数我不想耗费时间去逆向, 但是可以通过模拟浏览阅读页面来等待read响应进行read重播,进而轻易实现自动阅读。
稳定性
服务器测试了24小时, 阅读时间也是相应增加24。
有趣的是, 经测试, 每次程序运行5min, 增加的时长可能是 5min、6min、8min、11min、13min 甚至是 21min。
但是总时长是稳定的, 也就是说会回归一天能拉满的时间24h。
实现代码
虽说是浏览器模拟事件, 到了python的表演时间, 但是我采用了JS去写, 辅佐包是 Playwright 。
总体是一次有趣的尝试。
准备事项
开始吧, 安装 Playwright
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| mkdir /server/auto/wxread && cd /server/auto/wxread
npm install playwright npx playwright install
npx playwright install-deps
npm install axios
|
代码
wxread.js1 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| 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;
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
是有效的即可。
1 2 3 4 5 6 7 8 9 10
| node wxread.js key=xxxx
|