大肥鱼-AstrBot-NapCat-搭建与踩坑
从零搭建一个 QQ AI 陪伴机器人:AstrBot + NapCat 全流程与踩坑实录
这篇不是"跑通就行"的入门文,而是一份跑了半个月、掉了二十多次线之后攒下来的实战笔记。
如果你正打算用 AstrBot + NapCat 接一个 QQ 机器人,或者已经在用、但被"莫名其妙掉线 / 半夜弹黑窗 / 消息不回"折磨,这篇应该能帮你少走很多弯路。
一、先说结论(省流版)
如果你只想要能跑不折腾的方案,直接抄这四条:
- NapCat 用官方
NapCat.Shell.Windows.Node独立包,别用 OneKey 注入版。 - 判在线看日志和探活接口,别看
online字段——它会骗你。 - 守护脚本必须加失败熔断,否则死循环重登会把账号玩进风控。
- Windows 上一切黑窗,九成来自计划任务和
.cmd本体,不是你以为的那个程序。
下面逐条展开。
二、整体架构
QQ 客户端(协议层由 NapCat 承担)
↕
NapCat(6099 = WebUI 管理台;3011 = HTTP 探活口,发消息也走它)
↕ 反向 WebSocket(NapCat → AstrBot ws://127.0.0.1:6199/ws)
AstrBot(6185 = WebUI;6199 = 反向 WS 服务端)
├ 对话模型:云端 LLM(OpenAI 兼容接口)
├ 视觉模型:本地 Ollama 或免费云模型
├ 向量嵌入:bge-m3(本地或云)
└ 语音:TTS 克隆 / 官方语音合成
分工要说清楚,不然排查方向一定跑偏:
- "被踢下线"发生在 NapCat ↔ QQ 服务器之间,跟你的 Python 业务代码基本无关。
- "不回消息"可能是三层里的任意一层:协议端没收到、AstrBot 没触发、模型超时。
- AstrBot 插件管不到 NapCat 掉线——这是两层的事,所以市面上没有"防掉线插件"这种东西。
三、安装推荐(组件怎么选)
3.1 AstrBot:用 venv + pip,别用 Docker
python -m venv <BOT_ROOT>\astrbot\.venv
<BOT_ROOT>\astrbot\.venv\Scripts\pip.exe install astrbot
为什么不用 WebUI 一键更新:CLI/venv 安装的 AstrBot,点 WebUI 更新会报:
You are running AstrBot via CLI, please use pip or uv tool upgrade
正确升级姿势:
# 1) 先停(杀 6185 监听进程)
# 2) 升级
<BOT_ROOT>\astrbot\.venv\Scripts\pip.exe install -U astrbot==<版本>
# 3) 再起
3.2 NapCat:三种形态,选错会一直掉线
| 形态 | 包名 | 依赖桌面 QQ | 稳定性 | 建议 |
|---|---|---|---|---|
| 官方 Shell 独立包 | NapCat.Shell.Windows.Node.zip | ❌ 不需要 | ⭐⭐⭐⭐⭐ | 首选 |
| OneKey 注入版 | NapCat.Shell.Windows.OneKey.zip | ✅ 注入桌面 QQ | ⭐⭐ | 不推荐 |
| Framework 版 | NapCat.Framework.zip | 需自行嵌入 | ⭐⭐⭐ | 进阶 |
为什么强烈推荐 Shell 独立包:
- 自带
node.exe+ 配套wrapper.node,ABI 对得上; - 不依赖桌面 QQ 进程,QQ 更新不会把它带崩;
- 不会和桌面版抢同一账号 Token。
⚠️ 这里有个巨坑:不能拿系统 node 去跑旧包的
napcat.mjs。
wrapper.node是 Electron 原生模块,系统 node 的 ABI 不匹配,会直接报
Error: The specified module could not be found。
必须用官方包里那一套运行时。
Shell 包解压后的标准结构:
Shell\
node.exe ← 自带运行时,别替换
wrapper.node ← 与 node.exe 配套
index.js ← 入口,内部已设置好 NAPCAT_WRAPPER_PATH 等环境变量
config.json
napcat\napcat.mjs ← NapCat 主体
napcat\config\ ← 配置目录
启动命令就一行:
<NAPCAT_ROOT>\Shell\node.exe index.js -q <BOT_QQ>
-q 是快速登录(复用上次登录态);不加则走扫码。
3.3 版本匹配
- NapCat 版本要与 QQ 版本对得上(在
config.json里能看到curVersion)。 - 不要盲目追最新。社区里有整片反馈:最新版几小时被踢一次,降级到稳定版反而能连续在线几十小时。
- 判断标准只有一个:你的环境下连续在线时长。
3.4 模型与嵌入
| 角色 | 推荐 | 说明 |
|---|---|---|
| 对话 | 任意 OpenAI 兼容云端模型 | 响应快、便宜优先 |
| 视觉 | 本地 qwen2.5vl 或免费云模型 | 省钱 |
| 嵌入 | bge-m3(dim 1024) | 中英混合知识库首选 |
| TTS | 官方 TTS / 克隆 TTS | 克隆注意版权,仅私用 |
知识库参数经验值:chunk 512 / overlap 50 / top_k 50 / top_m 5。
3.5 Windows 上"无窗口启动"
这是 Windows 上最容易被忽略的一节。目标是:开机自启但绝不闪黑窗。
按可靠程度排序:
| 方式 | 效果 | 备注 |
|---|---|---|
pythonw.exe + CREATE_NO_WINDOW | ⭐⭐⭐⭐⭐ | Python 项目首选 |
wscript.exe + Run(cmd, 0, False) | ⭐⭐⭐⭐⭐ | 通用,VBS 包一层 |
-WindowStyle Hidden | ⭐⭐ | 仍会先建 conhost,会闪 |
.bat 直接跑 | ⭐ | 必闪 |
Python 启动器示例:
import os, subprocess
CREATE_NO_WINDOW = 0x08000000
DETACHED_PROCESS = 0x00000008
log = open(r"<BOT_ROOT>\logs\napcat-shell.log", "a", encoding="utf-8")
subprocess.Popen(
[r"<NAPCAT_ROOT>\Shell\node.exe", "index.js", "-q", "<BOT_QQ>"],
cwd=r"<NAPCAT_ROOT>\Shell",
stdout=log, stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL,
creationflags=CREATE_NO_WINDOW | DETACHED_PROCESS,
close_fds=True,
)
再用 wscript.exe 包一层 VBS,彻底避免任何控制台:
On Error Resume Next
Set sh = CreateObject("WScript.Shell")
sh.Run """<PYTHONW_PATH>"" ""<BOT_ROOT>\tools\start_napcat_py.py""", 0, False
注意:
node.exe是控制台程序,CREATE_NO_WINDOW能压住;但某些 Rust 程序(比如bsk.exe)会自己建 console,CREATE_NO_WINDOW无效——这类只能改启动方式,或者启动后ShowWindow(SW_HIDE)。
四、掉线治理(本文核心)
这一节是我掉了二十多次线换来的,建议收藏。
4.1 第一课:别信 online 字段
很多教程教你查 get_status 返回的 online,看到 true 就放心了。
它会骗你。
online: true 只能说明 Node 进程还活着,不代表 QQ 协议层还连着。我遇到过好几次"端口通、online=true、但发消息全失败"的情况——行话叫脑死亡。
正确判据顺序:
日志 > 端口 > API 字段
具体做法:给 NapCat 加一个 HTTP 探活口,用它查登录身份,而不是查状态:
curl -X POST http://127.0.0.1:3011/get_login_info \
-H "Authorization: Bearer <your-token>"
返回里带你的机器人 QQ 号,才算真在线;探活口能连上但返回未登录 → 假在线。
4.2 掉线分型表(对症下药)
| 现象 | 真实类型 | 处理 |
|---|---|---|
| 6099 有,3011 没有 | 卡在登录 | 看日志,多半登录态失效 |
| 端口齐 + online=false | 注入丢失 | 重启注入即可,不用扫码 |
| 端口齐 + 重启后仍 false | 真·登录态失效 | 认命,扫码 |
| 端口全无 + 没进程 | 进程崩了 | 重新拉起 |
| 端口齐 + online=true 但发消息全败 | 脑死亡 | 用 L7 探活触发重启 |
第二行是很多人踩最久的坑:"注入丢失"不等于要扫码,登录态数据还在,重新拉起就能复用。
4.3 注入版和 Shell 版抢 Token(最隐蔽的坑)
如果你同时装过 OneKey 注入版和 Shell 独立包,会看到这种诡异现象:
- Shell 模式反复掉线,免扫码也失效;
- 杀了注入版进程,过几分钟它又自己起来了;
- 新实例启动后 WebUI 端口变成 6100(因为 6099 被老实例占着)。
根因链是这样的:
开机自启 / 守护脚本
→ launcher.bat(注入版)
→ NapCatWinBootMain.exe 注入 QQ.exe
→ 抢同一账号 Token
→ Shell 版被踢
处理办法(缺一不可):
- 停掉所有注入版进程(连进程树一起);
- 把注入器物理隔离(改名
.disabled而不是删除,方便回滚):NapCatWinBootMain.exeNapCatWinBootHook.dll- 注意根目录和
napcat\子目录各有一份,两处都要处理;
- 把启动脚本改成 Shell 版;
- 重启守护进程(旧进程还在跑旧逻辑)。
4.4 绝不能同时跑两组实例
健康的实例数量是固定的:
1 个主进程:node.exe index.js -q <QQ>
1 个 worker:node.exe ...\napcat\mjs -q <QQ>
如果是 2 主 + 2 worker,说明起了两组,必然互相抢 Token,表现就是"能上能下、反复掉线"。
排查命令(Windows):
Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
Where-Object { $_.CommandLine -match 'napcat' } |
Select-Object ProcessId, ParentProcessId, CommandLine
顺手提一句:查这类信息别把 PowerShell 塞进 bash 里,bash 会先吃掉
$_。
用-EncodedCommand(Base64 + UTF-16LE)传脚本,彻底免疫转义。
4.5 失败熔断:这条能救你的账号
-q 快速登录失败时,NapCat 会直接退出(exit code > 0)。
如果你的守护脚本傻乎乎地"退出就重启、重启还失败、再重启"……
就会形成死循环 → 频繁无效登录 → 触发腾讯风控 → 账号被临时冻结。
必须加熔断:
if not napcat_online and fail_count >= 3:
if restarts >= 3:
# 连续 3 次重启仍未上线 → 停手,写标记文件,等人扫码
write_flag("NAPCAT_NEED_MANUAL.txt")
log("FUSE: 已停止自动重启,需人工扫码")
else:
launch_napcat()
restarts += 1
恢复上线后,计数和标记一起清零。
4.6 顺手解决:登录后默认显示"离线/隐身"
NapCat 无头登录后,手机端看你的机器人是离线——不是它没上线,是它从没设置过在线状态。
调一次就行:
curl -X POST http://127.0.0.1:3011/set_online_status \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"status":10,"ext_status":0,"battery_status":0}'
status: 10 = 在线。三个字段缺一个都会报 schema 错误。
注意这个状态不持久,NapCat 重启就回到默认。做法:在守护循环里"检测到在线且未设置"时设一次,掉线时把标记清掉。
五、看门狗设计(四道防线)
一个合格的看门狗,要能区分四种"看起来都像挂了"的情况:
| 防线 | 判据 | 动作 |
|---|---|---|
| 进程 | 6185 / 6099 端口不通,连续 3 次 | 拉起进程 |
| 连接 | 3011 探活失败 ≥120 秒,但进程在 | 重启 AstrBot 逼重连(15 分钟节流) |
| 假死 | 最后一条日志是"收到用户消息",之后 ≥15 分钟无新日志 | 连续 2 票且距上次 >20 分钟 → 重启 |
| 重启后 | AstrBot 刚起来 | 自动重载依赖插件 |
假死判定是重点,用"日志静默 30 分钟"会疯狂误判(深夜没人说话也会被判死)。改成语义版:
只有当"最后一条日志恰好是收到用户消息、但之后一直没处理"时才怀疑假死。
空闲时完全不判,零误报。
另外两个工程细节:
- 掉线告警别弹窗:晚上会被骂。写日志 + 状态文件就够。
- 每日定时重启一次:作为兜底,防累积性卡死(凌晨执行最安全)。
六、Windows 黑窗治理(排查顺序很重要)
"半夜弹一个黑框一闪而过"这种事,按这个顺序查,基本一轮就能定位:
- 启动文件夹
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup - 注册表 Run
HKCU\Software\Microsoft\Windows\CurrentVersion\Run+HKLM\...\Run - 计划任务(最容易漏)
Get-ScheduledTask | Where-Object { $_.State -ne 'Disabled' } | ForEach-Object { "{0,-30} {1}" -f $_.TaskName, ($_.Actions.Execute + ' ' + $_.Actions.Arguments) } - 被引用的
.cmd/.bat本体(超级容易漏!)
你改了.vbs,但计划任务指向的是.cmd,.cmd里还写着:loop ... goto loop——黑窗就来自这里。 - 进程树和工作目录
父进程已退出、Get-CimInstance Win32_Process -Filter "Name='cmd.exe'" | Select-Object ProcessId, ParentProcessId, CommandLinecmd.exe还挂着的,就是孤儿进程。
常见元凶清单:
- 自愈脚本的
:loop死循环(一个进程没退干净,还抢锁) - 软件更新计划任务(每小时跑一次,必须管理员权限,会闪 UAC)
- 显卡/游戏辅助类程序每 2~3 秒轮询一次 PowerShell
- 用了
python.exe而不是pythonw.exe的定时备份任务
七、坑位速查表
| # | 坑 | 解法 |
|---|---|---|
| 1 | CLI 装的 AstrBot 点 WebUI 更新报错 | 用 pip install -U astrbot==<版本> |
| 2 | taskkill /F 杀不掉僵死进程 | 改用 .NET [Process]::GetProcessById($pid).Kill() |
| 3 | 系统 node 跑 napcat.mjs 报模块找不到 | 用官方包自带 node.exe + wrapper.node |
| 4 | 机器人反复掉线 | 先查是否两组实例 / 注入版抢 Token |
| 5 | 手机端显示机器人离线 | 调 set_online_status(status=10) |
| 6 | 重启后卡在"二维码已扫描" | 重启 NapCat(未登录状态重启零损失) |
| 7 | 自动扫码方案失败 | QQ 禁止相册/长按授权,只能用摄像头 |
| 8 | 插件配置改完就丢 | 重载插件会用内存值覆盖文件,改完别立刻 reload |
| 9 | 批量改配置被拒 | PUT /api/v1/system-config 必须传完整配置树 |
| 10 | PowerShell 传参报"缺少表达式" | bash 吃掉了 $,用 -EncodedCommand |
| 11 | 防火墙/杀软导致卡顿 | 把项目目录加进白名单(限制 I/O 的杀软尤其明显) |
| 12 | 掉登录期间的消息 | QQ 协议端直接丢弃,无法补回复 |
八、常用 API 速查
# 登录拿 token
POST /api/v1/auth/login {"username":"<user>","password":"<pwd>"}
# 插件管理
POST /api/plugin/reload {"name":"<plugin>"}
POST /api/plugin/on|off {"name":"<plugin>"}
GET/POST /api/plug/<plugin>/get_config|save_config
# 知识库
GET /api/v1/knowledge-bases
POST /api/v1/knowledge-bases {"name":"...","embedding_provider_id":"..."}
POST /api/v1/knowledge-bases/{id}/documents (multipart: file)
# 代发消息(走 NapCat 探活口)
POST http://127.0.0.1:3011/send_group_msg {"group_id":<gid>,"message":"..."}
POST http://127.0.0.1:3011/send_private_msg {"user_id":<uid>,"message":"..."}
⚠️ v4.x 的 API 前缀是
/api/v1,不是/api;而且用curl.exe调,PowerShell 的Invoke-RestMethod在登录接口会 422。
九、结语
做完这一整套,我的感受是:
机器人项目的稳定性,八成不在"AI 那部分",而在启动链路和守护逻辑。
模型再强,一掉线就是零;守护脚本写错一个循环,账号都能搭进去。
如果只让我留三条建议:
- 别用注入版,Shell 独立包能省掉一半莫名其妙的问题。
- 判在线用探活接口 + 日志,别信状态字段。
- 守护必须熔断,宁可停下等人,也别让它无限重试。
本文基于真实部署记录整理,所有账号、密钥、路径均已脱敏。欢迎在评论区交流你踩过的坑。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)