Zurück zur Startseite

Asynchroner Manga-Parser: Architektur in Python

Detaillierte Aufschlüsselung der Architektur eines asynchronen Manga-Parsers in Python. Umfasst Verträge über abstrakte Klassen, Validierung mit Pydantic, ORM mit SQLAlchemy und Übergang zu Mikroservices. Schwerpunkt auf Skalierbarkeit und Wartbarkeit der Codebasis.

Python Manga-Parser: Von Verträgen zu Mikroservices
Advertisement 728x90

Asynchroner Manga-Parser in Python: Von der Architektur zu Microservices

Der Aufbau eines skalierbaren Manga-Parsers ist eine Aufgabe, die die Herausforderungen der asynchronen Programmierung, des Schnittstellendesigns und des Zustandsmanagements vereint. Manga-Day ist ein praxisnahes Beispiel für den Übergang von einem Monolithen zu einer Microservices-Architektur mit asyncio, Pydantic und SQLAlchemy. Das Projekt entstand ursprünglich als Tool zur automatischen Datensammlung von Dutzenden von Websites, hat sich aber zu einem Tutorial für das Design erweiterbarer Systeme entwickelt.

Architekturgrundlagen: Schnittstellen und Asynchronität

Der Kern des Systems basiert auf der abstrakten Klasse BaseSpider. Jeder spezifische Parser (z. B. für multi-manga) implementiert eine einzige Schnittstelle, sodass neue Quellen dynamisch hinzugefügt werden können, ohne den Kern zu verändern. Die Schnittstelle umfasst drei zentrale Methoden:

from abc import ABC, abstractmethod

class BaseSpider(ABC):
    BASE_URL = "https://example-manga.com"

    @abstractmethod
    async def get(self, url: str, **kwargs) -> Optional[MangaSchema]: ...

    @abstractmethod
    async def pages(
        self, start_page: int | None = None
    ) -> AsyncGenerator[list[BaseManga], Any]: ...

Dieser Ansatz gewährleistet:

Google AdInline article slot
  • Einheitliche Behandlung von Fehlern und Timeouts
  • Die Möglichkeit, jeden Spider unabhängig zu testen
  • Unterstützung für horizontale Skalierung durch asynchrone Generatoren

Die Asynchronität wird auf asyncio-Ebene umgesetzt und ermöglicht die effiziente Bearbeitung von Hunderten paralleler Anfragen ohne I/O-Blockaden. Das ist besonders wichtig bei langsamen oder instabilen Quellen.

Datenvalidierung und ORM-Modelle

Pydantic sorgt für striktes Typing und Validierung. Das System basiert auf drei Modellstufen:

  • BaseManga — minimale Feldmenge: title, poster, url, sku (SHA256-Hash)
  • MangaWithGallery — ergänzt Liste von Bild-URLs
  • MangaSchema — vollständiges Modell mit genres, author und language (optional)

In der von SQLAlchemy verwalteten Datenbank sind folgende Entitäten implementiert:

Google AdInline article slot
  • Manga, Author, Genre, Language — Kerntabellen
  • GenreManga — Many-to-Many-Beziehung für Genres
  • Gallery — separate Tabelle für Bilder (um sie von der Hauptabfrage zu trennen)
  • GeneratedPdf — veraltete Tabelle, die zur Entfernung vorgesehen ist

Die Auslagerung der Gallery in eine eigene Entität vermeidet N+1-Probleme beim Laden von Manga-Listen – Bilder werden nun nur bei expliziter Anfrage geladen.

Manager: Geschäftslogik über den Daten

Manager bilden die Geschäftslogikschicht – Klassen für spezifische Operationen:

  • MangaManager: CRUD-Operationen nach SKU, URL, ID
  • RequestManager: HTTP-Anfragen mit Retry-Logik und Timeouts
  • AlertManager: Universelles Benachrichtigungssystem (Telegram, Discord usw.)
  • SpiderManager: Zentraler Orchestrator für alle Spider

Besonders interessant ist der SpiderManager wegen seiner Modularität. Er ist in vier Dateien aufgeteilt:

Google AdInline article slot
  • _load.py — dynamisches Laden der Spider über __all__
  • _status.py — Statusmodelle und Enums
  • _starter.py — Start und Lebenszyklusverwaltung
  • _spider.py — Zusammenführung der Komponenten zu einer einheitlichen Schnittstelle

Diese Zerlegung vereinfacht Tests und isoliert Änderungen – das Hinzufügen eines neuen Spiders erfordert nur eine Registrierung in __init__.py, ohne Kernanpassungen.

Übergang zu Microservices: Schmerzpunkte und Lösungen

Das Projekt startete als Monolith, doch zwei Dienste wurden zu Auslösern für den Wandel:

  • PDFService — verbrauchte zu viel RAM, in einen separaten Container ausgelagert
  • Bot — benötigte WebSocket und JWT-Authentifizierung, ebenfalls in einen isolierten Dienst migriert

Die Migration verlief in mehreren Phasen:

  • Frontend vom Kern entkoppelt – arbeitet nun ausschließlich über REST API, mit minimalem Jinja nur für Konfigurationen
  • Bot mit aiohttp für WebSocket umgeschrieben und rollenbasierter Zugriff via JWT implementiert
  • PDF-Generierung läuft nun als Hintergrundtask mit begrenzter Speichernutzung

Hauptprobleme:

  • Serialisierung komplexer Objekte zwischen Diensten
  • Datenkonsistenz bei partiellen Ausfällen
  • Einrichtung von Health Checks und graceful Shutdown

Wichtige Erkenntnisse

  • Schnittstellen sind wichtiger als Implementierungen — abstrakte Klassen ermöglichten Skalierung ohne Kern-Refactoring
  • Asynchronität ≠ automatische Performance — Anzahl paralleler Tasks kontrollieren und Semaphore nutzen
  • ORM ist kein Allheilmittel — manuelle Query-Optimierung und Denormalisierung (z. B. Auslagerung der Gallery) sind für Performance entscheidend
  • Microservices erhöhen Komplexität, bieten aber Flexibilität — Auslagerung des PDFService löste das Speicherproblem, steigerte aber den Deploymentsaufwand
  • Testbarkeit ist architektonisches Ergebnis — Modularität des SpiderManagers erlaubte Unit-Tests ohne Mocking externer Abhängigkeiten

Das Projekt dient nun als Einstieg, um zu verstehen, wie Systeme aufgebaut werden, die sich über Jahre weiterentwickeln lassen. Der Codebase umfasst Zehntausende Zeilen, doch klare Trennung der Verantwortlichkeiten hält es wartbar. Nächste Schritte: Implementierung eines Message Brokers für Task-Queues und vollständiges CI/CD mit Autotests bei jedem Pull Request.

— Editorial Team

Advertisement 728x90

Weiterlesen