TianLiLally
发布于 2026-11-02 / 0 阅读
0
0

1 star 的新仓库,把微信自动化最难的那一步做对了:wechat-scheduled-sender 深度拆解

💬

wechat-scheduled-sender

微信定时群发控制台 · Electron + Python UIA 自动化
开源 无 LICENSE
核心技术
UIA 语义控件
不依赖坐标、剪贴板、窗口位置
代码构成
Python 97KB / HTML 30KB
Electron 主进程 + Python 边车
最大风险
微信升级即失效
且违反用户协议,有封号风险

🔥 一个 1 star 的新仓库,把微信自动化最难的那一步做对了

微信 4.x 的界面是 Qt 自绘的。这意味着所有基于 UIA(UI Automation)的自动化工具都会撞上同一堵墙:QAccessible 在响应 WM_GETOBJECT 之前,会检查 Weixin.dll 里一个运行时 active byte。冷启动时如果没开读屏模式,这个字节是 0——此时 UIA 只能拿到 Qt 外壳(实测约 2 个节点),会话列表、输入框、发送按钮全都看不见。

这个仓库(Alanine-gH/wechat-scheduled-sender)抓到的正是这一步:把这个字节热写为 1 之后,控件树立即实体化,实测从 2 个节点变成 90+ 个,session_list、chat_input_field、发送按钮全部出现,而且不需要重启微信。这件事本身值得记一笔——但它同时也决定了这个项目最致命的短板,后面会讲。

📋 三层架构与真实能力边界

先看清楚它到底自己写了什么、又借了什么,这决定了它的可靠性边界:

  • Electron 主进程:目录重定向、拉起与回收 Python 边车、建窗口、系统集成;
  • Python 边车:UIA 自动化引擎 + 本地 HTTP 服务,端口由系统分配(--port 0),每次启动生成随机 token,只监听 127.0.0.1;
  • 单文件 HTML 控制台:经 preload 拿到端口与 token,走 X-Token 头调本地接口。

关键要说实话:gate 热激活、SQLCipher 数据库解密这些核心能力,来自依赖库 wechatauto-replica(PyPI 1.2.9,Apache-2.0),不是本仓库原创。这个仓库自己写的是 920 行 sender.py(打开会话、校验目标、写内容、点发送、回读校验)、编排层和界面。所以它更像一个「把难用的库包成能用的产品」的工程,而不是底层突破。

📊 实测速查大表:它能做什么 vs 它做不到什么

能力项 实测表现 可靠性
控件树实体化 热写 active byte,2 → 90+ 节点,无需重启微信 微信一升级就失效
窗口鲁棒性 移动、缩放、被遮挡都不影响;最小化会自动 SW_RESTORE 较好
写入方式 ValuePattern.SetValue(),绕开剪贴板与输入法,多行可整体写入 好
发送结果校验 输入框清空 + 数据库回读命中,日志标 [已校验] 好(同类工具少有)
计划可复现 随机种子 = 当天日期,同一天重复生成结果完全一致 好
发送节流 默认相邻两条间隔 4~6 分钟;30 个群 1 轮约 150 分钟 合规设计,但很慢
多账号 可枚举所有账号数据,但只能给当前登录的账号发 受限

⚠️ 五个硬伤:用之前必须知道的

🚨 项目自带排查记录里的真实事故
  1. 依赖脆弱是结构性的,不是 bug:微信从 4.1.15.13 自动更新到 4.2.0.11 后,gate RVA 从 0xb135c38 变成 0xb507c08。库「扫到一个候选值就标记 verified」,结果控件树时有时无——26 条目标全部失败。这类方案的宿命是:微信一升级就得等库更新,中间是不可用状态;
  2. 合规风险明确:本质是逆向 + 自动化微信客户端,违反微信用户协议,账号封禁风险由使用者承担。作者自己在宣传物料里也写明「不是官方接口,高频群发有风控风险,内容请合法合规」;
  3. 仓库没有 LICENSE 文件:LICENSE 请求返回 404,README 里「许可」二字出现 0 次。宣传图上标着 MIT,但仓库里没有对应文件——法律上等于保留所有权利,不能直接商用或二次分发;
  4. 安全设计有缺口:服务端 Access-Control-Allow-Origin: "*" 通配,配合「浏览器模式无 token 就放行」的设计,意味着任意网页都能跨域打这个本地服务。虽然只监听 127.0.0.1,但浏览器模式下等于本地接口对全网页面开放;
  5. 微信必须已登录且窗口可恢复:数据库密钥存在微信进程内存里,首次提取后缓存到本地;发送是 GUI 操作,微信完全退出就跑不了。另外安装目录必须可写,不要装在 C:\Program Files 下。
💡 仓库规模参考(GitHub API 实测)
  1. 创建与推送都在 2026-11-02 当天(06:59 → 09:11 UTC),属于刚发布的新项目;
  2. stars 1 / forks 1 / watchers 0,作者账号 19 个公开仓库、0 follower——几乎没有社区验证,踩坑只能靠自己;
  3. 仓库里还带了 5.8MB 宣传视频、分镜工程、配音时间轴与发布文案,是带推广意图的项目,不是纯技术沉淀。

🎯 值得学的不是代码,是这个习惯

✅ 「不在用户目录创建任何东西」是怎么做到的
  1. 第一层:Electron 路径重定向——必须在 app ready 之前调 app.setPath() 改道 userData / sessionData / temp / crashDumps / logs,晚了就先创建再改道,为时已晚;
  2. 第二层:环境变量(这一步最容易漏)——只调 app.setPath('temp') 不够,它只改浏览器进程的 PathService;Chromium 的子进程(renderer / GPU / network)用继承的 TEMP/TMP 环境变量经 GetTempPath() 自己解析临时目录。必须同时改 process.env.TEMP/TMP/TMPDIR;
  3. 第三层:第三方库兜底——把 os.path.expanduser('~') 整体重定向到安装目录,且必须在 import wechatauto 之前执行,否则模块级常量已经算好了。
🔬 真正值得抄的是验证方法,不是代码
  1. 作者做了一次独立验证:另开一个进程,自己取基线、自己冷启动、自己归因,不依赖主程序的日志自证;
  2. 第一轮没通过——抓到真实反例:Chromium 渲染进程每次启动都在真实 %TEMP% 里留一个 0 字节 GUID .tmp;
  3. 用 Restart Manager 归因确认占用者是 --type=renderer,单独跑 Python 服务做同一次数据库读取则零新增——反证不是 Python 侧;
  4. 补上 process.env.TEMP/TMP/TMPDIR 后复验:3 次冷启动(含一次 78 秒)10 → 10,零新增,才判定通过。

结论:技术上它能跑,但只在特定微信版本上;工程上「用户文件重定向 + 独立验证」这套方法论值得学。但我不建议直接使用——合规风险、版本脆弱、缺 LICENSE 三条叠加,代价大于收益。真要用,先找作者补许可声明,并接受「微信一升级就可能全线失效」这个前提。作者本人在推广时把风险说在前面,这点是负责任的;问题出在仓库少了那个 LICENSE 文件。

免责声明

本文章仅供参考学习使用,不具备任何教学行为,了解账户授权、第三方服务风险、数据处理及责任限制。


评论