"""Adapter für die Brettspielbox-Messevorschau (A-Z-Liste). Seite: …/brettspiel-neuheiten-spiel-2026-herbst-2026-a-z/ (WordPress). Struktur (Stand Analyse August 2026): Die komplette A-Z-Liste steht auf einer Seite in `div.wp-block-columns`-Blöcken — pro Buchstabe ein Absatz (`p`) mit dem Buchstaben bzw. „0-9“ und eine `ul` mit einem `li` pro Spiel im Format „Titel (Verlag)“; optionale Links im Eintrag zeigen auf Vorstellungs-/Rezensionsartikel und dienen als quellen_url, sonst gilt die Listenseite selbst. """ from __future__ import annotations import re from bs4 import BeautifulSoup from .basis import QuellenAdapter, QuellenTreffer, bild_aus_element TITEL_VERLAG_MUSTER = re.compile(r"^\s*(.+?)\s*\(([^()]*)\)\s*$") class BrettspielboxQuelle(QuellenAdapter): name = "brettspielbox" anzeigename = "Brettspielbox Messevorschau (A–Z)" start_urls = ( "https://brettspielbox.de/brettspiel-neuheiten-spiel-2026-herbst-2026-a-z/", ) def seite_verarbeiten(self, inhalt: bytes, url: str): suppe = BeautifulSoup(inhalt, "html.parser") treffer: list[QuellenTreffer] = [] for spalte in suppe.select(".wp-block-columns"): for liste in spalte.find_all("ul"): for eintrag in liste.find_all("li"): text = eintrag.get_text(" ", strip=True) titel, verlag = _zerlege_eintrag(text) if not titel: continue link = eintrag.find("a", href=True) from urllib.parse import urljoin quellen_url = ( urljoin(url, link["href"]) if link is not None else url ) treffer.append( QuellenTreffer( titel=titel, verlag=verlag, autor=None, erscheinungsdatum_oder_quartal=None, quellen_url=quellen_url, bild_url=bild_aus_element(eintrag, url), ) ) return treffer, [] def _zerlege_eintrag(text: str) -> tuple[str | None, str | None]: """„Titel (Verlag)“ → (Titel, Verlag); ohne Klammer nur Titel.""" fund = TITEL_VERLAG_MUSTER.match(text) if fund is None: return (text.strip() or None), None verlag = fund.group(2).strip() or None titel = fund.group(1).strip() return (titel or None), verlag