☰
AnimeGarden HTTP 开放接口实战指南:资源检索、详情、Collection 与元数据 API 详解
2026/10/14 0:16:16 网站建设 项目流程
  • 后端
  • 前端
  • 网页爬虫
  • MCP 服务
  • AI 技能

【免费下载链接】AnimeGarden

動漫花園 镜像站 | 动画 BT 资源聚合站 | 动画 BT 资源开放接口

项目地址:https://gitcode.com/gh_mirrors/an/AnimeGarden
点击查看免费下载

AnimeGarden 是動漫花園的镜像站与动画 BT 资源聚合站,除了网页端,还对外提供一套无需鉴权的 JSON HTTP 开放接口,覆盖状态查询、资源搜索、资源详情、收藏夹(Collection)以及用户/字幕组/番剧元数据五类能力。本文以仓库中的接口参考文档 api.md 为核心,逐接口讲清 Base URL、分页约定、全部查询参数与响应结构,并结合 服务端路由实现 与 @animegarden/client SDK 的源码,说明参数解析、查询语义和缓存策略等实现细节,读完即可直接用curl或 SDK 编写可靠的资源抓取与聚合程序。

一、Base URL、鉴权与总体响应约定

接口的 Base URL 为:

https://api.animes.garden
  • 本文档覆盖的公开端点均不需要任何鉴权(仓库中/admin/*管理端点使用 Bearer Token 鉴权,属于运维内部接口,不在开放接口范围内,见 admin.ts);
  • SDK 的默认baseURL即https://api.animes.garden/,见 constants.ts 中DefaultBaseURL的定义;
  • 服务端对所有开放接口启用了 CORS(origin: '*'),并附带X-Request-Id、X-Response-Timestamp等诊断响应头,请求整体有 60 秒超时,超时返回408与{ status: 'ERROR', message: 'Request timeout after waiting 60 seconds...' },见 server/index.ts。

1.1 状态码与错误模型

响应体约定遵循统一的status字段模式:

  • 成功响应通常带status: "OK";
  • 错误响应通常带status: "ERROR"和message,例如详情接口的message会是Unknown detail id: dmhy 123;
  • 未匹配到资源时,服务端还可能返回{ status: 'ERROR' }配合500状态码,见全局错误处理器 server/index.ts。

1.2 分页对象 pagination

资源列表的分页信息统一放在pagination对象中:

interface PaginationResult { page: number; // 从 1 开始 pageSize: number; // 请求的每页条数 complete: boolean; }
  • page从1开始;pageSize是请求的每页条数,实际返回的资源条数可能更少(最后一页常见);
  • complete: true只表示"当前页之后没有更多匹配资源",不代表调用方已经取遍了之前各页。

服务端在解析分页参数时会做归一化:page非法或小于1时回落到1;pageSize非法、小于1或超过MaxRequestPageSize(1000)时回落到DefaultPageSize(100),见 resolver.ts 与 constants.ts。

此外,resources-query.ts 定义了深分页保护:当(page - 1) * pageSize + pageSize > 10000时抛出ResourcesDeepPaginationError,接口返回400;慢查询繁忙返回503,慢查询超时返回504。也就是说,即使pageSize=1000,page最多也只能推进到offset不超过约 1 万条的位置,超出时请改用时间窗口(before/after)收窄查询。

二、状态 API:GET /

用于获取 API 状态、当前时间戳与上游 provider 的健康状况:

  • 参数:无;
  • 响应:200,包含status: 'OK'、timestamp(上游数据时间戳)、providers(各 provider 的健康状态),以及指向openapi.json与llms.txt文档的发现链接links,见 server/index.ts;另有结构几乎相同的/health端点可供探活。
curl 'https://api.animes.garden/'

providers里的四个上游(dmhy、moe、mikan、ani)即本项目全部受支持的 provider 常量SupportProviders,见 constants.ts。

三、资源 API

3.1 GET /resources:多条件资源检索

GET /resources是核心查询端点,支持 query-string 参数,也支持 JSON body(服务端通过ctx.req.json().catch(() => undefined)同时解析两者,body 优先,见 resources.ts)。路由本身注册了/resources、/resources/、/resources/:page以及按 provider 限定的/resources/{provider}、/resources/{provider}/:page等变体。

查询参数一览(query 参数均可重复出现,多值字段在同字段内是OR关系):

参数说明备注(源码补充)
page页码,从1开始默认1;非法值回落1
pageSize每页条数默认100,最大1000,超限回落默认值
after时间下界,保留创建时间不早于该时刻的资源接受日期字符串或毫秒时间戳,服务端用 zodcoerce.date解析
before时间上界,保留创建时间不晚于该时刻的资源同上
search全文检索词,匹配标题/内容可多值;search存在时会覆盖include(优先级更高)
include标题包含匹配词,search的轻量替代可多值,命中其一即可
keyword必需关键词;重复该参数表示多个必需词全部命中(AND 语义)
exclude屏蔽词;命中的资源被剔除只要命中任一屏蔽词即剔除
type资源分类过滤(如 动画、合集、音乐)可多值,同字段内 OR
subjectBangumi 番剧 ID 过滤可多值,同字段内 OR
fansub字幕组名称过滤可多值,同字段内 OR
publisher发布者/上传者名称过滤可多值,同字段内 OR
tracker是否将 magnet 的 tracker 值返回取值为true/yes/on(不区分大小写)时启用,否则响应中会删除tracker字段
metadata是否返回解析后的元数据(如anipar结果)取值同上;数据库列类型即{ anipar?: ParseResult },见 schema/resources.ts

tracker与metadata的开关逻辑在 resources.ts:默认都关闭,只有当查询参数值属于['true', 'yes', 'on'](小写比较)时才保留对应字段,否则从每条资源上删除。

响应结构(200,ResourcesResponse):

{ "status": "OK", "resources": [ /* Resource[] */ ], "pagination": { "page": 1, "pageSize": 30, "complete": false }, "filter": { /* 服务端解析归一化后的筛选条件 */ }, "timestamp": "2024-01-01T00:00:00.000Z" }

