# 洛克魔法书 Wiki 开放接口

- 在线文档与调试：<https://091p.com/lkwg/api.html>
- 配对孵蛋页面：<https://091p.com/lkwg/breeding.html>（使用 `pets`、`pet-egg`、`pet-appearance` 三项既有资源，无新增上游端点）
- JSON 入口：`https://091p.com/lkwg/wiki-api.php`
- 机器可读目录：`wiki-api.php?api=help`（`api=index`、`resource=help`、`resource=resources` 等价）
- 数据来源：洛克魔法书 Wiki，`https://wegame.shallow.ink/api/v1/games/rocom/wiki/`

本站为非官方游戏资料工具。接口只读，无需调用方提供 API Key；上游匿名令牌仅在服务端使用，不会返回给调用方。仅支持 GET、HEAD、OPTIONS，允许跨域访问，不支持任意上游 URL、JSONP 或账号操作。

## 快速开始

```bash
# 按名称搜索精灵
curl --get 'https://091p.com/lkwg/wiki-api.php' \
  --data-urlencode 'resource=pets' \
  --data-urlencode 'q=喵喵' \
  --data-urlencode 'page_size=5'

# 单独获取种族值和生态资料，不必加载整个精灵档案
curl 'https://091p.com/lkwg/wiki-api.php?resource=pet-profile&pet_id=3001'

# 技能详情
curl 'https://091p.com/lkwg/wiki-api.php?resource=skill-detail&skill_id=7020600'

# 道具详情：外观物品使用 item_kind=visual
curl 'https://091p.com/lkwg/wiki-api.php?resource=item-detail&item_kind=bag&item_id=100403'
```

```javascript
const params = new URLSearchParams({ resource: 'pet-family', pet_id: '3001' });
const response = await fetch(`https://091p.com/lkwg/wiki-api.php?${params}`);
const result = await response.json();
if (!response.ok || !result.ok) throw new Error(result.error || `HTTP ${response.status}`);
if (result.warning) console.warn(result.warning, result.updated_at);
console.log(result.data);
```

```python
import json
from urllib.parse import urlencode
from urllib.request import urlopen

params = urlencode({"resource": "pets", "q": "喵喵", "page_size": 5})
with urlopen("https://091p.com/lkwg/wiki-api.php?" + params, timeout=60) as response:
    result = json.load(response)
if not result["ok"]:
    raise RuntimeError(result["error"])
for pet in result["items"]:
    print(pet["pet_id"], pet["name"])
