API מילות מפתח

נקודות הקצה של מילות מפתח מחזירות את תגיות העלילה שמצורפות לסרט או לסדרה, כל אחת כמזהה ושם. אפשר לחפש מילת מפתח אחת, להציג את הסרטים שנושאים אותה, או להעביר את המזהים ל-discover עם with_keywords כדי לבנות עמודי נושא. סרטים עונים תחת keywords, וסדרות עונות תחת results.

עודכן צפייה כ-Markdown

קבלת מילות המפתח של סרט

GET /3/movie/{movie_id}/keywords מחזיר את תגיות העלילה של סרט אחד. מילת מפתח היא ביטוי קצר כמו נושא, התרחשות או סוג מקור, ויש לה מזהה מספרי שאפשר להשתמש בו שוב בעמוד גילוי.

הדוגמה טוענת את מילות המפתח של סרט ואז מבקשת מ-discover את הסרטים הפופולריים ביותר שחולקים את מילת המפתח הראשונה שלו.

bashjspyphpgo
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נתיבחובה
    מזהה סרט מספרי, למשל 550.
  • api_keyשאילתהאחד משניים
    המפתח שלכם. השתמשו בו או בכותרת Authorization: Bearer.

שדות התגובה

שדהסוגהערות
idintegerמזהה הסרט.
keywordsarrayאובייקטים עם id ו-name. ריק כשלסרט אין מילות מפתח.
keywords[].idintegerמזהה מילת המפתח. השתמשו בו ב-with_keywords ובנתיבי מילות המפתח שלמטה.
keywords[].namestringהטקסט של מילת המפתח.

תגובה לדוגמה

JSON
{
  "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 /3/tv/{series_id}/keywords מקבל את אותו מפתח ומחזיר את אותם אובייקטים, אבל שם המערך הוא results. המזהה בנתיב הוא מזהה הסדרה, למשל 1396.

JSON
{
  "id": 1396,
  "results": [
    { "id": 1508, "name": "new mexico" },
    { "id": 2231, "name": "drug dealer" }
  ]
}

בתגובה האמיתית יש 29 פריטים, וכאן היא קוצרה ל-2 הראשונים. לקוח שמשרת את שני סוגי המדיה יכול לקרוא data.keywords ?? data.results ולהתייחס לשניהם באותה צורה.

רשומות מילות מפתח והסרטים שלהן

שיטה ונתיבמה מוחזרפרמטרים
GET /keyword/{keyword_id}{ id, name }אין
GET /keyword/{keyword_id}/moviesרשימה מדורגת של סרטים עם id, page, results, total_pages, total_resultslanguage, page

שני הנתיבים משתמשים במזהה המספרי ממערך מילות מפתח. רשימת הסרטים נותנת את אותו מבנה פריט כמו רשימות סרטים אחרות, כולל genre_ids ו-poster_path, בתוספת ה-id של מילת המפתח בראש. include_adult מתקבל ומתעלמים ממנו. עמוד אחרי total_pages מחזיר מערך results ריק. אין רשימת סדרות למילת מפתח, ולכן לסדרות השתמשו ב-/discover/tv?with_keywords=.

שילוב מילות מפתח עם discover

לכל דבר מעבר לרשימה פשוטה, סננו בעמוד גילוי. הוא ממיין, מדפדף ומשלב מילות מפתח עם מסננים אחרים, והוא מכסה סדרות וגם סרטים.

מטרהמחרוזת שאילתה
סרטים עם מילת מפתח אחת/discover/movie?with_keywords=818
סרטים עם שתי מילות מפתח יחד/discover/movie?with_keywords=818,4565
סרטים בלי מילת מפתח/discover/movie?without_keywords=818
סדרות עם מילת מפתח/discover/tv?with_keywords=9712
סדרות עם אחת משתי מילות מפתח/discover/tv?with_keywords=818%7C9712
מילת מפתח אחת בתוך ז'אנר/discover/movie?with_keywords=818&with_genres=18

פסיק בין מזהים פירושו את כולם. כתבו קו אנכי בין מזהים, כמו ב-with_keywords=818|4565, כדי להתאים לכל אחד מהם. תוצאות discover נשמרות בקצה במטמון 30 דקות.

מציאת מזהה מילת מפתח

כדי להפוך טקסט למזהה, קראו ל-GET /3/search/keyword?query=heist. הוא מחזיר רשימה מדורגת של זוגות id ו-name, 20 בעמוד. את כל נתיבי החיפוש ראו בעמוד חיפוש. חיפוש מילת מפתח שלא מתאים לשום דבר עונה כרגע 500 עם status_code 11 במקום רשימה ריקה. תשובות חיפוש נשמרות במטמון 10 דקות, אבל כל קריאה עדיין נספרת בבקשות שלכם לדקה, ולכן השהו את הקלט בתיבת הקלדה.

שגיאות

HTTPstatus_codeמתי
4017המפתח חסר או שגוי.
40236תקופת המסלול הסתיימה.
40434אין מילת מפתח עם המזהה הזה ב-/keyword/{keyword_id} וברשימת הסרטים שלה.
40537השתמשתם בשיטת כתיבה בנתיב של מילת מפתח.
42925חרגתם מהבקשות שלכם לדקה. המתינו Retry-After שניות.
50011שאילתת /search/keyword שלא מתאימה לשום דבר.

מזהה סרט או סדרה לא מוכר בנתיבי מילות המפתח אינו 404. מקבלים HTTP 200 עם המזהה ומערך ריק.

את כל הקודים ראו בעמוד שגיאות, ואת מגבלות המסלולים בעמוד מגבלות קצב.

הערות מעשיות

  • שמרו את ה-id של מילת המפתח, לא את השם. שם יכול להיות מנוסח מחדש, מזהה לא משתנה.
  • רשימות מילות מפתח נשמרות במטמון יחד עם פרטי הכותר, 6 שעות. רענון שבועי לעמודי תגיות מספיק בהחלט.
  • לכותר בודד יש רשימת תגיות קצרה. בעמודי נושא התחילו ממזהה מילת מפתח והציגו את הכותרים שלה ב-discover, ולא להפך.
  • השתמשו ב-without_keywords כדי להסיר רעש, למשל תגית שאתם לא רוצים לראות בעמוד משפחתי.
  • מערך ריק הוא תשובה תקפה לכותרים לא מוכרים. הסתירו את שורת התגיות במקום להציג שגיאה.