文档

消息监听

默认走数据库水位增量,不漏消息、群消息也带发送者、重启续跑不重复。

三行起一个监听

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 概率「连发两条」(真人的节奏)
  • 发送失败分两类:切换 / 窗口类失败(消息还没出去)会自动重试, 其它失败不重试(避免同一条发两遍)