注意响应中没有与resources同级的顶层complete字段,完成度只存在于pagination内。

Resource对象的字段(SDK 类型定义,见 types.ts):

字段说明
id站内资源主键
provider/providerId上游来源与上游侧 ID
title/href资源标题、上游详情页链接
type资源分类(动画、合集、音乐等)
magnetmagnet 链接
tracker仅在tracker=true时返回
size资源大小(字节)
fansub字幕组{ id, name, avatar },可为空
publisher发布者{ id, name, avatar }
subjectId关联的 Bangumi 番剧 ID,可为空
createdAt/fetchedAt资源创建时间 / 服务端抓取时间
metadata仅在metadata=true时返回,含anipar解析结果

curl 示例(摘自 api.md 原文,URL 编码后的中文条件):

# 搜索「葬送的芙莉莲」,必需词 1080p / 简体内嵌,类型限定动画 curl 'https://api.animes.garden/resources?search=%E8%91%AC%E9%80%81%E7%9A%84%E8%8A%99%E8%8E%89%E8%8E%B2&keyword=1080p&keyword=%E7%AE%80%E4%BD%93%E5%86%85%E5%B5%8C&type=%E5%8A%A8%E7%94%BB&page=1&pageSize=30'

仓库 examples/api.http 中还有更多可直接运行的组合,例如:

### 按时间窗 + 字幕组/发布者过滤 GET https://api.animes.garden/resources?type=动画&fansub=LoliHouse&publisher=LoliHouse&after=2023-04-16T13:00:00.000Z&before=1681653600000 ### 多字幕组 OR 过滤 GET https://api.animes.garden/resources?fansub=ANi&fansub=爱恋字幕社 ### 带复杂组合条件的 JSON body 查询 GET https://api.animes.garden/resources?type=动画 Content-Type: application/json { "include": ["机动战士高达", "水星的魔女"], "keywords": ["第二季", "ANi"] }

查询语义(重点),来自文档 Notes 并经 resolver.ts 源码印证:

  • 不同查询组(type、subject、fansub/publisher、时间窗、标题条件)之间是AND关系;
  • fansub、publisher、type、subject、include等多值字段在同一字段内是 OR关系;
  • search优先级高于include:解析器在filter.search非空时会直接delete filter.include(resolver.ts);
  • keyword是必需词(AND 语义),exclude是屏蔽词,命中即剔除;
  • 标题匹配前会先做归一化:全角转半角、繁体转简体(normalizeTitle,见 utils.ts),因此中英文标点混用、繁简差异不影响匹配。

