文档
消息监听
默认走数据库水位增量,不漏消息、群消息也带发送者、重启续跑不重复。
三行起一个监听
from wx4auto import WeChat
wx = WeChat()
def on_msg(msg, chat): # ← 签名与 wxauto4 一致
who = msg.get_sender_name(fetch=True) # 群里也是真名,零成本
print(f"{chat.who}: {who} -> {msg.content}")
wx.AddListenChat("大模型能力以及微调", on_msg)
wx.AddListenChat("爱你老己", on_msg) # 群名带 emoji 也能匹配
wx.StartListening()
wx.KeepRunning() # 阻塞住主线程
⚠ 只
AddListenChat不会开始轮询,必须调StartListening()。 只登记不启动时,等 30 秒一个回调都不会有 —— 这个坑踩过很多次。
为什么走数据库
底层是轮询本地库的 sort_seq 增量:
| 数据库路线(默认) | 旧 UIA 路线 | |
|---|---|---|
| 微信窗口 | 不需要可见,也不需要开独立窗口 | 必须可见,且每个会话要独立成窗口(有上限) |
| 群消息发送人 | 直接给出 | 空串,要 fetch=True 点资料卡,每条 2~3 秒 |
| 漏消息 | 不会(按 sort_seq 水位,与渲染无关) |
虚拟列表只渲染可见区域 |
| 首次启动 | 只推新消息(水位自动置为当前最新,不刷历史) | 同 |
| 重启续跑 | 水位落盘,不重复推送 | 无 |
几个必须知道的细节
msg.get_sender_name(fetch=True) 的 fetch 会被忽略
签名与 wxauto4 保持一致,但这里是查数据库联系人表, 不点头像、不弹资料卡、零成本。
自己发的消息按 UIA 侧约定返回空串,用 msg.attr == "self" 判断。
回调里仍然可以发消息
def on_msg(msg, chat):
if msg.type == "text" and "在吗" in msg.content:
chat.SendMsg("在的") # 能用
发送需要界面,这时会按需把会话切到主窗口聊天区(并照常走“发送前最后一道闸”)。 想完全不动界面,就只在回调里读 / 记日志。
监听所有会话
wx.AddListenAll(on_msg) # 会自动发现新建的群
想退回旧行为
wx.AddListenChat(name, cb, source="uia")
# 或全局
WxParam.DATA_SOURCE = "uia"
名字解析
先精确,再模糊:真名 爱你老己❤️,按 爱你老己 调用也能命中。
有歧义时会打 WARNING 并取最接近的那个。
监听目标在库里找不到会明确失败,不会挂一个永远收不到消息的监听。
阻塞等一条消息
msg = wx.WaitForMessage("张三", timeout=30) # 他回我了 → Message;超时 → None
msg = wx.WaitForMessage(["群A", "群B"], timeout=60,
predicate=lambda m, c: "上线" in (m.content or ""))
内部是「临时挂监听 → 队列收集 → 命中就返回 → finally 里摘掉监听」。
⚠ 两个坑: ① 只
AddListenChat不会开始轮询,必须调StartListening()(本方法已内置 —— 只登记不启动时,等 30 秒一个回调都没有); ② 自己发的消息也会触发,用msg.attr == "self"区分。
定时发送
wx.SendLater(30, "该吃药了", who="妈妈") # 30 秒后
wx.SendLater("09:00", "早上好", who="张三", jitter=120) # 每天 9:00(±2 分钟抖动)
job = wx.SendLater("12:00", "开饭", who="群A")
job.cancel()
Scheduler 是进程内的轻量定时器(纯 threading.Timer,无依赖、不持久化)。
要「重启也在」的定时任务,请交给系统任务计划程序去拉起本库的脚本。
jitter 是给「拟人化」用的 —— 避免每天 09:00:00 整点准点发这种机器特征。
完整实战:陪聊机器人
仓库里有一个完整的「主动发 + 接话 + 自动俏皮回复」程序:
python tools/chat_700yi.py # 互动聊天(默认)
python tools/chat_700yi.py --send "在吗" "出来聊天" # 主动连发多条
python tools/chat_700yi.py --opener # 俏皮开场白
python tools/chat_700yi.py --auto # 全自动陪聊(只听 + 接话)
python tools/chat_700yi.py --auto --no-reply # 只看不回
设计要点:
- 收走数据库 —— 不需要窗口可见、群消息也能拿到发送人
- 发走 UIA(微信的设计:发送必须经过界面), 自带「切换会话 → 发送前校验 → 回车前最后一道闸」
- 俏皮回复是本地规则引擎(不调外部 API):关键词分类 + 模板随机 + 防重复 + 限流(默认两条回复间隔 ≥4 秒、每分钟 ≤10 条), 约 1/3 概率「连发两条」(真人的节奏)
- 发送失败分两类:切换 / 窗口类失败(消息还没出去)会自动重试, 其它失败不重试(避免同一条发两遍)