Files
horror/backend/app/netflix.py
2026-08-12 19:30:41 +02:00

54 lines
1.8 KiB
Python

"""Die echte Netflix-Titel-ID aus TMDBs Watch-Seite lesen.
Die API liefert nur den Anbieternamen. Die Titel-ID steht ausschließlich im
HTML der Watch-Seite, URL-kodiert im Weiterleitungslink von JustWatch.
Ohne sie bliebe nur eine Netflix-Titelsuche, und die geht ins Leere, sobald
Netflix den Film anders nennt: "LIENZO" heißt dort "Die Leinwand".
"""
import asyncio
import logging
import re
import httpx
log = logging.getLogger("netflix")
TITLE_ID = re.compile(r"netflix\.com%2Ftitle%2F(\d+)")
UA = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/131.0"
# Zu dichte Abrufe drosselt TMDB. Die Seite kommt dann mit Status 200, aber
# ohne Anbieterblock. Filme ohne ID versucht der nächste Sync erneut.
PAUSE = 1.5
def watch_url(movie_id):
return f"https://www.themoviedb.org/movie/{movie_id}/watch?locale=DE"
def title_url(netflix_id):
return f"https://www.netflix.com/de/title/{netflix_id}"
async def fetch_ids(movie_ids):
"""Seriell, mit Pause. Gibt {tmdb_id: netflix_id} für alles Gefundene."""
found = {}
async with httpx.AsyncClient(
headers={"User-Agent": UA}, timeout=60.0, follow_redirects=True
) as http:
for index, movie_id in enumerate(movie_ids, 1):
try:
resp = await http.get(watch_url(movie_id))
# Mehrere IDs bedeuten mehrere Fassungen — Godzilla Minus One
# liegt in Farbe und in Schwarzweiß. Die erste Kachel ist die
# Hauptfassung.
ids = TITLE_ID.findall(resp.text)
if ids:
found[movie_id] = ids[0]
except httpx.HTTPError:
log.warning("Watch-Seite nicht erreichbar: %s", movie_id)
if index % 50 == 0:
log.info(" %s/%s Watch-Seiten gelesen", index, len(movie_ids))
await asyncio.sleep(PAUSE)
return found