בניית מאגר סרטים משלכם מ-API

amodb הוא API עצמאי שמדבר בפרוטוקול TMDB v3. לסרטים, אנשים, חברות, אוספים, מילות מפתח וז'אנרים יש מזהים מספריים והם מצביעים זה על זה, ולכן אפשר למלא מהם טבלאות SQL ולשמור אותן עדכניות. אכלסו את הטבלאות בדפדוף ב-discover, רעננו אותן לפי גיל, והתאימו את המזהים שלכם עם find. ל-amodb אין פיד שינויים, ולכן רענון הוא שליפה מחדש פשוטה של השורות ששמרתם.

מה מקבלים:

  • שישה סוגי ישויות מקושרים עם מזהים מספריים יציבים.
  • דפדוף ב-discover לטעינה הראשונה: עד 20 תוצאות בעמוד, 500 עמודים לשאילתה.
  • חלונות תאריכי יציאה ב-discover, לפיצול הטעינה הראשונה ולרשימת יציאות חדשות.
  • חיפושי מזהים חיצוניים עבור imdb_id, tvdb_id, wikidata_id ו-kinopoisk_id.

אילו נתונים מקבלים

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

ישותקריאהמפתחמקושר אל
סרטGET /3/movie/{movie_id}id, imdb_idgenres[].id, production_companies[].id, belongs_to_collection.id
אדםGET /3/person/{person_id}id, imdb_idסרטים דרך /3/movie/{movie_id}/credits
חברהGET /3/company/{company_id}idסרטים דרך with_companies ב-discover. הערך parent_company הוא תמיד null וה-description ריק
אוסףGET /3/collection/{collection_id}idparts[], רשימת סרטים
מילת מפתחGET /3/keyword/{keyword_id}idסרטים דרך /3/keyword/{keyword_id}/movies או with_keywords
ז'אנרGET /3/genre/movie/listidgenres[].id בסרטים

קשרים של רבים לרבים דורשים טבלאות קישור: movie_genre, movie_company, movie_keyword ו-movie_credit. השתמשו ב-credit_id מעמוד קרדיטים כמפתח של האחרונה. רשימות השדות נמצאות בעמודים סרטים, אנשים ואוספים.

מתחילים בשלושה שלבים

  1. השוו את שלושת קצבי הבקשות בעמוד תמחור. קצב גבוה יותר מקצר את הטעינה הראשונה, ושום דבר אחר לא משתנה.
  2. צרו מפתח בלוח הבקרה של החשבון ושמרו אותו במשתנה סביבה.
  3. קראו ל-/3/discover/movie עבור חלון של יום אחד של תאריכי יציאה, ואז שלפו כל מזהה ברשימה.

בקשה לדוגמה

סקריפט ה-PHP מציג את הסרטים שיצאו אתמול והיום דרך discover ומעדכן או מוסיף (upsert) כל רשומה בטבלת SQLite. הוא ישן 3 שניות בין קריאות פרטים כדי להישאר מתחת ל-20 בקשות לדקה, מנסה שוב אחרי 429 לפי Retry-After, ומוחק שורות שהמזהה שלהן מחזיר עכשיו 404.

bashphp
curl -s "https://api.amodb.dev/3/discover/movie?primary_release_date.gte=2026-10-17&primary_release_date.lte=2026-10-18&sort_by=primary_release_date.asc&page=1" \
  -H "Authorization: Bearer $AMODB_KEY"
<?php
const BASE = 'https://api.amodb.dev/3';

function amodb(string $path, array $query = []): ?array
{
    $url = BASE . $path . '?' . http_build_query($query);
    for ($attempt = 0; $attempt < 3; $attempt++) {
        $retryAfter = 1;
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
            CURLOPT_HEADERFUNCTION => function ($handle, $line) use (&$retryAfter) {
                if (stripos($line, 'Retry-After:') === 0) {
                    $retryAfter = max(1, (int) trim(substr($line, 12)));
                }
                return strlen($line);
            },
        ]);
        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        if ($status === 429) {
            sleep($retryAfter);
            continue;
        }
        if ($status === 404) {
            return null;
        }
        if ($status !== 200) {
            throw new RuntimeException("amodb returned $status for $path");
        }
        return json_decode($body, true);
    }
    throw new RuntimeException("Still rate limited on $path");
}

$db = new PDO('sqlite:movies.sqlite');
$db->exec('CREATE TABLE IF NOT EXISTS movie (id INTEGER PRIMARY KEY, imdb_id TEXT, title TEXT, release_date TEXT, raw TEXT)');
$save = $db->prepare('INSERT OR REPLACE INTO movie (id, imdb_id, title, release_date, raw) VALUES (?, ?, ?, ?, ?)');
$drop = $db->prepare('DELETE FROM movie WHERE id = ?');

$from = date('Y-m-d', strtotime('-1 day'));
$to = date('Y-m-d');
$page = 1;
do {
    $list = amodb('/discover/movie', [
        'primary_release_date.gte' => $from,
        'primary_release_date.lte' => $to,
        'sort_by' => 'primary_release_date.asc',
        'page' => $page,
    ]);
    foreach ($list['results'] as $row) {
        $movie = amodb('/movie/' . $row['id'], ['language' => 'en-US']);
        if ($movie === null) {
            $drop->execute([$row['id']]);
            continue;
        }
        $save->execute([$movie['id'], $movie['imdb_id'] ?? null, $movie['title'], $movie['release_date'] ?? null, json_encode($movie)]);
        sleep(3);
    }
    $page++;
} while ($page <= min($list['total_pages'], 500));

