Пабудуйце ўласную базу даных фільмаў з API

amodb гэта незалежнае API, якое працуе па пратаколе TMDB v3. Фільмы, людзі, кампаніі, калекцыі, ключавыя словы і жанры маюць лікавыя id і спасылаюцца адно на адно, таму з яго можна запоўніць табліцы SQL і трымаць іх актуальнымі. Запаўняйце табліцы праз discover па старонках, абнаўляйце іх па ўзросце і супастаўляйце свае ідэнтыфікатары праз find. У amodb няма стужкі changes, таму абнаўленне гэта звычайнае паўторнае чытанне радкоў, якія вы захоўваеце.

Што вы атрымліваеце:

  • Шэсць звязаных тыпаў сутнасцей са стабільнымі лікавымі id.
  • Старонкі discover для першай загрузкі: да 20 вынікаў на старонку, 500 старонак на запыт.
  • Вокны дат выхаду ў discover, каб дзяліць першую загрузку і атрымліваць новыя рэлізы.
  • Пошук па вонкавых id для 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 са старонкі удзельнікі як ключ апошняй. Спісы палёў ёсць на старонках фільмы, персоны і калекцыі.

Пачніце за 3 крокі

  1. Параўнайце тры частаты запытаў на старонцы цэны. Большая частата скарачае першую загрузку, больш нічога не мяняецца.
  2. Стварыце ключ у асабістым кабінеце і трымайце яго ў зменнай асяроддзя.
  3. Выклічце /3/discover/movie для аднадзённага акна дат выхаду, потым атрымайце кожны id са спісу.

Прыклад запыту

Скрыпт на PHP пералічвае фільмы, што выйшлі ўчора і сёння, праз discover і дадае або абнаўляе кожны запіс у табліцы SQLite. Ён спіць 3 секунды паміж чытаннямі дэталяў, каб заставацца ніжэй за 20 запытаў у хвіліну, паўтарае 429 пасля Retry-After і выдаляе радкі, чый id цяпер вяртае 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 гадзінСтужкі changes няма. Абнаўляйце назвы, якія адкрываюць карыстальнікі, а астатнія радзей.
Злучэнне ўласных idGET /3/find/{external_id}Адзін id на выклік, крыніца вызначаецца праз external_source.
Лянівае запаўненнеGET /3/movie/{movie_id}, калі карыстальнік адкрывае назвуЗахоўвайце адказ з часавой пазнакай.

Акно старонак гэта галоўнае рашэнне ў праектаванні. Калі total_pages у адказе вышэй за 500, акно змяшчае больш за 10 000 радкоў, таму дзеліце яго напалам, пакуль не памесціцца. Для апошняга года патрэбны месяцы, а адзін дзень рэлізаў гэта некалькі соцень назваў. Захоўвайце скончаны кавалак, каб запуск, што збоіў, мог працягнуцца. Правілы супастаўлення для злучэння гл. на старонцы пошук па вонкавым ідэнтыфікатары.

Ацэнка аб’ёму сінхранізацыі

Кожны абноўлены радок каштуе адно чытанне дэталяў. План на 20 запытаў у хвіліну дае 1200 выклікаў у гадзіну, 40 дае 2400, а 120 дае 7200. Старонка discover пералічвае 20 id за адзін выклік. Запускайце абнаўленне ў гадзіны меншай нагрузкі, калі ваша праграма дзеліць ключ, бо ліміт дзейнічае на ключ, а не на скрыпт. Загалоўкі, што паказваюць, колькі засталося ў акне, гл. на старонцы ліміты запытаў.

Кэшаванне ў два пласты

ПластШто трымаеTTL
Edge-кэшДэталі і ўдзельнікі6 гадзін
Edge-кэшСпісы discover, трэндаў і папулярных30 хвілін
Edge-кэшПошук10 хвілін
Edge-кэшКанфігурацыя24 гадзіны
Edge-кэшВыявы30 дзён
Вашы табліцыРадкі, якія вы захоўваецеПакуль правіла ўзросту не скажа паўтарыць запыт, але не раней за 6 гадзін

Edge-кэш агульны для ключоў, але ліміт запытаў правяраецца да яго, таму трапленне ў кэш усё роўна расходуе адзін запыт з вашай хвіліны. Паўторнае чытанне радка часцей чым раз у 6 гадзін вяртае тую ж копію і марнуе квоту. Хай правіла ўзросту вырашае, калі абнаўляць.

Параўнанне

МагчымасцьУласны скрэйпінг старонакСтатычныя файлы набораў даныхamodb
СвежасцьНастолькі свежа, як апошні абыходНастолькі свежа, як апошні апублікаваны файлДэталі кэшуюцца 6 гадзін, абнаўляйце па ўзросце
Паэтапныя абнаўленніПаўторны абыход і параўнаннеСпампаваць новы файлDiscover з акном даты выхаду, без стужкі changes
Id паміж сутнасцяміURL старонакВызначае выдавецЛікавыя id, imdb_id і /3/find
Што вы запускаецеКраўлеры і сховішчаСховішча і задача імпартуСховішча і скрыпт сінхранізацыі
Ліміт запытаўВызначаюць сайты, якія вы абыходзіцеНе ўжываецца20, 40 або 120 запытаў у хвіліну, на ключ
Мовы на запісТое, што прапануе кожная старонкаЗалежыць ад файлаў14, выбіраюцца праз language

Цэны

Першая загрузка самая дарагая, і яна абмежавана вашымі запытамі ў хвіліну. Абярыце 20, 40 або 120 у хвіліну на старонцы цэны. Плаціце за 1, 3, 6, 12 або 24 месяцы са зніжкай 0, 10, 20, 30 або 40 працэнтаў. Нічога не прадаўжаецца аўтаматычна, бясплатнага тарыфа няма, і кожны план чытае тыя ж даныя.