快速开始

按道具 ID 或名称查询道具信息与展示图片。只读、免鉴权、支持跨域,直接 GET 就能用。

1. 搜一个道具,拿到它的 itemid

curl '/search?q=星梦茶会&limit=3'

2. 响应里每条都带图片地址image 可以直接放进 <img src>

{
  "query": "星梦茶会",
  "total": 6,
  "count": 3,
  "items": [
    {
      "itemid": 158961,
      "name": "星梦茶会套装",
      "category": "avatar",       "category_name": "装扮",
      "subcategory": "asm_base",  "subcategory_name": "套装",
      "image": "/img/158961.png",
      "images": ["/img/158961.png"]
    }
  ]
}

3. 已知 ID 就直接取

curl '/items/158961'

三步就够了。剩下的接口都是围绕这两件事展开的:怎么找到道具怎么按分类浏览

中文关键词少于 3 个字会慢一些。全文索引按 3 字符切分,「天使」「幻影」这类 两字词走不了索引,响应约 40 ms(三字以上约 1 ms)。功能完全正常,只是别用它做 输入即搜的联想。

几个概念

道具分两层分类

粗分类 category 只有 6 个,对应游戏商城的 Tab;细分类 subcategory 有 200 多个,来自客户端自己的分类表,不是自己编的。

code名称典型细分类
kart赛车car_new_a A级赛车、cr_tail 尾挂
avatar装扮asm_base 套装、rr_hair 发饰
function功能各类卡片、道具
pet宠物宠物、宠物装扮
gem宝石dmd_speedskill 圆形竞速宝珠
other其他角色、系统保留

完整的两层对照表随时可查:GET /categories

车系是另一条线

seriessubcategory 正交 —— 一个车头既属于「车头」也属于 「雷诺配件」。两个一起传是 AND。

图片

image 是首选的一张,images 是全部(主图、_b/_c 变体、动画帧)。约一半道具有图,没有的 imagenullimages[]。图片由 Nginx 直出,可放心并发拉。

万能查询

GET/lookup?q=

一个入口吃三种输入:道具 ID图片名道具名。 不用先判断手上这串东西是什么,直接丢进来。

curl '/lookup?q=171055'        # 道具 ID
curl '/lookup?q=171055.png'    # 图片名
curl '/lookup?q=20133_b.png'   # 图片变体,会还原到道具 20133
curl '/lookup?q=甜酷CP-麒麟'     # 道具名

返回体固定这个形状,items 里每条的结构和其他接口完全一样

{
  "query": "20133_b.png",
  "matched_by": "image",
  "total": 1,
  "items": [ { "itemid": 20133, "name": "双髻鲨", "image": "…/20133.png", … } ]
}
参数默认说明
q必填道具 ID、图片名(带不带 .png 都行)或道具名
limit20最多返回几条,1–200。total 是命中总数,不受它影响

matched_by 告诉你它是按什么命中的,便于判断结果可不可信:

含义
itemid按道具 ID 命中
image按图片名命中(输入带 .png 或带 _b 这类变体后缀)
name_exact名字完全相同
name_fuzzy名字包含关键词,按相关度排序
none没查到。仍然是 200total 为 0、items[]

为什么图片名能当 ID 用:全库 68,358 张图的文件名前导数字恒等于它所属的 itemid(实测 0 例外)。所以 171055171055.png20133_b 走的是同一条路径。

这个接口的覆盖范围比其他接口大。/items/{id} 只有有图的 67,374 条,而这里覆盖全部 135,689 条,外加 154 张没有道具记录的图片。 查不到图或查不到道具时,对应字段是 null / [],结构不变:

  • 有道具无图 → imagenullimages[]、分类等字段为 null
  • 有图无道具(孤儿图)→ name空字符串,图片字段正常

名字有一半不唯一。73,231 个不重复名字里有 33,661 个对应多条道具 (子件 1,737 条、赛车卡 529 条、作废id 344 条…)。 所以 别默认取 items[0] 就完事 —— 先看 total

GET/search

只按名称搜索,中文子串匹配,按相关度排序。