discover מחזיר שורות רשימה, לא רשומות מלאות. אלה 2 מתוך 20 התוצאות בעמוד 1. קראו את /3/movie/{id} לשאר השדות.

JSON
{
  "page": 1,
  "results": [
    {
      "adult": false,
      "backdrop_path": "/siepLRGVjM8yLKppApkD3uSh8Y0.jpg",
      "genre_ids": [
        35
      ],
      "id": 1800227,
      "original_language": "en",
      "original_title": "Sly's Pack",
      "overview": "Nesmith, Gary, & Tony are smoking weed on the roof of a parking garage, but a...",
      "popularity": 0.0071,
      "poster_path": "/3HpIWZUI7jmpKZkfZNdchS2WsvN.jpg",
      "release_date": "2026-10-17",
      "title": "Sly's Pack",
      "video": false,
      "vote_average": 0,
      "vote_count": 0
    },
    {
      "adult": false,
      "backdrop_path": null,
      "genre_ids": [
        99
      ],
      "id": 1800168,
      "original_language": "en",
      "original_title": "The Good Life",
      "overview": "The Good LIfe is based on the best-selling book by Drs. Robert Waldinger and...",
      "popularity": 0.0143,
      "poster_path": null,
      "release_date": "2026-10-17",
      "title": "The Good Life",
      "video": false,
      "vote_average": 0,
      "vote_count": 0
    }
  ],
  "total_pages": 15,
  "total_results": 299
}

מילוי ורענון הטבלאות

משימהקריאהמגבלות
טעינה ראשונהGET /3/discover/movie עם sort_by וחלון תאריכיםpage מ-1 עד 500, עד 20 תוצאות בעמוד, כלומר 10,000 לשאילתה. פצלו לפי primary_release_date.gte ו-.lte כדי להרחיק.
יציאות חדשותGET /3/discover/movie עם primary_release_date.gte שמוגדר לזמן הריצה האחרונה, ו-GET /3/movie/upcomingנשמר במטמון 30 דקות.
רענון שורותGET /3/movie/{movie_id} לשורות שגילן מעל 6 שעותאין פיד שינויים. רעננו את הכותרים שמשתמשים פותחים, ואת השאר בתדירות נמוכה יותר.
חיבור המזהים שלכםGET /3/find/{external_id}מזהה אחד בקריאה, המקור נבחר עם external_source.
מילוי עצלGET /3/movie/{movie_id} כשמשתמש פותח כותרשמרו את התגובה עם חותמת זמן.

חלון הדפדוף הוא ההחלטה העיצובית המרכזית. כש-total_pages בתגובה גבוה מ-500, החלון מכיל יותר מ-10,000 שורות, ולכן חצו אותו לחצאים עד שהוא נכנס. שנה אחרונה דורשת חלוקה לחודשים, ויום אחד של יציאות הוא כמה מאות כותרים. שמרו את הפרוסה שסיימתם כדי שריצה שהתרסקה תוכל להמשיך. כללי ההתאמה לחיבור נמצאים בעמוד חיפוש לפי מזהה חיצוני.

תכנון גודל הסנכרון

כל שורה שמרעננים עולה קריאת פרטים אחת. מסלול של 20 בקשות לדקה נותן 1,200 קריאות בשעה, 40 נותן 2,400 ו-120 נותן 7,200. עמוד discover מציג 20 מזהים בקריאה אחת. הריצו את הרענון בשעות שקטות אם האפליקציה שלכם חולקת את המפתח, כי המגבלה היא לכל מפתח, לא לכל סקריפט. את הכותרות שמדווחות כמה נשאר בחלון ראו בעמוד מגבלות קצב.

מטמון בשתי שכבות

שכבהמה היא מחזיקהTTL
מטמון קצהפרטים וקרדיטים6 שעות
מטמון קצהרשימות discover, טרנדים ופופולריים30 דקות
מטמון קצהחיפוש10 דקות
מטמון קצההגדרות24 שעות
מטמון קצהתמונות30 יום
הטבלאות שלכםהשורות ששמרתםעד שכלל הגיל שלכם קובע לשלוף מחדש, אף פעם לא לפני 6 שעות

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

איך זה בהשוואה

יכולתגירוד דפים בעצמכםקבצי מערכי נתונים סטטייםamodb
עדכניותטרייה כמו הסריקה האחרונה שלכםטרייה כמו הקובץ האחרון שפורסםפרטים במטמון 6 שעות, שליפה מחדש לפי גיל
עדכונים מצטבריםסריקה מחדש והשוואההורדת קובץ חדשdiscover עם חלון תאריכי יציאה, בלי פיד שינויים
מזהים בין ישויותכתובות דפיםנקבעים על ידי המפרסםמזהים מספריים, imdb_id ו-/3/find
מה אתם מריציםסורקים ואחסוןאחסון ומשימת ייבואאחסון וסקריפט סנכרון
מגבלת קצבנקבעת על ידי האתרים שאתם סורקיםלא רלוונטי20, 40 או 120 בקשות לדקה, נספרות לכל מפתח
שפות לכל רשומהמה שכל דף מציעתלוי בקבצים14, נבחרות עם language

תמחור

הטעינה הראשונה היא החלק היקר, והיא מוגבלת בבקשות לדקה שלכם. בחרו 20, 40 או 120 לדקה בעמוד תמחור. שלמו על 1, 3, 6, 12 או 24 חודשים עם 0, 10, 20, 30 או 40 אחוז הנחה. שום דבר לא מתחדש אוטומטית, אין מסלול חינמי, וכל מסלול קורא את אותם נתונים.