3.2 GET /detail/{provider}/{id}:单资源详情

获取某条资源的完整详情(描述、文件列表、多 magnet):

  • 路径参数:
    • provider:dmhy|moe|mikan|ani;
    • id:上游侧资源 ID 字符串(例如 dmhy 的帖子 ID);
  • 响应:200返回{ status, resource, detail, timestamp },其中detail为ResourceDetail:description(种子描述)、files[]({ name, size })、magnets[]({ name, url })、hasMoreFiles(文件列表是否还有更多),类型见 types.ts;
  • 未找到时返回错误:源码对无法解析的 ID 返回400,对库中不存在的详情返回404,两者响应体均为{ status: 'ERROR', message: 'Unknown detail id: ...' }并设置Cache-Control: no-store;成功响应缓存Cache-Control: public, max-age=86400(24 小时),见 resources.ts。
curl 'https://api.animes.garden/detail/dmhy/123456'

实现上,详情查询走了memo内存缓存(TTL 1 小时、有容量上限与自动 GC,cacheErrors: false不缓存错误),避免对同一provider:id重复打上游,见 resources.ts。

3.3 GET /detail/infohash/{hash}:按 Info Hash 查询

用 torrent 的 info hash 反查资源与详情,适合从磁力链接提取 hash 后直接换取结构化数据:

  • 路径参数hash:40 位十六进制([0-9A-F]{40})或 32 位 base32([A-Z2-7]{32})info hash,大小写不敏感(源码先toUpperCase再校验,见 resources.ts);
  • 响应:200返回{ status, resource, detail, timestamp };
  • 非法 hash 返回400+status: 'ERROR'、Invalid info hash: ...;hash 合法但库中不存在时返回404+Unknown detail info hash: ...。处理这类详情查询时,应把400/404的ERROR统一视为"输入无效或未找到"。

四、Collection API:GET /collection/{hash}

Collection 是"保存好的多组筛选条件 + 每组的第一页结果",适合把一套常用订阅条件固化成可分享的 hash。

4.1 创建与获取

  • 创建:POST /collection或PUT /collection,body 为{ name, authorization, filters[] },服务端对 collection 内容做哈希后落库,返回{ status, id, hash, createdAt };重复提交相同内容不会重复建库(onConflictDoNothing)。见 collections.ts 与 collections/index.ts;
  • 获取:GET /collection/{hash},其中hash为创建时返回的 collection hash。该端点不接受page/pageSize参数。

4.2 响应结构

200返回{ status, hash, name, createdAt, filters[], results[] }(源码另附updatedAt),其中results[i]与filters[i]一一对应,包含:

  • resources[]:该组筛选条件命中的资源(第一页);
  • pagination:固定为{ page: 1, pageSize: 1000, complete: boolean }——每个 filter 固定取第 1 页、每页至多1000条,见 collections/index.ts(query.find(f, { page: 1, pageSize: 1000 }));
  • filter:解析归一化后的资源查询条件。

results[i]上没有与resources同级的complete字段,完成度在pagination内。服务端对该接口结果有 5 分钟的 memo 缓存。

4.3 获取更多资源

当results[i].pagination.complete为false时,取下一页的正确姿势是:

  1. 取出对应filters[i].searchParams(服务端已拼好的查询串);
  2. 调用GET /resources,在searchParams基础上追加page(下一页,即results[i].pagination.page + 1)与相同pageSize(1000)。

Collection 查询本身永远返回page=1,所以"翻页"必须回到/resources完成。

4.4 分页字段迁移(破坏性变更)

旧的完成度字段已移除且不保留别名:

旧响应路径新响应路径
/resources:result.completeresult.pagination.complete
/collection/{hash}:result.results[i].completeresult.results[i].pagination.complete

SDK 同样为资源与 collection 查询结果暴露pagination对象。调用方、fixtures 与断言都应改为从pagination读取全部分页字段。迁移细节(含 SDK 侧CollectionFilter结果态的filter.complete→filter.pagination.complete)在 pagination.md 中有更完整的说明。

五、元数据 APIs

