微信自动回复(桌面版 4.x)
本机微信登着,人不在电脑前——它替你把私聊接住:按你的人设回一句口语化的话,
业务问题从你的知识库里找答案,其余一律等你回来自己看。
跑在你自己的电脑上:读的是本机微信数据,发的是本机微信窗口,
不注入、不破解、不经过任何服务器,模型调用也由你自己配 Key。
为什么需要单独一个技能
微信 4.x 把能自动化的路基本堵死了,网上大多数"微信机器人"代码在 4.x 上一行都跑不通:
| 现象 | 后果 |
|---|---|
窗口类名从 WeChatMainWndForPC 变成 Qt51514QWindowIcon |
老库按类名找窗口,永远返回"找不到" |
| UIA 控件树是空的,整窗只有一个 2x2 占位元素 | 所有"按控件路径定位输入框"的方案全部失效 |
| 输入框/发送键坐标随窗口尺寸浮动 | 写死坐标的脚本换台电脑就点偏 |
所以本技能的发送端走纯视觉路线:截窗口 → 本地 OCR 定位 → 真实点击 →
剪贴板粘贴 → OCR 复验 → 回车。每一步都带校验,任何一步对不上就中止,绝不瞎发。
能干什么
- AI 自动回复私聊:白名单里的人(或全量单聊)发来消息 → 拟一句人味回复 → 发出
- 会用你的知识库:报价、课时、地址、常见问答写进
knowledge/,回答就有据可依 - 判断"这句不用回":道谢、表情、好的收到 → 直接跳过(真人不会句句都回)
- 但提问一定回:带问号的句子即使模型想跳过,也会被强制要求正面回答
- 单发工具:不经模型,直接给某人发一句话,用来验证通道
环境要求
- Windows 10 / 11(Server 版、精简系统请先干跑验证)
- 微信桌面版 4.x(实测 4.1.15 正常;3.x 不要用)
- Python 3.9+(推荐 3.11 / 3.13)
- 一个 OpenAI 兼容的大模型 Key(DeepSeek / 硅基流动 / 通义 / 本地 Ollama 均可)
依赖一条命令装完
"<python>" -m pip install wechatauto-replica pywin32 pyautogui pyperclip pillow \
winrt-runtime winrt-Windows.Foundation winrt-Windows.Foundation.Collections \
winrt-Windows.Globalization winrt-Windows.Graphics.Imaging winrt-Windows.Media.Ocr \
winrt-Windows.Storage winrt-Windows.Storage.Streams
> 为什么是 winrt 不是 winsdk:读 Windows 内置 OCR 通常用 winsdk,
> 但它已停止维护,在 Python 3.13 上 PyPI 没有任何可用分发(不是编译失败,是根本没有)。
> 继任者 PyWinRT 的 winrt-* 系列 API 几乎一致。技能里的 wx_compat.py 做了导入重定向,
> 所以代码照旧写 from winsdk...,实际加载的是 winrt。
>
> 镜像源装不上就换官方:把 -i https://pypi.tuna.tsinghua.edu.cn/simple 加上或去掉再试。
> Windows 中文 OCR:系统 OCR 依赖已安装的中文语言包。绝大多数中文 Windows 自带;
> 若 doctor.py 报"OCR 不可用",到「设置 → 时间和语言 → 语言」里
> 给中文补装"可选功能 → 光学字符识别"。
五步跑起来
1. 预检(装完先跑这个)
"<python>" scripts/doctor.py
逐项体检:系统 / Python / 依赖 / 微信版本 / 窗口 / OCR(真画一张中文图去识别,不是只 import)/ 数据库 / 模型 Key / 白名单解析 / 是否已有实例在跑。
全绿再往下走;有 ❌ 它会直接告诉你补什么。它还会顺手告诉你 config.json 的 account 该填什么。
加 --shot 会存一张微信窗口截图,方便核对窗口是否被拖得太窄(建议 ≥1200 像素宽)。
加 --no-network 跳过模型连通测试(不花钱)。
2. 改配置
打开根目录 config.json,至少填两处:
"targets": ["张三"], // 只自动回复这些人(微信里显示的名字或备注)
"min_interval_s": 25 // 同一人两次回复的最小间隔,别调太低
想回复所有单聊就设 "all_private_chats": true,并把不该回的人写进 blacklist
(家人、领导、中介、群发号……命中任意子串即跳过)。
> 强烈建议:account 填上 doctor.py 给你的那个目录名。
> 底层库有个"按密钥可用性自动切账号"的自愈逻辑,会无视你指定的账号去选"能解开最多库"的那个。
> 一旦切到别的号,就会出现读着 A 号的消息、却发给当前登录的 B 号的串号事故。
> 填了 account,对不上就直接拒绝启动。
3. 放 Key
二选一(优先级:环境变量 > 文件):
- 环境变量
DEEPSEEK_KEY(也认WX_LLM_KEY/OPENAI_API_KEY) - 存成根目录
api_key.txt,内容就一行 Key
支持任意 OpenAI 兼容接口,改 config.json 的 api_base / model 即可。
4. 干跑观察
"<python>" scripts/wechat_replier.py
只打印"对方说了什么 → 我打算回什么",一条都不发。
日志出现 已启动; 模式=干跑; 范围=[...]; 知识库=XXX字 就是通了。
让它跑一会儿,看拟出来的回复像不像你说话;不像就改 config.json 的 persona。
5. 正式运行
前台调试用:
"<python>" scripts/wechat_replier.py --live
要长期无人值守就用保活守护(它用 pythonw 无窗口拉起,之后负责一直看着):
"<python>" scripts/keepalive.py
正常时无输出。连这个也不想每次手动敲,就挂一条定时任务(见下)。
知识库:让它答得像你
knowledge/ 目录下的 .md / .txt 会被自动读取(README 和 _ 开头的文件除外),
拼进模型的背景知识里。这不是越全越好——写进口径,别写成宣传稿。
建议这样组织:
## 我做什么
一句话说清业务。
## 常见问题
Q: 多少钱?
A: 具体看课时,我发你报价表。(→ 不要在知识库里写死价格,除非你愿意它直接报)
## 回复纪律
- 日期只按表里的报,表里没有就说"我确认下"
- 价格不主动报数字
- 不知道的一律"我确认下回你"
knowledge/_模板.md 是一份可直接改的骨架。
命令速查
| 命令 | 作用 |
|---|---|
python scripts/doctor.py |
环境预检 |
python scripts/wechat_replier.py |
干跑(不发送) |
python scripts/wechat_replier.py --live |
真回复 |
python scripts/wechat_replier.py --live --all |
真回复 + 全量单聊 |
python scripts/keepalive.py |
保活检查(挂定时任务) |
python scripts/keepalive.py --status |
看运行状态 + 最近日志 |
python scripts/send_once.py "名字" "内容" |
直接发一条(验证通道) |
python scripts/send_once.py "名字" --dry |
只切会话读标题,不发 |
python scripts/wx_ocr.py |
单独测本地 OCR |
稳定运行(无人值守)
两步,做完就不用管:
① 保活守护:scripts/keepalive.py 一条命令管三件事——
- 进程不在 → 无窗口自动拉起
- 进程在但心跳 5 分钟没动(假死)→ 杀掉重启
- 查询失败 → 什么都不做(宁可不动,也不杀错)
② 定时任务:让它在每小时跑一次保活。用工作流/计划任务工具建一条,任务内容:
执行 "<python>" "<技能目录>\scripts\keepalive.py"
- 输出为空:一切正常,什么都不要说
- 输出以 ✅ 开头:一句话告诉用户(例:"微信助手掉线了,已自动恢复")
- 输出以 ⚠️ 开头:把内容照转给用户
命令要用绝对路径、单条执行,不要 cd 拼接。正常时它完全静默,只有真发生动作才出声。
内置护栏
- 只回名单里的人(白名单或全量+黑名单),群聊 / 公众号 / 系统号 / 自己一律不碰
- 防发错人:发送前 OCR 读会话标题,不含目标关键词就中止
- 防误发:粘贴后 OCR 复验输入框真有字才按回车;发送后再验证输入框已清空
- 限频:同人最小间隔 + 每小时总量上限
- 停止词:对方说"停止监听 / 别回了 / 关掉"即跳过
- 问句必回:带问号的句子被模型判成"不用回"时,强制重答一次
- 干跑默认:不加
--live永远只打印不发送 - 不碰破坏性操作:代码里没有 Esc(微信 4.x 按 Esc 会退出当前聊天/隐藏窗口)、
不用最小化恢复(会把 Qt 渲染搞成白屏)
安全与合规
- 自己用、低频。默认 25 秒间隔,不要为了"秒回"把间隔调到个位数
- 不要用来群发营销或骚扰——高频自动化很容易触发平台风控,风险落在账号上
- 回复要有人味:短句、口语、不加编号和括号,否则一眼就看得出是机器
- 出现平台风控提示 → 立刻停掉,把间隔调大
- 数据不出本机:只读本机微信数据用于判断回复,不外传;模型请求只发对话内容
- 微信升级后窗口布局可能变,发送会先在标题校验处中止(不会乱发),需要重新校准比例
文件结构
wechat-autoreply/
├── SKILL.md 本文件
├── config.json ← 唯一需要改的地方
├── api_key.txt 模型 Key(自己新建,别提交/分享)
├── knowledge/ 业务知识库(.md/.txt 自动引用)
│ ├── README.md
│ └── _模板.md
├── scripts/
│ ├── doctor.py 环境预检
│ ├── wechat_replier.py 主程序:监听 + 拟回复 + 发送
│ ├── wx_send.py 发送通道:截图/OCR/点击/粘贴/复验
│ ├── wx_window.py 窗口定位、截图、DPI 处理
│ ├── wx_ocr.py Windows 内置 OCR(同步版)
│ ├── wx_compat.py winsdk → winrt 导入重定向
│ ├── wx_proc.py 进程存活判断(pid 文件 + Win32,不用 powershell)
│ ├── keepalive.py 保活守护
│ └── send_once.py 单发工具
├── references/
│ └── pitfalls.md 排坑手册(出问题先看这个)
└── data/ 运行时生成:日志、状态(不用管,可随时删)
出问题
先跑 python scripts/doctor.py,再查 references/pitfalls.md——
里面按症状分类写了 18 条实测坑(发不出去、回错人、静默退出、OCR 拆字、白屏、
后台进程莫名消失……)和对应处置。