博客评论区机器人接入说明
面向站外开发者。读完本文即可实现一个评论区机器人,无需阅读本站源码。
本文是接口契约的唯一对外口径。字段、限频数值、错误码均照实抄录, 若与源码不符以源码为准(但也请提 issue —— 那就是本文过期了)。
0. 一句话说清
没有专用的「机器人接口」。 机器人就是一个普通的登录账号, 走和对人完全一样的 HTTP 接口。你需要的只有三件事:
- 一个 core+ 账号(§2)—— 注册出来是
user,需要提权一次 - 读评论(§6)—— 两条路都要登录,且同一档 core+
- 一个 POST 发评论(§7)
无需申请 token、无需白名单、无需站长开任何开关。
⚠️ 但有一件事本文档必须提前说清:评论区没有推送。 讨论那边有 SSE 长连接, 评论区没有 SSE、没有 webhook —— 想知道「有没有新评论」只能轮询(§6)。 这是评论区与讨论最大的差异,请先按轮询设计你的机器人。
1. 能力边界(先读这段)
| 范围 | 能读 | 能发 | 说明 |
|---|---|---|---|
| 某篇文章的评论 | ✅ | ✅ | 读与发都需 core+ 且登录 |
| 全站最近评论 | ✅ | ❌ | 只读接口,见 §6.2 |
| 其他用户的评论 | ✅ | ✅ | 评论是公开内容,任何人都能回复任何人 |
| 别的用户的账号 | ⚠️ | ❌ | 只有公开资料 GET /api/users/:id(免登录、按查看者收敛),见 docs/bot/account-bot.md §6 |
评论区没有成员表、没有可见性限制 —— 评论挂在文章下,所有读者看到的内容完全一致。 机器人的权限边界是三条:core+ 角色、登录状态、是否被禁言。 (角色要求与讨论一致,见 §2.2。)
⚠️ 读接口同样要求 core+。 本站没有只为读开放的豁免 —— 机器人模型统一是 「一个 core+ 账号 + 会话 cookie」,见 §2 与 §3。
ℹ️ 文章可以对外公开,评论域不受影响。 作者能逐篇把文章设为对外可见,那种情况下 站外读者只看得到正文,看不到评论区(也不显示评论数)。但评论接口本身的档位 一个字都没变:仍然是 core+ 且登录 —— 站内成员照常能读能发一篇对外文章的评论。 换句话说,「对外」是视图的属性,不是评论接口的属性。
⚠️ 机器人享受不到任何豁免:它同样会被禁言(被禁言期间发评论返回
403 您已被禁言,无法发表评论),也同样受每日限额约束(§9)。 这是刻意设计——出问题时站长能像处理普通用户一样处理它。⚠️ 而且机器人发的评论会真的给别人发通知(§8)—— 你 @ 不到人,但你的 回复会出现在对方的通知列表里。这是一个会对真人产生后果的接口,见 §11。
2. 准备账号
2.1 注册
POST /api/auth/register
Content-Type: application/json
{
"username": "mycommentbot",
"email": "bot@example.com",
"password": "********",
"invite_code": "可选,填有效邀请码则直接升为 core",
"turnstileToken": "可选,站点启用 Turnstile 时必填"
}
校验规则:
| 字段 | 规则 |
|---|---|
username |
3–20 字符;仅允许字母 / 数字 / _ / -;不能以 - 或 _ 开头或结尾 |
email |
常规邮箱格式,≤100 字符 |
password |
≤100 字符 |
成功即自动登录(响应会 Set-Cookie,见 §3)。
📌 注册需由人工完成一次,这是预期流程。 机器人账号不开放脚本自助注册 (数量有限)。此外,站点若启用了人机验证(Turnstile),脚本同样无法自行注册。
做法:由人工在浏览器里建号一次,之后机器人用账号密码登录即可 —— 后续所有交互都不再涉及人机验证。
2.2 提权到 core+
注册出来是 user,而评论区的规则是「只有核心用户可以发表评论」 ——
与讨论一致。两条路:
- 注册时带有效邀请码 → 直接是 core(推荐,全自动);
- 让站长在服务器上执行:
npm run cli -- promote-core mycommentbot
这两条路与讨论机器人完全相同(
docs/bot/chat-bot.md§2.2)。
3. 鉴权
本站没有 Bearer token,会话是一个 HttpOnly Cookie。流程:
POST /api/auth/login
Content-Type: application/json
{ "username": "mycommentbot", "password": "********" }
响应头:
Set-Cookie: raricy_session=<JWT>; Path=/; HttpOnly; SameSite=Lax; Max-Age=2592000
| 属性 | 值 |
|---|---|
| Cookie 名 | raricy_session |
| 有效期 | 30 天 |
HttpOnly |
是 |
SameSite |
Lax |
Path |
/ |
Secure |
站点走 HTTPS 时为是 |
之后每个请求带上 Cookie: raricy_session=<JWT> 即可。
💡 读评论也要这个 Cookie:§6 那两条路都是 core+ 档。本站的机器人模型一直是 「一个 core+ 账号 + 会话 cookie」,没有例外的只读口 —— 发评论(§7)与看通知(§8) 同样要登录。所以哪怕只读不写,也得先备好一个 core+ 账号(§2.2)。
3.1 三个必须处理的点
- Cookie 会过期(30 天)。收到
401就重新登录一次。 - 会话会被主动作废:改密码、被强制下线、被禁言 / 重置密码都会让旧 Cookie
立刻失效(服务端有
session_version快照机制)。表现同样是401。 ⚠️ 被降权(core → user)不属于这一类 —— 会话不会失效,只是评论接口 改回403 需要核心用户权限。别把它当会话失效去重登,重登也还是 403。 - CSRF 校验对你无影响。 本站对写请求校验
Origin/Referer同源, 但两者都缺失时放行。非浏览器客户端本来就不发这两个头 → 天然通过。 ⚠️ 所以不要自作主张伪造一个Origin,写错反而会被判定为跨源而 403。
3.2 会话是否仍有效
GET /api/auth/me
⚠️ 这个接口永远返回 200 —— 会话缺失 / 失效时返回
{ "code": 200, "message": "ok", "user": null },不会回 401。
判据是 user 是不是 null,不是状态码。适合发评论前探活,但请按 user 判。
4. 响应信封与错误码
站内接口(/api/...)共用同一信封:
{ "code": 200, "message": "ok", ...其他数据字段 }
出错时 code 与 HTTP 状态码一致,且只有 code 和 message:
{ "code": 403, "message": "您已被禁言,无法发表评论" }
⚠️ 例外:
/api/spider/*系列的成功响应不走信封,直接返回裸数组 / 裸对象(§6.2)。 但出错时仍走{ code, message }(401 / 403 / 404 都是)。所以别对 spider 一律 按裸数据解析 —— 先看 HTTP 状态码,非 2xx 就按信封读。
| 状态码 | 含义 | 常见 message |
|---|---|---|
400 |
参数错误 | 评论内容不能为空 / 评论内容不能超过5000字 / 父评论不存在或已删除 |
401 |
未登录 / 会话失效 | 请先登录 / 用户名或密码错误 |
403 |
被禁言 / 角色不足 / 跨源 | 您已被禁言,无法发表评论 / 需要核心用户权限 / 跨源请求被拒绝 (CSRF) |
404 |
文章不存在 | 文章不存在 |
429 |
触发限频 | 今日评论已达上限(8000条),请明日再试 |
⚠️ 站内接口一律
Cache-Control: no-store,别在客户端缓存这些响应。 spider 系列中较新的接口(如GET /api/spider/favorites/:id)也带这个头; 评论 / 博客那几条早期接口没有,但它们在服务端也不做缓存 —— 轮询时请自行控制频率(§9)。
5. 时间戳格式(⚠️ 本站最容易踩的坑)
评论的 created_at 是 ISO 8601 字符串,带 Z 后缀:
"2026-09-11T20:31:05.000Z"
但那个 Z 是假的。 本站全库时间戳的语义是「UTC+8 墙上时间,贴 Z 标签」
(历史遗留,见 docs/architecture.md)。上面这个例子表示的是北京时间
2026-09-11 20:31:05,而不是 UTC 20:31:05。
正确处理
// ✅ 想原样展示给用户 —— 直接截断,得到的就是北京时间墙上时间
const wall = created_at.slice(0, 19).replace('T', ' '); // "2026-09-11 20:31:05"
// ✅ 想得到真实瞬间(做时间差、跨时区换算)
const realMs = new Date(created_at).getTime() - 8 * 3600 * 1000;
// ❌ 错误 —— 会整整差 8 小时
new Date(created_at).toLocaleString('zh-CN')
// "2026/9/12 04:31:05" ← 凭空多出 8 小时
简单记法:把字符串里的
Z抹掉,当成 UTC+8 的墙上时间读,就对了。 时区无关的用法(比较两条评论谁更新)不受影响 —— 因为大家偏移量一致。
6. 读评论(两条路,都需要 core+ 账号)
6.1 按文章读 —— 完整的评论树
GET /api/blogs/:id/comments
:id 是文章的 UUID。需要 core+ 账号 + 会话 Cookie(建号提权见 §2,
登录换 cookie 见 §3)。未登录 401,非 core 403。
响应:
{ "code": 200, "message": "ok", "comments": [ /* CommentNode[],见 §10 */ ] }
特点:
- 返回该文章下全部已批准评论,一次给完,没有分页;
- 嵌套结构:
comments是顶层评论数组,回复在各自的children里; - 每条都带
content(Markdown 原文)—— 这是机器人要读的字段; - 已删除且没有回复的评论会被隐藏;有回复的保留,但正文被替换为
[该评论已删除]; - 没有限频。
💡 轮询姿势:这个接口没有增量参数。请自行记住上次见到的评论 id 集合 (或最大的
created_at),每次拉回来做差集。⚠️ 评论 id 是 UUID,不是自增数字 —— 不能当游标用。 这一点与讨论不同 (讨论的消息 id 是全局自增的)。你没法说「给我 id 大于 X 的评论」, 只能拉全量再自己比对。
6.2 读全站最近评论 —— 适合「发现新评论」
GET /api/spider/comments
需 core+ 登录,裸数组,不包信封(未登录 401,非 core 403):
[
{ "id": "…", "blog_id": "…", "author": {…}, "content_html": "…", "created_at": "…" }
]
| 特点 | 说明 |
|---|---|
| 条数 | 最近 100 条,固定 |
| 排序 | 按 created_at 倒序(最新在前) |
| 结构 | 扁平数组,children 恒为 [] |
| 字段 | 只有公共字段(§10.1)。⚠️ 不含 content 原文,只有 content_html |
⚠️ 两个坑:
- 只有 100 条上限。 如果你的轮询间隔里全站新增超过 100 条评论, 中间那些就永久错过了。轮询间隔请留足余量。
content_html不是 Markdown 渲染结果,是「HTML 转义 + 换行转<br>」 的纯文本。想拿 Markdown 原文,请走 §6.1。
6.3 读单条评论 / 单篇文章
GET /api/spider/comments/:id → 裸对象:**§10.1 公共字段 + 恒为空的 `children`**;
⚠️ **不含** §10.2 的 `content` / `image` / `blog` / `liked`;
不存在或已删除 → 404 {code,message}
GET /api/spider/blogs/:id → { "meta": {…}, "content": "Markdown 正文" };不存在 → 404
GET /api/spider/favorites/:id → { "id","title","author","count","blogs" };不存在 → 404 {code,message}
这三条都需 core+ 登录(未登录
401,非 core403)—— 与 §6.1 / §6.2 同一口径。收藏夹那条的完整口径(含限频)见
docs/bot/favorite-bot.md。此处只点一句: 它只读公开收藏夹,且是 spider 系列里唯一有限频的一条。
meta 里有 title / author / category / comments_count 等,方便机器人在
回复时引用文章标题。
7. 发评论 / 回复
POST /api/blogs/:id/comments
Cookie: raricy_session=<JWT>
Content-Type: application/json
{ "content": "说点什么" }
7.1 请求字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
content |
string | 否* | 正文,Markdown 源文(站内客户端渲染) |
parent_id |
string | 否 | 回复某条评论,用被回复评论的 UUID。须同一篇文章且未被删除 |
image_id |
string | 否 | 引用图床图片,必须是你自己上传的 |
quote_blog_id |
string | 否 | 引用一篇文章的 UUID |
* 至少要有一个有效载荷(正文或附件),否则报 评论内容不能为空。
| 长度上限 | 值 |
|---|---|
纯文本评论 content |
5000 字 |
带附件(image_id / quote_blog_id)时的 content |
5000 字 |
两档同值(2026-09 起)—— 此前带附件档是 500 字(「带附件时正文本来就是个图注」)。 服务端仍分两条错误码(
tooLong/captionTooLong),所以两档都按 5000 记即可。 长度按trim()之后计算,恰好 5000 字放行。
不带 parent_id = 顶层评论(会通知文章作者);
带 parent_id = 回复(会通知被回复者)。详见 §8。
7.2 成功响应
{ "code": 200, "message": "评论成功", "comment": { /* CommentNode,见 §10 */ } }
✅ 这里
message是字符串("评论成功"),新评论对象在comment字段里 —— 与讨论机器人的发送接口不同(那个接口的message被消息对象覆盖了)。 判断成功仍建议只看code === 200。
评论创建即 approved,立即可见,没有审核队列。
内容引用 [@<内容ID>]
正文里可以写 [@<内容ID>],服务端原样入库,由渲染端按 ID 长度展开:
| 写法 | 长度 | 效果 |
|---|---|---|
[@a1b2c3d4] |
8 位 | 内联云剪贴板的正文(该剪贴板须公开,或你是作者) |
[@AbCdEf1234] |
10 位 | 内联图床图片 —— 渲染成 /api/images/<ID>/raw 的图 |
[@音频/AbCdEf1234] |
—— | 内联音频 —— 渲染成 /api/audio/<ID>/raw 的播放器(具名命名空间,不按长度分流)。一条正文最多展开 3 个,见 docs/bot/audio-bot.md §6.3 |
[@vOtE12345] |
9 位 | 投票 —— 评论里不展开,原样显示 |
[@123456] |
6 位数字 | 收藏夹 —— 评论里不展开,原样显示(只有博客正文会渲染成卡片) |
要点:
- 一条评论最多展开 1 条云剪贴板,多写的原样留在正文里
- 图床图片最多 50 张;剪贴板正文超过 2000 字会截断并附回原剪贴板的链接
- 写在代码块 / 行内代码里的
[@id]不展开 - 剪贴板正文是另一名用户写的,与正文走同一条净化管线
- ⚠️ 评论区本身就要 core+(§1 / §6.1):未登录访客与非 core 读者根本看不到评论区
(页面的访客视图不渲染它)。所以
[剪贴板 <ID> 加载失败]只会出现在 core+ 读者读到一条别人的私有剪贴板时 —— 它不是评论区的常态
正文里不能手写 <img>(白名单里没有,写了会以转义文本显示)。要贴图用上面的
[@<10位图片ID>],或者用 image_id 字段发图片附件。
📌 用户名片(
[@用户/<用户名>],渲染成头像 + 用户名的行内名片,点进主页) 与表情一样不在上面的表里 —— 它认的是名字而不是 ID。一条评论最多 5 张, 不算 @ 提及(不发通知),取数与权限见docs/bot/account-bot.md§6。
7.3 会被拒绝的情形
| 情形 | 返回 |
|---|---|
| 未登录 / Cookie 失效 | 401 请先登录 |
| 账号不是 core+(见 §2.2) | 403 需要核心用户权限 |
| 账号被禁言 | 403 您已被禁言,无法发表评论 |
| 文章不存在或已隐藏 | 404 文章不存在 |
| 正文为空且无附件 | 400 评论内容不能为空 |
| 正文超长 | 400 评论内容不能超过5000字 / …不能超过5000字 |
parent_id 指向的评论不存在 / 不同文章 / 已删除 |
400 父评论不存在或已删除 |
image_id 不存在、已删、或不属于你 |
400 图片不存在或不属于你,请重新上传 |
quote_blog_id 不存在或已删 |
400 引用的博客不存在或已删除 |
| 触发每日限额 | 429 今日评论已达上限(8000条),请明日再试 |
8. 怎么知道「有人回我了」
评论区没有 @ 提及机制(这点与讨论不同 —— 讨论有 @ 提及且会进通知列表)。 评论区唯一的通知来源是评论之间的回复关系:
| 你发的评论 | 谁收到通知 |
|---|---|
顶层评论(无 parent_id) |
文章作者(action 文章评论) |
回复某条评论(有 parent_id) |
被回复评论的作者(action 评论回复) |
| —— | 自己评自己不发通知 |
所以机器人想知道「有没有人回复我」,只有一条路:登录后轮询通知列表。
GET /api/notifications?page=1&unread_only=true
Cookie: raricy_session=<JWT>
响应:
{ "code": 200, "message": "ok", "unreadCount": 3,
"notifications": [ /* 见下 */ ],
"total": 12, "page": 1, "perPage": 20, "pages": 1,
"hasPrev": false, "hasNext": false }
notifications 条目:
{
"id": "…",
"timestamp": "2026-09-11T20:31:05.000Z", // ⚠️ 同 §5 的假 Z
"action": "评论回复", // 或 "文章评论"
"recipientId": "u_me",
"actor": { "id": "u_xxx", "username": "alice" }, // 触发者,**这就是要回复的对象**
"object": { "type": "blog", "id": "<文章 id>" }, // ⚠️ 嵌套对象,不是两个平铺字段
"detail": "你的评论在《标题》下收到了回复",
"read": false
}
| 字段 | 说明 |
|---|---|
action |
"评论回复"(有人回了你的评论)/ "文章评论"(你的文章被评论) |
actor |
触发者 {id, username}。⚠️ 没有头像字段;actor 已注销时为 {id: null, username: "system"} |
object.type |
"blog" |
object.id |
⚠️ 是文章 id(blogId),不是评论 id |
read |
是否已读 |
⚠️ 通知里拿不到「是哪条评论回复了我」。
object.id只给到文章层面。 所以标准做法是:
- 轮询通知,发现
action === "评论回复"且read === false;- 用
object.id去拉GET /api/blogs/<object.id>/comments(§6.1);- 在树里找
author.id === actor.id、且parent_id指向自己发的某条评论 的最新一条;- 回复它(带上它的 id 作为
parent_id);POST /api/notifications/<通知 id>/read标记已读,避免下轮重复处理。
💡
unread_only=true+ 只处理action === "评论回复"是最省事的过滤方式 —— 顺便也把「文章评论」的通知排除掉了(那是给文章作者的,不是你被回复)。
9. 限频
| 规则 | 额度 | 适用 |
|---|---|---|
commentDaily |
8000 次 / 24 小时 | 发评论(按用户计) |
| 读评论(§6.1 / §6.2,以及 §6.3 的评论与博客那两条) | 无限频 | 随便轮询 |
| 读公开收藏夹(§6.3 第三条) | 120 次/分 / IP | 该系列的例外,见 docs/bot/favorite-bot.md §4 |
| 登录 | 15 分钟内失败 300 次 / IP、100 次 / 用户名 | 仅统计失败 |
| 图片上传(§7.1 引用图时) | 200 张 / 小时 | POST /api/images(一次多张按张数计) |
| 音频上传(引用音频时) | 200 次 / 小时 | POST /api/audio(一次一个文件,见 docs/bot/audio-bot.md §8)。与图片是两个独立的桶 |
超限一律 429。
⚠️ 发评论没有分钟级限额,只有每天 8000 条。 这意味着一台失控的机器人 可以在 1 分钟内刷 8000 条评论,而不是被平滑地限速。请务必在机器人侧 自己做节流(例如「同一篇文章 N 分钟内最多回 1 条」)。
📌 建议只回应「回复了你」的评论(§8 那条路径),而不是「看到新评论就回」 —— 后者在一篇热文下会瞬间刷屏,且很可能触怒站长与读者。
限频计数存在服务端(进程内计数桶,定期落盘快照),重启不会清零 —— 别指望靠重启洗掉自己的用量。但它也不是持久化账本,不要拿它做用量统计。
10. 数据结构
10.1 公共字段(站内与 spider 接口都有)
{
"id": "9f1c…", // UUID,⚠️ 不是自增数字,不能当游标
"blog_id": "3a7e…",
"author": {
"id": "u_xxx", // 可能为 null(作者已被删除)
"username": "alice", // 可能为 null
"is_admin": false,
"avatar_url": "/api/avatar/u_xxx" // 可能为 null
},
"parent_id": null, // 顶层评论为 null
"root_id": null, // 所属楼中楼的根评论 id
"content_html": "纯文本<br>已转义", // 转义+<br>,非 Markdown 渲染
"status": "approved",
"is_deleted": false,
"likes_count": 3,
"created_at": "2026-09-11T20:31:05.000Z", // ⚠️ 语义见 §5
"updated_at": "2026-09-11T20:31:05.000Z"
}
10.2 CommentNode(站内接口额外字段)
在 §10.1 基础上多出:
{
"content": "**Markdown** 原文", // ← 机器人要读的就是这个
"image": { // 引用的图床图片,无则 null
"id": "img_xxx",
"url": "https://…",
"mime_type": "image/png"
},
"image_missing": false, // 引用了图但图已不存在
"blog": { // 引用的博客,无则 null
"id": "uuid", "title": "标题", "description": "…",
"author": "alice", // 作者 username,可能为 null
"updated_at": "2026-09-11T20:31:05.000Z"
},
"blog_missing": false,
"liked": false, // 随「查看者」而变;未登录恒为 false
"children": [ /* CommentNode[],回复 */ ]
}
⚠️
is_deleted: true的评论,content与content_html都已被替换为[该评论已删除]—— 原文不会下发。请不要把占位符当正文去回复。
11. 礼仪与约定
技术之外,三点请配合 —— 评论区的后果比讨论更重,因为它会打扰到真人:
- 让机器人的身份可辨认。 建议用户名带
bot后缀(如mycommentbot), 或在其个人简介里写明「这是机器人」。否则读者会以为在跟人对话。 - ⚠️ 你的每一条评论都会给真人发通知。 顶层评论通知文章作者,回复通知被回复者。 一个「见评论就回」的机器人等于给全站作者群发通知 —— 这是骚扰,且会被禁言。 请只回应明确指向你的那类评论(§8)。
- 别把评论内容外送而不告知。 如果你打算把评论正文发给第三方服务 (AI 模型、日志平台等),请先和站长沟通,并在机器人简介里说明用途 —— 评论作者并没有同意自己的内容被送往站外。
12. 排错速查
| 现象 | 原因 |
|---|---|
读评论也 401 请先登录 |
读接口同样要登录(§6 标题)。没带 Cookie 或会话已过期 —— 重新登录(§3) |
读评论 403 需要核心用户权限 |
账号不是 core+。注册出来是 user,需提权一次(§2.2) |
发评论 401 请先登录 |
没带 Cookie,或会话已过期 —— 重新登录(§3) |
所有写请求 403 跨源请求被拒绝 (CSRF) |
你手动设置了错误的 Origin。非浏览器客户端直接不带该头即可(§3.1) |
发评论 403 您已被禁言… |
账号被禁言,等解禁或联系站长 |
429 |
触发限频,见 §9;注意 8000/天 的硬上限 |
| 时间显示差 8 小时 | created_at 的 Z 是假标签,见 §5 |
| 拿不到评论的 Markdown 原文 | 你用的是 /api/spider/comments(只有 content_html),改用 §6.1 |
| 轮询漏掉评论 | /api/spider/comments 只给最近 100 条,间隔太大就会错过(§6.2) |
| 「给我 id 大于 X 的评论」拿不到 | 评论 id 是 UUID,没有游标语义(§6.1) |
| 通知里找不到「是哪条评论」 | 通知只给到 blogId,需回查评论树(§8) |
回复时报 父评论不存在或已删除 |
parent_id 那条评论被删了,或不属于这篇文章 |
13. 最小可用流程(轮询版)
准备:人工注册一个账号(§2.1)并提权到 core+(§2.2)
循环(每 N 分钟):
1. POST /api/auth/login → 存下 raricy_session
2. GET /api/notifications?unread_only=true → 筛 action === "评论回复"
3. 对每条:
a. GET /api/blogs/<object.id>/comments → 拉评论树(需 core+ 会话,见 §6.1)
b. 在树里找:author.id === actor.id
且 parent_id 指向我自己发的某条评论
且不在「我回复过的」集合里
c. POST /api/blogs/<object.id>/comments
{ "content": "...", "parent_id": "<那条评论的 id>" }
d. POST /api/notifications/<通知 id>/read → 标记已读,避免下轮重复
e. 自行节流:同一篇文章 N 分钟内最多回 1 条
断线 / 401 → 重新登录(§3)。
429 → 退避;注意 8000 条/天 是硬上限。
💡 如果你的机器人只读不写(例如做评论分析、摘要、归档),动作确实更简单 —— 但它仍然需要一个 core+ 账号:§6.1 与 §6.2 的读接口与写接口同一档。 本站没有「匿名只读」的豁免,机器人模型统一是「一个 core+ 账号 + 会话 cookie」。