Heim > Backend-Entwicklung > Python-Tutorial > Eine Datenpipeline für Millionen Filme und Millionen Streaming-Links

Eine Datenpipeline für Millionen Filme und Millionen Streaming-Links

Patricia Arquette
Freigeben: 2024-12-27 15:02:10
Original
986 Leute haben es durchsucht

Februar 2023: Ich wollte alle Partituren für Filme und Fernsehsendungen auf einer Seite sehen und wissen, wo ich sie streamen kann, konnte aber keinen Aggregator finden, der alle für mich relevanten Quellen enthält.

März 2023: Also habe ich ein MVP erstellt, das spontan Punkte sammelte, und die Website online gestellt. Es hat funktioniert, war aber langsam (10 Sekunden, um die Ergebnisse anzuzeigen).

Okt 2023: Da mir klar wurde, dass das Speichern von Daten auf meiner Seite eine Notwendigkeit ist, habe ich windmill.dev entdeckt. Es stellt ähnliche Orchestrierungs-Engines deutlich in den Schatten – zumindest für meine Bedürfnisse.


Schneller Vorlauf bis heute und nach 12 Monaten ununterbrochener Datensuche möchte ich Ihnen mitteilen, wie die Pipeline im Detail funktioniert. Sie erfahren, wie Sie ein komplexes System aufbauen, das Daten aus vielen verschiedenen Quellen erfasst, Daten normalisiert und in einem optimierten Format für Abfragen kombiniert.

Bilder oder nicht passiert!

A Data Pipeline for illion movies and million streaming links

Dies ist die Ausführungsansicht. Jeder Punkt repräsentiert einen Flow-Lauf. Ein Flow kann alles sein, zum Beispiel ein einfaches Ein-Schritt-Skript:

A Data Pipeline for illion movies and million streaming links

Der Block in der Mitte enthält ein Skript wie dieses (vereinfacht):

def main():
    return tmdb_extract_daily_dump_data()

def tmdb_extract_daily_dump_data():
    print("Checking TMDB for latest daily dumps")
    init_mongodb()

    daily_dump_infos = get_daily_dump_infos()
    for daily_dump_info in daily_dump_infos:
        download_zip_and_store_in_db(daily_dump_info)

    close_mongodb()
    return [info.to_mongo() for info in daily_dump_infos]

[...]
Nach dem Login kopieren
Nach dem Login kopieren

Das folgende Biest ist ebenfalls ein Flow (denken Sie daran, dies ist nur einer der grünen Punkte):

A Data Pipeline for illion movies and million streaming links

