kita / notes

约 2 分钟

Danbooru 被 Cloudflare 挡死,我换了第二图源

图源改造的需求摆在那儿:现在的搜图插件只有一个主源(Lolicon),挂了就回退 Pixiv,链路太薄。我想改成 Yande.re → Danbooru → Pixiv 三级回退。

前两个源都是同一种标签体系(Danbooru 系的 tag),这点很重要——意味着中文关键词只要转成一套标签,两个源都能用。

结果第一个候选就折了。

Danbooru 从服务器 IP 过去直接被拦

在服务器上打 Danbooru 的 API,回来的不是 JSON:

<html><head><title>Attention Required! | Cloudflare</title>

Cloudflare 的拦截页。我一开始以为是要带浏览器 UA,加了 UA 还是一样;再试带 Authorization 的 API key 请求,照样拦。

这套拦截是按来源 IP 判的,不是按请求头。 腾讯云那台机器的出口 IP 在 Cloudflare 那里已经被标记了,加什么头都没用。我把这条验证完才彻底放弃这条路——中间在"是不是 UA 不对""是不是要 API key"上浪费了几轮。

换谁:同标签体系是筛选条件

既然主源没了,第二图源得满足两点:免鉴权能用,以及标签体系和 Danbooru 一致(不然中文标签映射层得写两套)。

我试了几个 Danbooru 系的站,最后选了 Safebooru.org:

  • 同 Danbooru 标签体系,标签名基本可以平移
  • 免鉴权,服务器 IP 过去没被拦
  • 只收 safe 分级内容,和插件"普通分级"的定位刚好对上

链路就定成 Yande.re → Safebooru → Pixiv:前两个都不需要 token,第三个留作最后兜底。

中文标签这块,不自造轮子

原来的想法是让 Yande.re / Danbooru 自己处理中文搜索——不现实,它们只认英文 tag。

改成在 Bot 前面加一层「中文 → Danbooru 标准标签」的转换。标签库我没自己攒,用的现成的:

ffdkj-Danbooru_Tag-Chinese-English-Translation-Table
tag.sqlite  24MB, 328,023 行
schema: tags(name TEXT PK, category INTEGER, cn_name TEXT, post_count INTEGER)

32 万行,直接下载丢进插件数据目录,查询是本地的,不依赖网络。

匹配写成三级:

-- 1. 精确
SELECT name FROM tags WHERE cn_name = ?
-- 2. 模糊(带 post_count 排序)
SELECT name FROM tags WHERE cn_name LIKE ? ORDER BY post_count DESC LIMIT 5
-- 3. 都没命中就原词透传

多候选的时候取 post_count 高的那个——这个字段很有用,等于"这标签有多少人用过",能筛掉生僻译名。

一个没料到的坑:库里带来源注解

精确匹配经常 miss,明明库里有这个词。翻数据才发现 cn_name 存的不只是译名:

甘雨(原神)

带着来源注解。 用户搜"甘雨"两个字,cn_name = '甘雨' 匹配不上 甘雨(原神)。

所以实际跑的是模糊匹配为主,精确匹配只在小部分干净的译名上命中。这个我在建好库、测试查询之后才发现,要是只按设计看书写的代码,上线就是"搜啥都搜不到"。

落地

改完之后在容器里跑了一遍导入测试,确认 tagresolver 能正确把中文转成 Danbooru tag,再重启容器验证插件加载。

服务器上改插件有个细节:文件是 scp 上去的,改完要在容器内 py_compile 检查一遍再重启,不然语法错误会让整个 AstrBot 起不来——这个坑我在别的插件上踩过。

← 回到全部笔记