参数默认说明
q必填关键词。空格分隔多个词表示都要出现(q=天使 套装
limit20每页条数,最大 100
offset0跳过多少条,用于翻页
category不限粗分类,逗号分隔可多传
subcategory不限细分类,逗号分隔可多传
sortrelevance还可以是 id(ID 升序)、newest(ID 倒序)
facetstrue返回各分类命中数,前端拿去做 Tab。不需要就传 false,响应小很多也更快
fieldnameall 连描述一起搜 —— 会捞进一堆名字不相关的,慎用
/search?q=雷诺&category=kart            雷诺相关的赛车
/search?q=天使&subcategory=car_new_a    只要 A级赛车
/search?q=天使&limit=5&facets=false     只要结果,不要分类统计

响应在 items 之外还有 total(总命中)、 categories / subcategories(各分类命中数,facets=true 时)。

查单个

GET/items/{itemid}

查不到返回 404。加 ?full=true 额外返回 restypeitemselltypemodify_timeraw(客户端原始记录, 字段很多,一般用不上)。

curl '/items/158961'
curl '/items/158961?full=true'

批量查

GET/batch?ids=

逗号分隔,一次最多 200 个。返回顺序与传入顺序一致,查不到的不占位、 单独列在 missing 里。

curl '/batch?ids=158961,10008,12720'

{"requested":3, "found":2, "missing":[12720], "items":[…]}

展示一批道具时用这个,别循环调单个接口。

分页列表

GET/items

不带关键词地按条件翻页。

参数默认说明
page1页码,从 1 开始
size50每页条数,最大 100
category subcategory series不限逗号分隔可多传
itemtype garagetype sextype不限客户端原始枚举值,见 /enums
has_image不限只要有图 / 无图的
/items?subcategory=car_new_s&size=50          所有 S级赛车
/items?subcategory=car_new_a,car_new_b        A车 + B车
/items?series=other_refititem_renault         雷诺车系全部配件
/items?category=avatar&page=2&size=100        装扮第 2 页

响应带 totalpages,直接拿去渲染分页器。

分类表

GET/categories

两层分类树,每层带道具数量。做分类导航就靠它,别把 code 写死在前端。

{"categories":[
  {"code":"kart","name":"赛车","count":3493,
   "subcategories":[
     {"code":"car_new_a","name":"A级赛车","itemtype":1539,"count":729},
     {"code":"car_new_s","name":"S级赛车","itemtype":1543,"count":177}
   ]}
]}

?empty=true 连一条道具都没有的分类也列出来; 加 ?has_image=true 只统计有图的。

车系表

GET/series

车系配件对照表,配合 /items?series= 用。

枚举表

GET/enums

客户端原始常量的数值 → 名称映射(itemtypegaragetypesextype 等)。一般用不上 —— 响应里已经带了 *_name 字段。

数据统计

GET/stats

道具/图片总数、各分类数量、最常见的 itemtype。另有 GET /healthz 供监控探活,返回 {"ok":true,"items":67369}

ID 名称对照表

全部 135,689 个道具的 itemid + 名字,静态文件直接下载, 不用调接口。适合在本地做 ID 反查、批量校对、离线搜名字。

文件大小格式
/download/qqspeed-items-idname.csv5.8 MBUTF-8 带 BOM,Excel 直接打开不乱码
/download/qqspeed-items-idname.jsonl11 MB每行一个 JSON 对象
curl -O '/download/qqspeed-items-idname.csv'

CSV 三列,JSONL 三个字段:

itemid,name,sources
10008,"腾彩气球",ItemList|Client1

{"itemid":10008,"name":"腾彩气球","sources":["ItemList","Client1"]}
字段说明
itemid道具 ID,唯一,可直接用于 /items/{itemid}
name道具名。有 401 条是空字符串 —— 客户端里本来就没给名字
sources该 ID 出现在哪几个客户端道具表文件里,排查用,一般可忽略

这份表是全量 135,689 条,比接口的默认数据集大一倍 —— 接口只收录有展示图的 67,374 条,其余 68,315 条多为无展示图的功能性道具, 用 /items/{itemid} 查会返回 404表里有的 ID 不等于接口查得到。 只要有图的那部分,筛 sources 没用,得改用 /items?has_image=true 翻页。

游戏更新后这份文件才会变,不是实时的。缓存 1 小时。

响应字段

所有返回道具的接口,单条道具的结构都一样:

字段类型说明
itemidint道具 ID,唯一
namestring道具名
descriptionstring|null描述
usagedescstring|null用途说明
category / category_namestring|null粗分类 code 与中文名
subcategory / subcategory_namestring|null细分类 code 与中文名
series / series_namestring|null车系 code 与中文名
itemtype / itemtype_nameint|null客户端原始类型
garagetype / sextypeint|null商城分栏 / 性别限制(0 通用 1 男 2 女)
create_timestring|null客户端记录的创建时间
has_imagebool有没有展示图
image_countint图片张数
imagestring|null首选图片完整地址
imagesstring[]全部图片地址,无图时是 []

可能为 null 的字段一定存在,不会整个消失。解析时按「值可能是 null」 处理即可,不用判断字段存不存在。

错误码

状态码什么时候响应体
400分类 code 不认识、ids 为空或超过 200 个{"detail":"未知分类 nope,可选值见 /categories"}
404道具不存在{"detail":"道具不存在: 999999999"}
422参数类型/范围不对,如 limit=500{"detail":[{"loc":["query","limit"],"msg":"…"}]}
429超过限流(单 IP 20 次/秒,突发 40)Nginx 默认页

400 / 404 的 detail 是字符串,422 的是数组。两种都要能处理 —— 最省事的写法是只看状态码,需要展示原因时再判断 detail 的类型。

标识你的应用

可选。带上它,你的调用就能被单独统计出来,而不是跟别人混在一起按 IP 猜。

每次请求加一个请求头,值自己起,8~64 个字符,只能用字母、数字和 - _ . :

curl -H 'X-Client-Id: myapp-prod-01' '/search?q=天使'

不方便加请求头(比如直接在浏览器地址栏、或者小程序里拼 URL)就用查询参数,效果一样:

/search?q=天使&client_id=myapp-prod-01

不带也能正常用,接口行为、返回内容、限流都完全不受影响 —— 这个值只进统计, 不参与鉴权,也不做配额。

为什么建议带上

不带的话只能靠 IP + User-Agent 认人:你的服务换台机器、或者用户从 WiFi 切到 4G, 就会被当成新的调用方;反过来,同一个出口 IP 后面的一堆人会被算成一个。 带上之后这些都不会错。

值要固定,别每次启动随机生成 —— 那跟不带没区别。多环境建议区分开, 例如 myapp-prod / myapp-test,出问题时好定位是哪一边打的。 里面别放用户 ID、手机号之类的个人信息,一个应用一个值就够了。