```

## 配对孵蛋页面的数据来源

[配对孵蛋](https://091p.com/lkwg/breeding.html) 不调用新的上游接口。Wiki 目录没有独立的“配对”端点；页面组合已有只读资源：`pets&q=名称` 搜索精灵及蛋组，`pets&egg_group_id=蛋组ID` 列出同组伙伴，`pet-egg&pet_id=精灵ID` 查询性别比、蛋尺寸、孵化时间和 `probabilities.home.glass` 家园来源炫彩配置，`pet-appearance&pet_id=精灵ID` 恢复分享链接。

页面据蛋组交集判定物种是否可能配对，并排除只有母性却放在父方、只有公性却放在母方的情况。本站没有玩家精灵的个体性别及家园状态：即使显示“蛋组匹配”，仍须在游戏内确认一公一母、精灵小窝相邻等条件。蛋资料按所选母方的孵蛋配置展示，不能把随机蛋池概率当作家园产蛋概率。

## 完整功能页面（2026-10-23）

- [全部独立功能页](https://091p.com/lkwg/catalogs.html)：115 个可用页面，对应本次从上游目录、官方前端和发布方客户端确认的 101 条公开 GET 路由。
- [上游 API 与页面逐项对照](UPSTREAM-APIS.md)：包含来源证据、查询参数、36 项未接入接口的边界和独立说明页。
- 每个资源的机器文档均返回 `page`、`upstream_url`、`pagination`、`id_param`、`parameters`，页面和接口白名单均由 `wiki-resources.php` 维护。运行 `python3 tools/build-pages.py` 重新生成页面，`--check` 检查同步状态。
- 13 个道具细分视图共用 `/items`，`pet-detail` 是本站聚合表现，因此逻辑资源数不等于上游路由数。
- 新增精灵生态、性格、故事，技能可学习精灵，果实刷新，完整道具/装扮/邮件/剧情详情，蛋组查询，公告，公开阵容和公开收集榜单。
- `options`、`activities` 与额外游戏接口返回 `raw`（完整上游 `data`）；游戏公告分页使用 `page` / `limit`，不要套用 Wiki 的 `page_no` / `page_size`。必填查询缺失返回 400。
- `pet-size` 接受 `diameter`（米）、`weight`（千克）、`pool`（`magic` / `normal` / `same_ride` / `nightmare`）、`random_egg_id`、`ride_talent=1`、`include_display_only=true|false`。只展示上游随机蛋池匹配，不能当作家园配对概率。
- `profile-asset-detail` 需 `asset_type=avatar|card_skin|label` 与 `asset_id`；`photo-action-detail` 需 `action_type=pose|emoji|filter` 与 `action_id`。这些类型参与缓存键。
- `announcement-detail` 使用 `thread_id` 字符串，不套用 Wiki 数字 ID 的九位限制。`share-code-records` 只查询已收录公开记录，`share_code` 在本站最多 4096 字节，其他常规文本参数仍最多 240 字节。
- `pet-collection-rankings` 仅访问公开存量榜单，固定 `resolve_names=0`，不透传 `uid`、不触发姓名补全或付费实时查询。页面不会调用分享码解析、账号绑定或其他写入接口。

## 详情接口

目前有 48 个独立详情/关联查询资源返回 `data`，外加保留的 `pet-appearance` 与聚合 `pet-detail`。全部为明确列入白名单的路径，不开放任意路径代理。

### 精灵资料分区（13 个）

均需 `pet_id`，例如 `3001`。通用别名 `id` 也可用。

| resource | 内容 |
| --- | --- |
| `pet-profile` | 种族值、体型、属性克制、性别比、移动方式 |
| `pet-family` | 进化链、进化条件 |
| `pet-skills` | 升级、血脉、技能石技能 |
| `pet-acquisition` | 获取方式 |
| `pet-egg` | 孵蛋配置、尺寸、变异概率 |
| `pet-talents` | 特长池及概率 |
| `pet-features` | 特性 |
| `pet-ride` | 骑乘与同乘 |
| `pet-fruit` | 吸引果实 |
| `pet-handbook` | 图鉴课题 |
| `pet-ecology` | 生态与角色互动 |
| `pet-natures` | 性格效果与属性修正 |
| `pet-stories` | 背景故事 |

已存在的 `pet-detail&pet_id=3001` 仍返回 `sections`，保留基础资料及原有 10 个分区的聚合结构；新增的生态、性格和故事可单独查询，不增加旧聚合调用的负担。`pet-appearance&pet_id=3001` 仍返回 `pet`。分区接口会复用较新的完整档案缓存，避免重复请求上游。

### 其他图鉴详情

下表是原有 13 项，其余新接入详情见 [完整 API 对照](UPSTREAM-APIS.md)。

| resource | ID 参数 | 示例值 |
| --- | --- | --- |
| `skill-detail` | `skill_id` | `7020600` |
| `item-detail` | `item_id` | `100403` |
| `random-egg-detail` | `random_egg_id` | `1` |
| `pet-egg-detail` | `egg_conf_id` | `3001001` |
| `task-detail` | `task_id` | `102001` |
| `region-detail` | `region_id` | `1` |
| `dungeon-detail` | `dungeon_id` | `120108` |
| `shop-detail` | `shop_id` | `1001` |
| `furniture-detail` | `furniture_id` | `1000013` |
| `exchange-detail` | `exchange_id` | `1001011` |
| `medal-detail` | `medal_id` | `1003` |
| `skill-stone-detail` | `item_id` | `231001` |
| `fashion-detail` | `suit_id` | `59` |

`item-detail` 额外接受 `item_kind=bag|visual`，默认 `bag`。背包物品和外观物品的 ID 空间不同，缓存也按类型分开。`pet-egg` 按精灵 ID 查孵蛋资料，`pet-egg-detail` 按蛋配置 ID 查某种蛋配置，二者不要混用。

详情 ID 必须是 1 到 999999999 的十进制正整数，不接受前导零、小数、路径或数组。原生参数和 `id` 同时提供时必须相同，否则返回 400。实际 ID 请从对应列表响应中获取，不要连续枚举探测。

## 列表与配置接口

原有 78 个资源全部保留，本次扩展后目录共 115 项。完整参数与独立页面映射由 `wiki-resources.php` 统一生成，避免页面文档和请求白名单不一致。

- 精灵与战斗：`pets`、`skills`、`skill-stones`、`skill-stone-recipes`、`pet-carryons`、`pet-levels`。
- 孵蛋与养育：`pet-eggs`、`random-eggs`、`egg-items`、`pet-fruits`、`pet-foods`、`pet-gifts`。
- 家园：`home-progression`、`home-egg-lay-rates`、`furniture`、`plants`、`recipes`、`fruit-trees`。
- 世界与冒险：`regions`、`dungeons`、`balls`、`medals`。
- 任务与剧情：`tasks`、`task-summaries`。
- 商店与兑换：`shops`、`exchanges`、`mails`。
- 装扮：`fashion`、`fashion-items`、`fashion-beauty`、`fashion-bonds`、`fashion-wands`、`fashion-bag-charms`、`music`、`chat-emojis`、`photo-actions`。
- 道具：`items`、`avatars`、`card-skins`、`titles`、`actions`、`glass-pieces`、`bloodline-items`、`pet-growth-materials`、`boss-tokens`、`pet-medals`、`pet-memories`、`task-items`、`food-materials`、`plant-seeds`、`profile-assets`、`handbook-areas`。
- 分类目录：`catalogs`。省略 resource 时返回此资源。

通用参数：

- `q`：资源支持的名称 / 描述关键词；并非所有资源都支持搜索。
- `page_no`：默认 1，限制在 1–1000。
- `page_size`：默认 24，限制在 1–100。
- 支持整数形式的分页参数，超出范围时限制到边界；非法字符串或数组返回 400。
- 筛选参数必须是合法 UTF-8 字符串，每个参数最多 240 字节；空值不透传。
- 只透传目录中的白名单筛选，未声明的参数忽略。
- `catalogs`、`home-progression`、`handbook-areas` 不提供分页控件；上游按配置整体返回。
- 头像等道具细分资源自带固定筛选，不接受调用方覆盖。

例如草系精灵：`wiki-api.php?resource=pets&type_id=3&page_size=10`。某属性 ID 的实际含义以资料源为准。

## 响应与兼容性

```json
{
  "ok": true,
  "resource": "skill-detail",
  "source": "https://wegame.shallow.ink/api/v1/games/rocom/wiki/skills/7020600",
  "updated_at": "2026-09-24T12:00:00+08:00",
  "skill_id": 7020600,
  "data": { "skill_id": 7020600, "name": "蓄能轰击" }
}
```

这是精简结构示例，时间为示意值。实际 `data` 保留上游详情的完整字段，不把详情中的 `items` 数组误当作分页列表。

| 资源类型 | 数据字段 |
| --- | --- |
| 图鉴列表 | `items`、`catalog`、`total`、`total_pages`、`has_more`、`page_no`、`page_size` |
| 新增详情 | `data`，同时回显对应 ID；道具详情额外回显 `item_kind` |
| 精灵完整档案 | `sections` |
| 精灵基础与外观 | `pet` |
| 家园成长等配置 | `raw`（兼容保留空 `items`） |

上游缺少的字段可能不存在或为 `null`，调用方应容错处理。`updated_at` 是资料获取时间，命中缓存时不重置。`source` 不包含匿名令牌。

失败响应：

```json
{"ok": false, "error": "未找到对应资料，请检查资源类型和 ID"}
```

- 200：成功，可能附带 `stale`、`warning`。
- 204：OPTIONS 成功，无响应体。
- 400：资源、参数类型、ID 或筛选值无效。
- 404：上游明确表示资料不存在。
- 405：方法不支持，`Allow` 为 `GET, HEAD, OPTIONS`。
- 429：上游限流且无法回退缓存，附带 `Retry-After: 60`。
- 502：上游连接、鉴权或响应异常，且没有可用缓存。

错误响应不缓存，不向外暴露令牌、文件路径或上游调试内容。原有精灵聚合接口某个非基础分区失败时返回部分资料和 warning。

## 缓存与调用建议

- 默认列表缓存 180 秒。
- 经验表、家园配置、目录及详情缓存 86400 秒。
- 精灵聚合详情包含 warning 时仅短暂复用，180 秒后重试缺失资料。
- 普通列表上游失败时可使用 1 天内的缓存；新增详情可使用 7 天内的缓存。上游明确 404 时新增详情不回退旧缓存。
- 原有精灵聚合 / 外观接口保留既有旧缓存回退策略；详情应注意 `updated_at`。
- 返回旧缓存时带 `stale: true` 和 warning。
- HTTP 缓存 120 秒；响应大小限制 8 MiB，单次上游超时 15 秒，临时错误有限重试。
- 请复用缓存、串行或低并发调用，不要全站高频抓取。该服务无可用性保证。

## 图片与文本兼容

- 保留原有 `icon`、`small_icon`、`big_icon` 等字段；有有效图片来源的对象额外返回 `image_sources`（最多 3 个实际来源）和 `image_url`（本站缓存图片地址）。调用方建议优先使用 `image_url`。
- `image.php?url=...&fallback[0]=...` 只接受本站使用的图片域名和资源路径：Wiki 的 `/api/v1/resources/wiki/assets/`、B 站 Wiki 的 `/images/rocom/`、`img.71acg.net`、`res.3839pic.com`。不支持任意地址代理、内网地址、SVG、账号或自定义请求头。
- 图片响应按真实内容校验；PNG、JPEG、WebP、GIF（及运行环境支持的 AVIF）统一输出 PNG，动图取静态首帧。HTML 错误页、损坏图片和超过 8 MiB / 1600 万像素的源图不缓存。最多跟随 2 次仍在白名单中的重定向。
- 成功图片缓存 7 天，上游失败时可回退 30 天内的有效图片，并通过 `X-Image-Cache: stale`、`Warning` 和短 HTTP 缓存标记。429 不立即重试同一源图；失败源图冷却 60 秒，404 冷却 300 秒，期间仍可使用备用图。
- 上游没有提供图片时不猜测图片路径，也不拿无关素材冒充；页面显示“暂无图片”。全部来源失败时图片代理返回不缓存的 JSON 错误，前端使用明确占位图。精灵图片接口保留 PNG 提示图的既有行为。
- JSON 和 HTML 请求自动解压，按解压后体积限流；兼容 UTF-8 BOM、GBK/GB18030、明确声明的 Big5 和带 BOM 的 UTF-16/UTF-32。合法 UTF-8 优先保留，避免错误声明导致二次乱码。
- 展示文本清理 HTML 实体、重复 Unicode 转义、游戏富文本标签及控制字符；仅修复可无损逆转的中文误解码，不推测已经丢失的文字。查询参数、标识符、令牌和数值不做文本替换。
- 两个商人接口共用 UTF-8 DOM 解析及源页面缓存，支持引号转义、懒加载商品图。商品价格无法解析或页面无有效货物时不覆盖好缓存；回退响应包含 warning，页面保留可见提示。生成货单图片最多缓存 180 秒，避免一次缺图固化为长期货单。

## 维护与测试

核心文件：

- `wiki-resources.php`：资源白名单和机器可读参数文档。
- `wiki-api.php`：参数验证、上游匿名访问、响应与缓存。
- `upstream.php`：HTTP 解压、字符编码和图片字段兼容。
- `image-cache.php` / `image.php`：受限图片获取、格式校验与缓存回退。
- `merchant-source.php`：商人页面解析和共用源缓存。
- `api.html` / `api.css` / `api.js`：接口目录、链接生成和按需在线调试。

```bash
php -l lkwg/wiki-api.php
php -l lkwg/wiki-resources.php
node --check lkwg/api.js
python3 lkwg/tests/wiki_api_test.py
python3 lkwg/tests/image_api_test.py
php lkwg/tests/upstream_test.php
```

回归测试在临时目录复制接口，并启动本机模拟上游与临时 PHP 服务。不访问真实 Wiki，不修改生产缓存，不需要额外 Python 包。前端 DOM 测试使用 jsdom（不是浏览器视觉测试），可将依赖安装在临时目录，不影响站点：

```bash
TEST_DEPS=$(mktemp -d)
npm install --prefix "$TEST_DEPS" --registry https://registry.npmjs.org \
  --no-audit --no-fund --ignore-scripts jsdom@26.1.0
NODE_PATH="$TEST_DEPS/node_modules" node --test lkwg/tests/*_test.cjs
```
