בניית מאגר סרטים משלכם מ-API
amodb הוא API עצמאי שמדבר בפרוטוקול TMDB v3. לסרטים, אנשים, חברות, אוספים, מילות מפתח וז'אנרים יש מזהים מספריים והם מצביעים זה על זה, ולכן אפשר למלא מהם טבלאות SQL ולשמור אותן עדכניות. אכלסו את הטבלאות בדפדוף ב-discover, רעננו אותן לפי גיל, והתאימו את המזהים שלכם עם find. ל-amodb אין פיד שינויים, ולכן רענון הוא שליפה מחדש פשוטה של השורות ששמרתם.
מה מקבלים:
- שישה סוגי ישויות מקושרים עם מזהים מספריים יציבים.
- דפדוף ב-discover לטעינה הראשונה: עד 20 תוצאות בעמוד, 500 עמודים לשאילתה.
- חלונות תאריכי יציאה ב-discover, לפיצול הטעינה הראשונה ולרשימת יציאות חדשות.
- חיפושי מזהים חיצוניים עבור
imdb_id,tvdb_id,wikidata_idו-kinopoisk_id.
אילו נתונים מקבלים
זהו מודל הנתונים. כל שורה היא טבלה אחת בעותק יחסי.
| ישות | קריאה | מפתח | מקושר אל |
|---|---|---|---|
| סרט | GET / | id, imdb_id | genres[].id, production_, belongs_ |
| אדם | GET / | id, imdb_id | סרטים דרך / |
| חברה | GET / | id | סרטים דרך with_companies ב-discover. הערך parent_company הוא תמיד null וה-description ריק |
| אוסף | GET / | id | parts[], רשימת סרטים |
| מילת מפתח | GET / | id | סרטים דרך / או with_keywords |
| ז'אנר | GET / | id | genres[].id בסרטים |
קשרים של רבים לרבים דורשים טבלאות קישור: movie_genre, movie_company, movie_keyword ו-movie_credit. השתמשו ב-credit_id מעמוד קרדיטים כמפתח של האחרונה. רשימות השדות נמצאות בעמודים סרטים, אנשים ואוספים.
מתחילים בשלושה שלבים
- השוו את שלושת קצבי הבקשות בעמוד תמחור. קצב גבוה יותר מקצר את הטעינה הראשונה, ושום דבר אחר לא משתנה.
- צרו מפתח בלוח הבקרה של החשבון ושמרו אותו במשתנה סביבה.
- קראו ל-
/3/discover/movieעבור חלון של יום אחד של תאריכי יציאה, ואז שלפו כל מזהה ברשימה.
בקשה לדוגמה
סקריפט ה-PHP מציג את הסרטים שיצאו אתמול והיום דרך discover ומעדכן או מוסיף (upsert) כל רשומה בטבלת SQLite. הוא ישן 3 שניות בין קריאות פרטים כדי להישאר מתחת ל-20 בקשות לדקה, מנסה שוב אחרי 429 לפי Retry-After, ומוחק שורות שהמזהה שלהן מחזיר עכשיו 404.
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} לשאר השדות.
{
"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_ ו-.lte כדי להרחיק. |
| יציאות חדשות | GET /3/discover/movie עם primary_ שמוגדר לזמן הריצה האחרונה, ו-GET /3/movie/upcoming | נשמר במטמון 30 דקות. |
| רענון שורות | GET / לשורות שגילן מעל 6 שעות | אין פיד שינויים. רעננו את הכותרים שמשתמשים פותחים, ואת השאר בתדירות נמוכה יותר. |
| חיבור המזהים שלכם | GET / | מזהה אחד בקריאה, המקור נבחר עם external_source. |
| מילוי עצל | GET / כשמשתמש פותח כותר | שמרו את התגובה עם חותמת זמן. |
חלון הדפדוף הוא ההחלטה העיצובית המרכזית. כש-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 אחוז הנחה. שום דבר לא מתחדש אוטומטית, אין מסלול חינמי, וכל מסלול קורא את אותם נתונים.