目标

在 Ubuntu 物理机(i5-3570)上,用 Docker 跑起官方微信 Linux 版,对指定群做全自动监听+回复,并在博客后台单独开一个 WeChat RPA 看板管起来。默认干跑只读不发,调通再真发。

1. 为什么是这套方案

最早想的是全屏截图+视觉模型读图,实测两个问题:旧 CPU 跑图像又慢又飘;全局截屏容易回错群。网盘那篇 Ubuntu_.md 改用独立窗口物理隔离 + 剪贴板轮询 + 水位线,正好对症:wmctrl 按窗口标题只盯一群;Ctrl+A/C 走剪贴板拿纯文本,不怕缩放换肤;MD5 水位记最后一条,新消息才触发,资源极低。

我相对原案做了 8 处加固:相对坐标替代写死 400,250;正则提 sender/time/msg 替代 substring 判自己;结构化水位+去重集;窗口丢失重试;环境变量配置化;15s 发送限流;DRY_RUN 默认只读;rpa+audit 双日志。详见容器目录 DEV_SPEC.md。

2. 容器侧:Dockerfile + start.sh + main.py

底座 ubuntu:22.04(官方 deb 明确支持 jammy,比宿主 25.04 稳)。220M 的 WeChatLinux_x86_64.deb 先下到构建目录 COPY 进去,避免每次构建重下。Xvfb 造 :99 假屏,openbox 当窗口管理器(wmctrl 必须有 WM),x11vnc+noVNC 暴露 5900/6080 给人扫码。

Xvfb :99 -screen 0 1280x800x24 &
openbox &
x11vnc -display :99 -forever -shared -rfbport 5900 -nopw &
websockify --web=/usr/share/novnc/ 6080 localhost:5900 &
/opt/wechat/wechat &  # 实测路径,脚本另有三处兜底探测
DRY_RUN=1 python3 /opt/main.py  # 定向RPA主程序
python3 /opt/vision-loop.py    # 独立截图排错,每5s一张留20张

main.py 主循环:等窗口出现→归位 800x600→建基线(旧消息不回)→每 5s 激活窗口、点阅读区、Ctrl+A/C、pyperclip 读文本→正则解析成 {sender,time,msg}→水位找新→过滤系统消息/自己/非@→剪贴板粘贴+回车。发完睡 1.2s 等上屏再同步水位,防止把自己当新消息。

TARGET_GROUP=VIP客户服务群  # =独立窗口标题,一字不差
BOT_NAME=AI助手
POLL_INTERVAL=5
DRY_RUN=1  # 先只读不发
ONLY_AT=0
MIN_REPLY_GAP=15

3. Web 后台:单独 wechat 模块

遵守站内约束:只增不改旧逻辑。新增 app/models_wechat.py 两表(wechat_targets 配群,wechat_events 收发审计),app/blueprints/admin/wechat_routes.py 7 个路由,两个模板,看板侧栏加一个入口。

看板 /admin/wechat 一页看全:容器状态(docker ps 白名单)、VNC 地址、最新 6 张截图、目标群表、最近 30 条审计;/wechat/logs?kind=rpa tail 日志;/wechat/shot?name=... 看原图。容器启停走 docker stop/start/restart 白名单(只认 wechat-linux/wechat-test)。

容器与库之间不直连:/wechat/api/config 拉配置、/wechat/api/report 按 msg_hash 去重上报,都走 X-API-Key(.env 的 ADMIN_API_KEY),与后台登录隔离。

4. 联调验证

1)docker build -t wechat-linux:4.1 约 3.6G,一次过(中文字体 61M 最慢)。2)先起 wechat-test,截图已看到官方微信扫码登录二维码,noVNC 200。3)浏览器开 http://192.168.1.178:6080/vnc.html 扫码,双击目标群弹出独立窗口,RPA 日志出现“基线已建立”即进入轮询。4)事故复盘:加完路由没重启 uwsgi,老进程不认新 endpoint,全站 admin 500→nginx 502,systemctl restart flaskblog 即好,之后改后台必重启。

5. 风险与下一步

个人号全自动仍可能限流封号:演示用小号+低频+限流+干跑先行。图片语音文件暂只跳过记日志。下一步:main.py 改轮询本后台 api/config 并 report 上报;llm_reply() 桩换成 Qwen/DeepSeek+RAG(先把复制文本正则成结构化数组再喂模型);开 ONLY_AT giảm打扰。