把 AI 大模型接进 QQ,是很多人做自动化的第一步。这篇记录一套长期稳定运行的方案:NapCat 做协议端,OneBot 协议对接客户端,成本只要一台最低配云服务器。
为什么选 NapCat
早几年大家用 go-cqhttp,但那个项目 2023 年就停止维护了,QQ 版本一升级就登不上。现在的替代方案主要有 NapCat、Lagrange.OneBot 等。NapCat 基于官方 NTQQ 客户端改造,走真实客户端协议,稳定性明显更好,也不需要自己处理签名服务器。
| 方案 | 协议来源 | 维护状态 | 上手难度 |
|---|---|---|---|
| go-cqhttp | 旧版协议 | 已停止 | 低 |
| NapCat | NTQQ 客户端 | 活跃 | 中 |
| Lagrange.OneBot | 第三方实现 | 活跃 | 中 |
整体架构
这套方案分两段:
- 服务端:云服务器跑 NapCat 容器,负责登录 QQ、收发消息
- 客户端:你自己的程序或现成的 AI 客户端,通过 OneBot WebSocket 连过去
QQ 用户
↓ 消息
NapCat(云服务器 · Docker)
↓ OneBot WebSocket (:3001)
你的客户端(本地或另一台机器)
↓ API
大模型
好处是登录态和业务逻辑分开:客户端挂了不影响 QQ 在线,想换客户端随时换。
准备工作
- 一台云服务器,1核2G 足够(NapCat 实际占用约 200MB)
- 装好 Docker
- 一个专门的 QQ 小号,不要用主号
- 安全组放行两个端口:OneBot WS(3001)和 WebUI(609=)
安全提醒:WebUI 端口不要裸奔在公网。至少设一个强 token,或者用安全组限制来源 IP。
第一步:启动 NapCat 容器
docker run -d
--name napcat
--restart=always
-p 3001:3001
-p 6099:6099
-m 400m --memory-swap 600m
-v /root/napcat/config:/app/napcat/config
-v /root/napcat/qq-data:/app/.config/QQ
-e TZ=Asia/Shanghai
mlikiowa/napcat-docker:latest
关键参数:
--restart=always:服务器重启后自动拉起,必须加-m 400m:内存上限,防止吃满小内存服务器-v .../config:配置持久化-v .../qq-data:/app/.config/QQ:QQ 登录态持久化,最容易漏的一条
最后这条如果漏了,每次重建容器都要重新扫码登录 —— 而频繁扫码正是 QQ 风控最敏感的动作。
第二步:登录 QQ
容器起来后访问 WebUI:
http://你的服务器IP:6099/webui
首次登录需要 token,正确来源只有容器日志:
docker logs napcat 2>&1 | grep -i token
会看到类似:
WebUI Token: 7fbf7af05ba1
用这个 token 登录,然后在 QQ 登录页扫码,或用「快速登录」选历史账号。
token 一定从日志里读,不要凭记忆。配置文件和实际生效的 token 可能不一致。
第三步:配置 OneBot WebSocket
WebUI 里进「网络配置」,新增一个 WebSocket 服务器:
- 类型:WebSocket Server
- 端口:3001
- Host:0.0.0.0
- Token:设一个强密码
- 消息格式:array(推荐)
保存后 NapCat 开始监听 3001。注意验证方式:不要只看端口有没有占着,要看 QQ 是否在线 —— 没登录时 docker-proxy 照样占着端口,但后端没有服务,从外部连是连不上的。
第四步:客户端接入
以 Python 为例:
import websockets, json, asyncio
async def main():
uri = "ws://你的服务器IP:3001"
headers = {"Authorization": "Bearer 你设的token"}
async with websockets.connect(uri, extra_headers=headers) as ws:
while True:
msg = json.loads(await ws.recv())
if msg.get("post_type") == "message":
print("收到:", msg["raw_message"])
# 这里接你的 AI 逻辑
await ws.send(json.dumps({
"action": "send_msg",
"params": {
"message_type": "private",
"user_id": msg["user_id"],
"message": "收到啦"
}
}))
asyncio.run(main())
第五步:三层验证
从下往上查,哪一层断了就在哪一层处理:
- QQ 是否在线:WebUI 看账号状态,或用手机发条消息试试
- WS 是否可用:
curl -i http://127.0.0.1:3001,返回 400 或 426 说明服务正常(只是 HTTP 握手不对) - 客户端是否连上:看客户端日志里的连接记录
如果第 2 步返回 000,说明容器里根本没有服务在听,先去看 QQ 有没有登录。
下一步
部署完成不等于稳定。掉线排查和长期运维的问题,我单独写了两篇:
- 连不上怎么办 →《QQ 机器人掉线排查:OneBot WS 连不上的 6 个真实原因》
- 怎么长期跑稳 →《QQ 机器人长期稳定运行:内存、日志与风控的 7 条实战经验》
小结
这套方案的成本就是一台最低配云服务器,纯文本消息流量很小,跑一年也花不了多少钱。真正的成本在维护,尤其是 QQ 登录态 —— 这是最容易出问题的地方1,做好数据卷挂载能省掉大半麻熃。