我用一台 2 核 2G 的服务器,养了一个会聊天的 QQ 机器人
缘起
想让常待的那个群里,多一个说话像人的机器人。
试过现成的框架,两条路都不太顺:要么太重(一套跑下来吃掉小服务器一半内存),要么太"机器人"(回话工整、没有脾气)。最后选了一个偏小众的组合,折腾了三天,把过程里真正有用的部分记在这里。
它长什么样
三层,缺一不可:
- QQ 客户端 —— 真正登录的是它。跑在服务器上,没有图形界面。
- NapCat —— 把客户端的能力翻译成标准协议。它自己没有账号,只是挂在客户端上的一层。
- QQ Agent —— 人设、记忆、语气、各种技能。它不认识 QQ,只认识 NapCat 给的接口。
三者用 OneBot v11 连接:一条长连接收消息,一个 HTTP 接口发消息。
这个分层的好处是:哪天想换协议端,第三层一行代码都不用改。
六个关键决定
| 决定 | 理由 |
|---|---|
| 选 Ubuntu 而不是 Windows | Windows 服务端光系统就吃 1G 内存,2G 机器不够用;而且无头模式根本不需要图形界面 |
| 不装宝塔 | 它自带一套 Nginx,会和已经调好的反向代理打架;面板本身也是额外的攻击面 |
| 用 NapCat 而不是官方机器人平台 | 官方平台不能进任意群、不能像真人一样说话 |
| 前面加一层 Nginx 反代 | 控制台的监听地址是写死的回环地址,不放代理根本连不上 |
| 数据库用 SQLite 而不是 MySQL | 省下 300MB 内存,个人站点这个量级完全够 |
| 告警走微信而不是 QQ | QQ 掉线的时候,QQ 通知必然发不出去 |
踩过的几个坑
① 浏览器反复弹密码框
不是密码错。NapCat 的网页用 Authorization 头传自己的令牌,而 Nginx 的 Basic 认证也用同一个头——一个请求只能有一个值,前端一覆盖,Nginx 就认为"没带密码",于是再弹一次。
② 技能全部报"缺少配置文件"
zip 解压时多套了一层同名目录,加载器只认第一层。拍平就好。
③ 二维码一直显示已过期
不是手慢。二维码有一条自动刷新循环,循环停了,文件就不再更新——拉多少次都是同一张死码。看文件修改时间才发现它七分钟没变过。
④ 自动重登不是万能的
登录态被吊销时,"快速登录"必然失败,密码登录会被要求过短信验证。这一步脚本做不了,只能人工。
⑤ 同一张图,命令行能下,程序下不动
curl 一百次成功,Node 的 fetch 有一半超时。不是网络不通,是两者对失败地址的处理方式不同。
几个数字
- 服务器:学生优惠,实付 ¥0(原价 ¥284.99,一年)
- 域名:首年 ¥1
- 微信推送:¥3.9,一次性
- 常驻内存:机器人 + 博客 + 两个面板,约 560 MB / 1.7 GB
还没解决的问题
机房 IP 跑非官方协议端,平台侧的风控是常态。最密的一天被踢下线五次,每次都要重新扫码。
目前的应对是三条:掉线立刻微信告警、告警里直接带扫码链接、关掉风险最高的行为(比如自动发说说)。能降频,但降不到零。
一点感受
回头看,整个过程里我大部分时间不是在"写代码",而是在描述现象和判断某个建议靠不靠谱。
真正省时间的地方,是有人能立刻说出"这不是你配错了,是这两个东西抢同一个请求头",而不是让我在十几个可能的配置项里逐个试。
工具能跑多快是一回事;能不能在出错时给出可验证的解释,是另一回事。
本文中的服务器地址、账号与令牌均已脱敏处理。