微信收款助手监控脚本 — 更新日志v2.0(RapidOCR 极速版)
项目:Windows 微信收款助手 OCR 监控 + 自动推送
更新日期:2026-10-01
版本:v2.0(RapidOCR 极速版)
一、版本概述
本次更新对原脚本进行了安全性、稳定性、性能三方面的全面改造。核心成果:
- ⚡ 单笔识别耗时从 10~20 秒压到 1.5~3 秒(提升 5~10 倍)
- 🔒 密钥外置,消除明文硬编码风险
- 🎯 ROI 自学习,自动定位金额行,适配不同窗口布局
- 🛡️ 短时去重,解决”同金额误判为重复订单”问题
二、重大改进
1. 安全性修复
| 问题 | 修复 |
|---|---|
| 密钥明文硬编码在代码里 | 外置到 config.json,首次运行自动生成 |
changeme_ 占位符残留 |
配置文件中明确警告需替换真实密钥 |
新增 config.json 配置文件,所有可变参数集中管理,代码不再包含敏感信息。
2. 稳定性修复
| # | 问题 | 修复方案 |
|---|---|---|
| 1 | 记事本保存的 config.json 带 BOM 导致读取失败 |
改用 utf-8-sig 编码读取,自动兼容 BOM |
| 2 | 心跳串行请求两个服务端,单个超时阻塞整个心跳 | 改用 ThreadPoolExecutor 并发请求,timeout 缩短到 3 秒 |
| 3 | 推送串行,Workers 成功后才发 PHP | 改为并发推送,两服务端同时请求 |
| 4 | 日志文件无限增长 | 改用 RotatingFileHandler,单文件 5MB × 保留 3 个备份 |
| 5 | 跨日时间判断错误(23:58 与 00:03 混淆) | 用 datetime 拼出完整时间对比,晚超 12h 视为昨天 |
| 6 | 监控线程异常退出主线程无感知 | 守护循环增加 monitor_thread.is_alive() 检测 |
| 7 | OCR 引擎初始化无 try 保护 | 加 try,失败打 critical 日志并退出 |
| 8 | PrintWindow 返回黑屏时无检测 |
新增 _is_blank_image,std<5 且 mean<20 判为黑屏 |
| 9 | 去重记录程序重启后清零 | 去重文件持久化(.pushed_records),启动时加载 |
3. 性能优化
3.1 OCR 从 10 秒 → 1.5 秒
| 优化项 | 说明 |
|---|---|
| 去掉图像放大 | 原代码 resize(width*2, height*2) 拖慢推理,已移除 |
| ROI 精确裁剪 | 只裁金额行区域(约 163×90),大幅缩小 OCR 输入 |
| rec-only 模式 | 用 engine(img, use_det=False, use_cls=False, use_rec=True) 跳过文本检测和方向分类,只跑识别 |
| 两段式识别 | 第一段走 ROI 快路径(~1.5s),失败才退回全图完整 OCR(~9s) |
3.2 心跳/推送并发化
- 心跳:
ThreadPoolExecutor同时请求两个服务端,总耗时从 5~10s 降到 <3s - 推送:两服务端并发,耗时从 2.7s 降到 1.1s
3.3 关键日志耗时观测
新增耗时打印:
[OCR-快] ROI 命中: 0.01,OCR 2.69s,总 2.71s
[推送] 完成,耗时 1.15s,成功=True
[周期] 本次检测总耗时 3.92s
4. 新增:ROI 自学习机制
背景:窗口布局随微信版本/分辨率变化,写死比例容易裁偏。
机制:
- 每次全图 OCR 成功后,从结果里找「纯金额行」(正则
^[¥¥]?\s*\d+\.\d{2}$) - 优先选「收款金额」标签下方最近的那一行
- 把该行的像素坐标(不是比例)写回
config.json - 下次识别直接走新 ROI,速度极快
日志示例:
[自学习] 金额行原始像素: y[331-381] x[234-361],图尺寸 600x800,来源文本:¥0.01
[配置] 已保存: {'amount_roi_px_top': 311, 'amount_roi_px_bottom': 401, ...}
[自学习] ROI 已更新为像素:y[311-401] x[216-379]
关键设计:用像素坐标而不是比例,避免 PrintWindow 截图尺寸与窗口尺寸不一致导致的换算误差。
5. 新增:OCR 结果 strict 修复
背景:rec-only 模式下,RapidOCR 对「大字号 + 有间隙」的金额容易丢字符,例如:
¥0.01→ 识别为01(丢了¥和.)¥1.00→ 识别为.00(丢了1)
修复逻辑(strict=True 时启用):
| OCR 结果 | 修复后 | 规则 |
|---|---|---|
01 |
0.01 |
纯数字,倒数第二位前插小数点,去前导 0 |
123 |
1.23 |
同上 |
1234 |
12.34 |
同上 |
0.1 |
0.10 |
只有 1 位小数,补零 |
日志示例:
[OCR修复] '01' → '0.01'(补小数点+去前导0)
[OCR修复] '02' → '0.02'(补小数点+去前导0)
6. 新增:短时去重机制
背景:ROI 只裁金额行,没有时间信息,导致不同订单但同金额的 key 相同(如 unknown_0.01),被误判为重复。
旧机制:
dedup_key = f"{msg_time}_{amount}" # msg_time 永远是 unknown
if dedup_key in pushed_records: skip
新机制:
short_key = f"{current_hash[:8]}_{amount}" # 截图哈希 + 金额
if now - recent_push.get(short_key, 0) < 10: # 10 秒内同图同金额才去重
skip
效果:
- 同一订单的重复检测(截图未变)→ 被 pHash 提前跳过,不会进到推送
- 同一订单截图微抖 → 10 秒内同 hash 同金额 → 去重 ✅
- 不同订单同金额 → 截图 hash 不同 → 正常推送 ✅
三、配置项说明
config.json 主要字段:
{
"servers": [
{
"name": "Workers版",
"url": "https://域名/appPush",
"heart_url": "https://域名/appHeart",
"key": "请改成真实密钥",
"timeout": 5
},
{
"name": "PHP版",
"url": "http://域名/appPush",
"heart_url": "http://域名/appHeart",
"key": "秘钥",
"timeout": 10
}
],
"window_title": "微信收款助手",
"scan_interval": 0.5,
"heartbeat_interval": 10,
"time_filter_minutes": 5,
"debug_save": false,
"window_width": 600,
"window_height": 800,
"amount_roi_px_left": 216,
"amount_roi_px_right": 379,
"amount_roi_px_top": 311,
"amount_roi_px_bottom": 401
}
关键字段:
| 字段 | 说明 |
|---|---|
debug_save |
是否保存 debug_roi.png 供调试(正式使用建议 false) |
scan_interval |
截图检测间隔(秒),0.5 表示每 0.5 秒检测一次 |
amount_roi_px_* |
金额行像素 ROI,自学习会自动更新,也可手动调 |
四、性能对比
| 阶段 | 旧版 | 新版 | 提升 |
|---|---|---|---|
| OCR 识别 | 7~10s | 1.5~3s | 3~5 倍 |
| 心跳请求 | 5~10s(串行) | <3s(并发) | 2~3 倍 |
| 推送 | 2.7s(串行) | 1.1s(并发) | 2.5 倍 |
| 单笔总耗时 | 10~20s | 1.5~4s | 5~10 倍 |
五、升级须知
5.1 从旧版升级
- 删除旧的
config.json(旧版无此文件,不用删;如果之前手建过,删掉让程序重新生成) - 替换整个
.py文件 - 首次运行会自动生成
config.json,手动把key改成真实密钥 - 跑一笔收款,让它自学习 ROI
- 确认
[OCR-快] ROI 命中后,把debug_save改为false
5.2 首次部署
- 安装依赖:
pip install rapidocr_onnxruntime pygetwindow pywin32 pillow numpy requests infi.systray - 把
icon.ico放在脚本同目录(可选) - 运行脚本
5.3 打包成 exe(可选)
python -m PyInstaller --onefile --noconsole --name 微信收款监控 --collect-all rapidocr_onnxruntime --collect-all onnxruntime --collect-all cv2 --add-data "icon.ico;." --hidden-import numpy --hidden-import PIL --hidden-import pygetwindow --hidden-import win32gui --hidden-import infi.systray vmq.py
打包后 config.json 会生成在 exe 同目录,不会被 PyInstaller 的临时目录干扰。
六、已知问题与后续规划
已知问题
¥1.00这类金额,rec-only 偶尔丢整数位- 当前 strict 修复未覆盖
.00→0.00场景(因为 0 元无意义,未处理) - 若实际场景有 1.00 以上金额,可考虑切回
det+rec全流程
- 当前 strict 修复未覆盖
自学习坐标可能偏移
- RapidOCR 返回坐标的参考系因版本而异
- 已通过”像素存坐标”降低影响,但极端情况下仍需手动微调
窗口必须可见
PrintWindow要求窗口未最小化,最小化时会先ShowWindow(SW_RESTORE)- 若窗口被其他窗口完全遮挡,仍能截图(PrintWindow 特性),不影响
后续规划
- [ ] 支持多窗口/多账号同时监控
- [ ] 识别结果置信度过滤(低于阈值跳过)
- [ ] Webhook / 钉钉 / 企业微信 多种推送通道
- [ ] 打包成带 GUI 配置界面的版本
七、故障排查速查
| 现象 | 排查方向 |
|---|---|
程序启动后卡在 [OCR] 正在加载 |
RapidOCR 首次加载 onnx 模型需 10~30s,耐心等待;超 1 分钟看是否模型文件缺失 |
[配置] 读取失败: Unexpected UTF-8 BOM |
config.json 被记事本保存为 BOM 格式,用 VSCode 另存为 UTF-8 无 BOM |
[OCR-快] ROI 未命中,退回全图 频繁 |
ROI 位置偏了,检查 debug_roi.png(需 debug_save=true) |
[OCR修复] '01' → '0.01' 但推送失败 |
服务端 key 不对或网络问题,看具体返回 |
| 推送成功但后台未收到 | 检查服务端签名规则是否与代码一致 |
[去重] xxx 在 10s 内已推送过,跳过 |
正常,防抖机制;若真是新订单被误判,检查截图 hash 是否巧合相同 |
八、改造历程回顾
从最初的 v1.0 到 v2.0,共修复 12 类问题:
| # | 问题 | 状态 |
|---|---|---|
| 1 | 硬编码密钥 | ✅ 外置 config.json |
| 2 | 跨日时间判断 | ✅ datetime 拼时间 |
| 3 | 去重不持久化 | ✅ 改短时去重 |
| 4 | 日志无限增长 | ✅ RotatingFileHandler |
| 5 | 心跳串行阻塞 | ✅ 并发 + timeout 3s |
| 6 | 推送串行 | ✅ 并发两服务端 |
| 7 | OCR 10 秒 | ✅ ROI 快路径 1.5~3s |
| 8 | RapidOCR 参数不兼容 | ✅ 改回无参 + 自动探测 |
| 9 | 记事本 BOM 报错 | ✅ utf-8-sig |
| 10 | ROI 定位错 | ✅ 自学习 + 像素坐标 |
| 11 | OCR 丢小数点 | ✅ strict 修复 01→0.01 |
| 12 | 同金额误去重 | ✅ hash+金额 短时去重 |
九、致谢
感谢在调试过程中提供多轮日志和 debug_roi.png 的实测反馈。正是这些真实数据让 ROI 自学习和 strict 修复逻辑得以精准定位问题并逐层修复。
如遇新问题,请附上 vmq.log 完整日志 + debug_roi.png(如 debug_save=true),便于快速定位。
十、附上完整源代码
此段内容已加密
请输入密码解锁此部分内容
密码错误,请重试

💬 评论区 0