关键词 API
关键词接口返回附加在电影或电视剧上的情节标签,每个是一个 ID 加名称。你可以查询单个关键词、列出带有它的电影,或把 ID 传给 discover 的 with_keywords 构建主题页。电影的响应在 keywords 下,电视剧的在 results 下。
获取电影的关键词
GET / 返回一部电影的情节标签。关键词是一个简短的短语,例如主题、场景或原著类型,它带有一个数字 ID,可以在发现中复用。
示例加载一部电影的关键词,然后向 discover 请求与它的第一个关键词相同的最热门电影。
curl -s "https://api.amodb.dev/3/movie/550/keywords" \
-H "Authorization: Bearer $AMODB_KEY"
curl -s "https://api.amodb.dev/3/discover/movie?with_keywords=818&sort_by=popularity.desc" \
-H "Authorization: Bearer $AMODB_KEY"const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };
const kw = await fetch(`${base}/movie/550/keywords`, { headers });
if (!kw.ok) throw new Error(`keywords failed with ${kw.status}`);
const { keywords } = await kw.json();
console.log(keywords.map((k) => `${k.id}:${k.name}`).join(', '));
if (keywords.length > 0) {
const first = keywords[0];
const found = await fetch(`${base}/discover/movie?with_keywords=${first.id}&sort_by=popularity.desc`, { headers });
if (!found.ok) throw new Error(`discover failed with ${found.status}`);
const page = await found.json();
console.log(first.name, page.results.slice(0, 5).map((m) => m.title));
}import os
import requests
base = "https://api.amodb.dev/3"
headers = {"Authorization": f"Bearer {os.environ['AMODB_KEY']}"}
r = requests.get(f"{base}/movie/550/keywords", headers=headers, timeout=10)
r.raise_for_status()
keywords = r.json()["keywords"]
print(", ".join(f"{k['id']}:{k['name']}" for k in keywords))
if keywords:
first = keywords[0]
d = requests.get(
f"{base}/discover/movie",
params={"with_keywords": first["id"], "sort_by": "popularity.desc"},
headers=headers,
timeout=10,
)
d.raise_for_status()
print(first["name"], [m["title"] for m in d.json()["results"][:5]])<?php
function amodb_get(string $url): array {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("amodb returned $status");
}
return json_decode($body, true);
}
$base = 'https://api.amodb.dev/3';
$keywords = amodb_get("$base/movie/550/keywords")['keywords'];
if ($keywords) {
$first = $keywords[0];
$found = amodb_get("$base/discover/movie?with_keywords={$first['id']}&sort_by=popularity.desc");
$titles = array_column(array_slice($found['results'], 0, 5), 'title');
echo $first['name'], ': ', implode(', ', $titles), PHP_EOL;
}package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
var client = &http.Client{Timeout: 10 * time.Second}
func get(path string, out any) error {
req, _ := http.NewRequest("GET", "https://api.amodb.dev/3"+path, nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return fmt.Errorf("amodb returned %s", res.Status)
}
return json.NewDecoder(res.Body).Decode(out)
}
type Keywords struct {
Keywords []struct {
ID int `json:"id"`
Name string `json:"name"`
} `json:"keywords"`
}
type Page struct {
Results []struct {
Title string `json:"title"`
} `json:"results"`
}
func main() {
var kw Keywords
if err := get("/movie/550/keywords", &kw); err != nil {
panic(err)
}
if len(kw.Keywords) == 0 {
return
}
first := kw.Keywords[0]
var page Page
if err := get(fmt.Sprintf("/discover/movie?with_keywords=%d&sort_by=popularity.desc", first.ID), &page); err != nil {
panic(err)
}
fmt.Println(first.Name)
for i, m := range page.Results {
if i == 5 {
break
}
fmt.Println(" ", m.Title)
}
}参数
movie_id路径必填数字形式的电影 ID,例如550。api_key查询二选一你的密钥。使用它,或使用Authorization: Bearer请求头。
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 电影 ID。 |
keywords | array | 带有 id 和 name 的对象。电影没有关键词时为空。 |
keywords[].id | integer | 关键词 ID。用于 with_keywords 和下面的关键词路径。 |
keywords[].name | string | 关键词文本。 |
示例响应
{
"id": 550,
"keywords": [
{ "id": 818, "name": "based on novel or book" },
{ "id": 825, "name": "support group" },
{ "id": 851, "name": "dual identity" }
]
}真实响应包含 14 个关键词,这里只保留前 3 个。关键词名称不做翻译,所以 language 在这里没有作用。
电视剧的关键词
GET / 使用同一个密钥,返回同样的对象,但数组名为 results。路径中的 ID 是剧集 ID,例如 1396。
{
"id": 1396,
"results": [
{ "id": 1508, "name": "new mexico" },
{ "id": 2231, "name": "drug dealer" }
]
}真实响应包含 29 项,这里只保留前 2 项。同时服务两种媒体类型的客户端可以读取 data.keywords ?,并用同样的方式处理两者。
关键词记录及其电影
| 方法和路径 | 返回内容 | 参数 |
|---|---|---|
GET / | { id, name } | 无 |
GET / | 带有 id、page、results、total_pages、total_results 的电影分页列表 | language、page |
两个路径都使用关键词数组中的数字 ID。电影列表的条目结构与其他电影列表相同,包括 genre_ids 和 poster_path,顶层还有关键词 id。include_adult 会被接受但被忽略。超出 total_pages 的页码返回空的 results 数组。没有按关键词列出剧集的接口,所以电视剧请使用 /。
与 discover 组合关键词
除了简单列表之外的需求,请在发现中筛选。它可以排序、分页,并把关键词与其他筛选条件组合,而且既支持电影也支持电视剧。
| 目标 | 查询字符串 |
|---|---|
| 带有一个关键词的电影 | / |
| 同时带有两个关键词的电影 | / |
| 不带某个关键词的电影 | / |
| 带有某个关键词的剧集 | / |
| 带有两个关键词之一的剧集 | / |
| 某个类型内的一个关键词 | / |
ID 之间的逗号表示全部满足。在 ID 之间写竖线,如 with_keywords=818|4565,则匹配其中任意一个。discover 结果在边缘缓存 30 分钟。
查找关键词 ID
要把文本变成 ID,请调用 GET /。它返回由 id 和 name 组成的分页列表,每页 20 条。所有搜索路径见搜索。如果关键词搜索没有任何匹配,目前会返回 500 和 status_code 11,而不是空列表。搜索结果缓存 10 分钟,但每次调用仍计入你的每分钟请求数,所以请为输入联想框做防抖。
错误
| HTTP | status_code | 何时出现 |
|---|---|---|
| 401 | 7 | 密钥缺失或错误。 |
| 402 | 36 | 套餐周期已结束。 |
| 404 | 34 | /keyword/{keyword_id} 及其电影列表中没有该 ID 的关键词。 |
| 405 | 37 | 你对关键词路径使用了写入方法。 |
| 429 | 25 | 你超过了每分钟请求数。请等待 Retry-After 秒。 |
| 500 | 11 | 没有任何匹配的 /search/keyword 查询。 |
关键词路径上未知的电影或剧集 ID 不会返回 404。你会得到 HTTP 200,带有该 ID 和一个空数组。
实用说明
- 请保存关键词
id,而不是名称。名称可能被改写,ID 不会变。 - 关键词列表与该作品的详情一起缓存 6 小时。对标签页来说,每周刷新一次就足够了。
- 单个作品的标签列表很短。做主题页时,请从关键词 ID 出发,在 discover 中列出它的作品,而不是反过来。
- 用
without_keywords去除噪声,例如你永远不想出现在家庭页面上的标签。 - 对冷门作品,空数组是有效的答案。请隐藏标签行,而不是显示错误。