5.1 GET /users:发布者列表

  • 参数:无;响应:200,{ status, users[] },列表项含id、名称、avatar等;
  • 路由实现见 users.ts,数据来自内存中的UsersModule.ids索引,响应缓存Cache-Control: public, max-age=86400;
  • 从源码结构看,users[]每项对应users表一行:id、name(规范名)、avatar、providers(provider →{ providerId, avatar?, aliases? }的映射),见 schema/users.ts。同一个人在不同上游的旧名称会被归一化为aliases(见 normalize.ts 所在的规范化逻辑),因此按providerId匹配比按name匹配更稳定。
curl 'https://api.animes.garden/users'

5.2 GET /teams:字幕组列表

  • 参数:无;响应:200,{ status, teams[] },结构与/users对称(id、名称、avatar、各 provider 侧身份);
  • 路由与 users.ts 中的/teams一致,数据源为teams表,缓存策略相同(24 小时)。
curl 'https://api.animes.garden/teams'

5.3 GET /subjects:番剧列表

  • 参数:无;响应:200,{ status, subjects[] },列表项含 Bangumi 主题 ID、名称、检索词、activedAt、isArchived;
  • 实现见 subjects.ts:返回的是SubjectsModule.activeSubjects,即仅未归档(isArchived === false)的主题,见 subjects/index.ts;
  • 从源码结构看,subjects表以bangumi_id为主键(id即 Bangumi 主题 ID),另存search检索词 JSON、actived_at与is_archived,见 schema/subjects.ts。这些subjectID 可直接用于/resources?subject=...过滤。
curl 'https://api.animes.garden/subjects'

六、配套 SDK:@animegarden/client

服务端仓库自带 TypeScript SDK packages/client,HTTP 层行为与本文各端点一一对应:

  • fetchResources(options):封装/resources;设置count(-1表示取全部匹配)时会以pageSize=1000连续翻页直到pagination.complete或取满count,按href去重并按createdAt降序输出,见 api/resources.ts;
  • fetchResourceDetail(provider, id)/fetchResourceDetailByInfoHash(hash):分别封装两个详情端点,见 api/detail.ts;
  • fetchCollection(hash)/generateCollection(collection):封装 collection 查询与创建,提交时会自动剔除 filters 里的resources、pagination等客户端查询态字段,只保存筛选条件本身,见 api/collection.ts;
  • 通用请求选项FetchOptions支持自定义fetch、baseURL(默认https://api.animes.garden/)、retry(默认 0)、timeout、signal与 hooks,见 types.ts。

SDK 的高级 API 统一返回ClientResult:成功为{ ok: true, ...数据 },失败为{ ok: false, code, error },错误码覆盖NOT_FOUND、BAD_REQUEST、RATE_LIMITED、SERVER_ERROR、NETWORK_ERROR、TIMEOUT、ABORTED、INVALID_RESPONSE,并标注是否可重试;完整模型与取消/超时归类规则见 error-model.md。多页请求失败时会保留已取回的部分resources与pagination,便于降级展示。

七、使用要点小结

  1. 分页:从page=1逐页推进,pageSize建议不超过1000,并始终检查pagination.complete;深分页(offset 超过约 1 万条)会收到400,此时改用after/before时间窗切片;
  2. 查询语义:字段间 AND、字段内 OR;search会覆盖include;keyword全命中、exclude命中即剔除;
  3. 按需取字段:tracker、metadata默认不返回,需要 magnet tracker 或anipar解析结果时显式传tracker=true/metadata=true;
  4. 详情兜底:/detail/{provider}/{id}与/detail/infohash/{hash}的400/404都应按"无效输入或未找到"处理;成功结果有 24 小时缓存(max-age=86400),不适合秒级刷新场景;
  5. Collection 翻页:collection 端点只给第一页(每 filter 至多 1000 条),继续取数请用filters[i].searchParams回查/resources;
  6. 迁移注意:旧的顶层complete字段已删除,所有完成度判断都改读pagination.complete。

以上端点、参数与响应结构的原始出处是仓库内的接口参考文档 api.md,可复现的请求样例集中在 examples/api.http,分页与错误模型的补充文档见 pagination.md 和 error-model.md。

  • 后端
  • 前端
  • 网页爬虫
  • MCP 服务
  • AI 技能

【免费下载链接】AnimeGarden

動漫花園 镜像站 | 动画 BT 资源聚合站 | 动画 BT 资源开放接口

项目地址:https://gitcode.com/gh_mirrors/an/AnimeGarden
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询