(Bild mit höherer Auflösung: https://i.imgur.com/LGhTUGG.png)

Lass uns das aufschlüsseln:

  1. Holen Sie sich den nächsten priorisierten Film oder die Fernsehsendung (siehe nächster Abschnitt)
  2. Holen Sie sich aktuelle Daten von TMDB
  3. Scrape IMDb, Metacritic und Rotten Tomatoes für aktuelle Ergebnisse
  4. Suchen Sie TV-Tropen nach... Tropen
  5. Huggingface API zum Sammeln von DNA-Daten (wird weiter unten erläutert)
  6. Speichern Sie hochdimensionale Vektoren für DNA-Daten
  7. Speichern Sie relationale Daten für Filme, Shows und Streaming-Links

Jeder dieser Schritte ist mehr oder weniger komplex und erfordert die Verwendung asynchroner Prozesse.

Wo fängst du an? Prioritätswarteschlange

Um zu bestimmen, welche Titel als nächstes ausgewählt werden sollen, werden zwei Spuren parallel verarbeitet. Dies ist ein weiterer Bereich, in dem Windmill glänzt. Parallelisierung und Orchestrierung funktionieren mit ihrer Architektur einwandfrei.

Die beiden Spuren zur Auswahl des nächsten Artikels sind:

Spur 1: Flüsse für jede Datenquelle separat

Zunächst werden Titel, an die keine Daten angehängt sind, für jede Datenquelle ausgewählt. Das heißt, wenn die Metacritic-Pipeline einen Film enthält, der noch nicht gescrapt wurde, wird dieser als nächstes ausgewählt. Dadurch wird sichergestellt, dass jeder Titel, auch neue, mindestens einmal verarbeitet wurde.

Sobald an jeden Titel Daten angehängt sind, wählt die Pipeline diejenigen mit den am wenigsten aktuellen Daten aus.

Hier ist ein Beispiel für einen solchen Flow-Lauf, hier mit einem Fehler, weil das Ratenlimit erreicht wurde:

A Data Pipeline for illion movies and million streaming links

Mit Windmill können Sie ganz einfach Wiederholungsversuche für jeden Schritt im Ablauf definieren. In diesem Fall besteht die Logik darin, es im Fehlerfall dreimal erneut zu versuchen. Sofern das Ratenlimit nicht erreicht wurde (was normalerweise ein anderer Statuscode oder eine andere Fehlermeldung ist), stoppen wir sofort.

Spur 2: Prioritätsfluss für jeden Film/jede Show separat

Das oben Gesagte funktioniert, weist jedoch ein ernstes Problem auf: neue Versionen werden nicht rechtzeitig genug aktualisiert. Es kann Wochen oder sogar Monate dauern, bis alle Datenaspekte erfolgreich abgerufen wurden. Beispielsweise kann es vorkommen, dass ein Film über einen aktuellen IMDb-Score verfügt, die anderen Scores jedoch veraltet sind und die Streaming-Links komplett fehlen. Insbesondere bei den Spielständen und der Streaming-Verfügbarkeit wollte ich eine deutlich bessere Genauigkeit erreichen.

Um dieses Problem zu lösen, konzentriert sich die zweite Spur auf eine andere Priorisierungsstrategie: Die beliebtesten und angesagtesten Filme/Sendungen werden für eine vollständige Datenaktualisierung über alle Datenquellen hinweg ausgewählt.Ich habe diesen Ablauf bereits zuvor gezeigt, Es ist das, das ich vorhin als Biest bezeichnet habe.

Titel, die häufiger in der App angezeigt werden, erhalten ebenfalls einen Prioritätsschub. Das bedeutet, dass jedes Mal, wenn ein Film oder eine Sendung in den Top-Suchergebnissen auftaucht oder wenn die Detailansicht geöffnet wird, diese wahrscheinlich bald aktualisiert werden.

Jeder Titel kann nur einmal pro Woche aktualisiert werden unter Verwendung der Prioritätsspur, um sicherzustellen, dass wir keine Daten abrufen, die sich in der Zwischenzeit wahrscheinlich nicht geändert haben.

Dürfen Sie das tun? Überlegungen zum Schaben

Sie fragen sich vielleicht: Ist Scraping legal? Das Erfassen der Daten ist normalerweise in Ordnung. Was Sie mit den Daten tun, muss jedoch sorgfältig überlegt werden. Sobald Sie von einem Dienst profitieren, der gescrapte Daten verwendet, verstoßen Sie wahrscheinlich gegen deren Geschäftsbedingungen. (siehe „Die Rechtslandschaft des Web Scraping“ und „Scraping“ ist nur automatisierter Zugriff, und jeder tut es )

Scraping und damit verbundene Gesetze sind neu und oft ungetestet und es gibt viele rechtliche Grauzonen. Ich bin entschlossen, jede Quelle entsprechend zu zitieren, Tarifbeschränkungen zu respektieren und unnötige Anfragen zu vermeiden, um die Auswirkungen auf ihre Dienste zu minimieren.

Fakt ist, dass die Daten nicht zur Erzielung von Gewinnen verwendet werden. GoodWatch wird für immer für alle kostenlos nutzbar sein.

Mehr Arbeit? Ja, Mylord

Windmill verwendet Worker, um die Codeausführung auf mehrere Prozesse zu verteilen. Jeder Schritt in einem Ablauf wird an einen Worker gesendet, wodurch er von der eigentlichen Geschäftslogik unabhängig wird. Nur die Haupt-App orchestriert die Jobs, während Worker nur Eingabedaten und Code zur Ausführung erhalten und das Ergebnis zurückgeben.

Es ist eine effiziente Architektur, die sich gut skalieren lässt. Derzeit sind es 12 Arbeiter, die sich die Arbeit aufteilen. Sie werden alle auf Hetzner gehostet.

Jeder Worker hat einen maximalen Ressourcenverbrauch von 1 vCPU und 2 GB RAM. Hier eine Übersicht:

A Data Pipeline for illion movies and million streaming links

Windmühlen-Editor

Windmill bietet ein browserinternes IDE-ähnliches Editor-Erlebnis mit Linting, automatischer Formatierung, einem KI-Assistenten und sogar kollaborativer Bearbeitung (Letztes ist eine kostenpflichtige Funktion). Das Beste ist jedoch dieser Button:

A Data Pipeline for illion movies and million streaming links

Es ermöglicht mir, Skripte schnell zu iterieren und zu testen, bevor ich sie bereitstelle. Normalerweise bearbeite und teste ich Dateien im Browser und schiebe sie auf Git, wenn ich fertig bin.

Das Einzige, was für eine optimale Codierungsumgebung fehlt, sind Debugging-Tools (Haltepunkte und variabler Kontext). Derzeit debugge ich Skripte in meiner lokalen IDE, um diese Schwachstelle zu beheben.

Zahlen. Ich mag Zahlen

Ich auch!

Derzeit benötigt GoodWatch etwa 100 GB dauerhaften Datenspeicher:

  • 15 GB für rohe Vorverarbeitungsdaten (MongoDB)
  • 23 GB für verarbeitete relationale Daten (Postgres)
  • 67 GB für Vektordaten (Postgres)

Jeden Tag laufen 6.500 Flows durch die Orchestrierungs-Engine von Windmill. Daraus ergibt sich ein Tagesvolumen von:

  • 30.000 IMDb-Seiten
  • 9.000 TV Tropes-Seiten
  • 5.000 Rotten Tomatoes-Seiten
  • 1.500 Huggingface-Eingabeaufforderungen
  • 600 Metakritische Seiten

Diese Zahlen unterscheiden sich aufgrund unterschiedlicher Ratenbegrenzungsrichtlinien grundlegend.

Einmal pro Tag werden die Daten bereinigt und zum endgültigen Datenformat zusammengefasst. Derzeit ist die Datenbank, die die GoodWatch-Webapp-Stores betreibt:

  • 10 MillionenStreaming-Links
  • 1 MillionFilme
  • 300.000DNA-Werte
  • 200.000 Fernsehsendungen
  • 70.000 Filme/Sendungen mit DNA

Was ist das für eine DNA, von der Sie immer reden?

Stellen Sie sich vor, Sie könnten Filme nur nach ihrem Genre unterscheiden, was äußerst einschränkend ist, oder?

Deshalb habe ich das DNA-Projekt gestartet. Es ermöglicht die Kategorisierung von Filmen und Shows nach anderen Attributen wie Stimmung, Plotelements, Charaktertypen, Dialog oder Schlüssel-Requisiten .

Hier sind die Top 10 aller DNA-Werte über alle Artikel hinweg:

A Data Pipeline for illion movies and million streaming links

Es ermöglicht zwei Dinge:

  1. Nach DNA-Werten filtern (unter Verwendung relationaler Daten)
  2. Suche nach Ähnlichkeit (unter Verwendung von Vektordaten)

Beispiele:

  • Melancholische Stimmung
  • Ähnliche Geschichte wie Dune: Teil Zwei

Es wird in Zukunft einen eigenen Blogbeitrag über die DNA mit vielen weiteren Details geben.

Tauchen Sie tiefer in die Datenpipeline ein

Um die Funktionsweise der Datenpipeline vollständig zu verstehen, finden Sie hier eine Aufschlüsselung der Ereignisse für jede Datenquelle:

1. Einmal täglich wird eine MongoDB-Sammlung mit allen erforderlichen Eingabedaten aktualisiert

Für jede Datenquelle gibt es einen Init-Flow, der eine MongoDB-Sammlung mit allen erforderlichen Daten vorbereitet. Für IMDb ist das nur die imdb_id. Für Rotten Tomatoes sind der Titel und das Erscheinungsjahr erforderlich. Das liegt daran, dass die ID unbekannt ist und wir anhand des Namens die richtige URL erraten müssen.

2. Rufen Sie kontinuierlich Daten ab und schreiben Sie sie in die MongoDB-Sammlung

Basierend auf der oben erläuterten Prioritätsauswahl werden Elemente in den vorbereiteten Sammlungen mit den abgerufenen Daten aktualisiert. Jede Datenquelle verfügt über eine eigene Sammlung, die mit der Zeit immer vollständiger wird.

3. Einmal am Tag sammeln verschiedene Flows die Daten aus den MongoDB-Sammlungen und schreiben sie in Postgres

Es gibt einen Ablauf für Filme, einen für Fernsehsendungen und einen weiteren für Streaming-Links. Sie sammeln alle notwendigen Daten aus verschiedenen Sammlungen und speichern sie in ihren jeweiligen Postgres-Tabellen, die dann von der Webanwendung abgefragt werden.

Hier ist ein Auszug aus dem Ablauf und dem Skript zum Kopieren von Filmen:

A Data Pipeline for illion movies and million streaming links

Die Ausführung einiger dieser Flows dauert lange, manchmal sogar länger als 6 Stunden. Dies kann optimiert werden, indem alle aktualisierten Elemente markiert und nur diese kopiert werden, anstatt den gesamten Datensatz stapelweise zu verarbeiten. Einer von vielen TODO-Punkten auf meiner Liste ?

Terminplanung

Die Planung ist so einfach wie das Definieren von Cron-Ausdrücken für jeden Ablauf oder jedes Skript, das automatisch ausgeführt werden muss:

A Data Pipeline for illion movies and million streaming links

Hier ein Auszug aller Zeitpläne, die für GoodWatch definiert sind:

A Data Pipeline for illion movies and million streaming links

Insgesamt sind rund 50 Zeitpläne definiert.

Herausforderungen

Mit großartigen Daten geht große Verantwortung einher. Es kann viel schiefgehen. Und das tat es.

Sehr langsame Verarbeitung

Frühe Versionen meiner Skripte brauchten ewig, um alle Einträge in einer Sammlung oder Tabelle zu aktualisieren. Das lag daran, dass ich jeden Artikel einzeln eingefügt habe. Das verursacht viel Overhead und verlangsamt den Prozess erheblich.

Ein viel besserer Ansatz besteht darin, die einzufügenden Daten zu sammeln und die Datenbankabfragen in einem Batch durchzuführen. Hier ist ein Beispiel für MongoDB:

def main():
    return tmdb_extract_daily_dump_data()

def tmdb_extract_daily_dump_data():
    print("Checking TMDB for latest daily dumps")
    init_mongodb()

    daily_dump_infos = get_daily_dump_infos()
    for daily_dump_info in daily_dump_infos:
        download_zip_and_store_in_db(daily_dump_info)

    close_mongodb()
    return [info.to_mongo() for info in daily_dump_infos]

[...]
Nach dem Login kopieren
Nach dem Login kopieren

Speicherhungrige Skripte

Selbst bei der Stapelverarbeitung verbrauchten einige Skripte so viel Speicher, dass die Worker abstürzten. Die Lösung bestand darin, die Chargengröße für jeden Anwendungsfall sorgfältig abzustimmen.

Einige Stapel lassen sich gut in 5000er-Schritten ausführen, andere speichern viel mehr Daten im Speicher und laufen besser mit 500er-Schritten.

Windmill verfügt über eine großartige Funktion, um den Speicher zu beobachten, während ein Skript ausgeführt wird:

A Data Pipeline for illion movies and million streaming links

Wichtige Erkenntnisse

Windmill ist eine große Bereicherung im Toolkit jedes Entwicklers zur Automatisierung von Aufgaben. Für mich war es ein unschätzbarer Produktivitätsschub, da ich mich auf die Ablaufstruktur und die Geschäftslogik konzentrieren konnte, während ich die schwere Arbeit der Aufgabenkoordinierung, Fehlerbehandlung, Wiederholungsversuche und Caching auslagerte.

Der Umgang mit großen Datenmengen ist immer noch eine Herausforderung und die Optimierung der Pipeline ist ein fortlaufender Prozess – aber ich bin wirklich zufrieden damit, wie sich bisher alles entwickelt hat.

Okay, okay. Das reicht

Das dachte ich mir. Lassen Sie mich einfach ein paar Ressourcen verlinken und wir sind fertig:

  • GoodWatch
  • GoodWatch Discord Community
  • Windmühle
  • Windmill Discord Community

Wussten Sie, dass GoodWatch Open Source ist? Sie können sich alle Skripte und Flow-Definitionen in diesem Repository ansehen: https://github.com/alp82/goodwatch-monorepo/tree/main/goodwatch-flows/windmill/f

Lassen Sie es mich wissen, wenn Sie Fragen haben.

Das obige ist der detaillierte Inhalt vonEine Datenpipeline für Millionen Filme und Millionen Streaming-Links. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage