✕
开启精彩搜索
热门搜索
emby EMBY 解析 免流 源码 IPV6 阿里 阿里云 青龙 音乐 网心 网心云 webdav 阿里云盘 unraid 洗白 Rclone 刮削 云梦

微信收款助手监控脚本 — 更新日志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 自学习机制

背景:窗口布局随微信版本/分辨率变化,写死比例容易裁偏。

机制:

  1. 每次全图 OCR 成功后,从结果里找「纯金额行」(正则 ^[¥¥]?\s*\d+\.\d{2}$)
  2. 优先选「收款金额」标签下方最近的那一行
  3. 把该行的像素坐标(不是比例)写回 config.json
  4. 下次识别直接走新 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 从旧版升级

  1. 删除旧的 config.json(旧版无此文件,不用删;如果之前手建过,删掉让程序重新生成)
  2. 替换整个 .py 文件
  3. 首次运行会自动生成 config.json,手动把 key 改成真实密钥
  4. 跑一笔收款,让它自学习 ROI
  5. 确认 [OCR-快] ROI 命中 后,把 debug_save 改为 false

5.2 首次部署

  1. 安装依赖:
    pip install rapidocr_onnxruntime pygetwindow pywin32 pillow numpy requests infi.systray
    
  2. 把 icon.ico 放在脚本同目录(可选)
  3. 运行脚本

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. ¥1.00 这类金额,rec-only 偶尔丢整数位

    • 当前 strict 修复未覆盖 .00 → 0.00 场景(因为 0 元无意义,未处理)
    • 若实际场景有 1.00 以上金额,可考虑切回 det+rec 全流程
  2. 自学习坐标可能偏移

    • RapidOCR 返回坐标的参考系因版本而异
    • 已通过”像素存坐标”降低影响,但极端情况下仍需手动微调
  3. 窗口必须可见

    • 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