gwoe-antragspruefer/docs/reference/adapter-capabilities.md
Dotty Dotter f0f1c39911 Docs: Feld-Mapping-Tabelle pro Adapter + ADR 0005 + Auth-Tests
Adapter-Capabilities-Matrix (#93) erweitert um detailliertes Feld-
Mapping: Pro Adapter welches API-/HTML-/JSON-Feld zu welchem
Drucksache-Feld wird (title, datum, fraktionen, drucksache, link, typ)
mit konkreten Beispielwerten. 12 Adapter-Sektionen.

ADR 0005: Keycloak SSO mit Dev-Bypass — dokumentiert die Entscheidung
für Read/Write-Trennung (GET offen, POST mit JWT) und den Dev-Modus
(Auth deaktiviert wenn KEYCLOAK_URL nicht gesetzt).

Auth-Tests: 7 neue Tests für Token-Extraction, Auth-Enabled-Detection,
_pick_best_title (letztere skipped wenn slowapi nicht installiert).

201 passed, 5 skipped.
2026-04-10 16:29:28 +02:00

12 KiB
Raw Permalink Blame History

Adapter-Capabilities: Vergleichsmatrix

Stand: 2026-04-10. Automatisch aus parlamente.py + bundeslaender.py extrahiert.

Übersicht

16 Bundesländer + Bundestag, alle aktiv.

BL Adapter WP Suche Fuzzy Typ-Filter API
BUND BundestagAdapter 21 Server (DIP REST) + Title-Filter Nein Server (f.drucksachetyp) REST JSON
NRW NRWAdapter 18 Server (HTML-Form) + AND-Filter Nein Server (dokTyp) HTML POST
LSA PortalaAdapter 8 Server (eUI) + Title-Filter Nein Server (ETYPF=Antrag) eUI 2-Step
BE PortalaAdapter 19 Server (eUI, 730d-Fenster) + Title-Filter Nein Client-only eUI 2-Step
BB PortalaAdapter 8 Server (eUI) + Title-Filter Nein Server (ETYPF=Antrag) eUI 2-Step
RP PortalaAdapter 18 Server (eUI) + Title-Filter Nein Server (ETYPF=Antrag) eUI 2-Step
MV ParLDokAdapter 8 Server (ParlDok JSON) + Typ-Filter Nein Client (type=="Antrag") REST JSON
HH ParLDokAdapter 23 Server (ParlDok JSON) + Typ-Filter Nein Client (type=="Antrag") REST JSON
TH ParLDokAdapter 8 Server (ParlDok JSON) + Typ-Filter Nein Client (Substring "Antrag" in type) REST JSON
SH StarFinderCGI 20 Server (CGI, dtyp=antrag) + Title-Filter Nein Server (dtyp) Legacy CGI
HE StarWebHEAdapter 21 Server (eUI, VTDRS) + Title+Typ-Filter Nein Client ("antrag" in typ) eUI 2-Step
HB PARiSHBAdapter 21 Server (PARiS-Servlet) + Typ-Filter Nein (Thesaurus only) Client ("antrag" in typ) HTML POST
BW PARLISAdapter 17 Server (eUI, async Polling) + Title-Filter Nein Server (lines.l4=Antrag) eUI async
BY BayernAdapter 19 Server-Volltext (Solr) + Typ-Filter Ja (Solr) Client (typ=="antrag") HTML Scraping
SL SaarlandAdapter 17 Server-Volltext (Umbraco) + Typ-Filter Umbraco-Relevanz Client (DocumentType) REST JSON
SN SNEdasXmlAdapter 8 Statisch (manueller XML-Export) + Title-Filter Nein N/A XML Import

Such-Architekturen

Volltext-Suche server-seitig

Nur BY (TYPO3-Solr) und SL (Umbraco) bieten echte Volltextsuche über den gesamten Dokumentkorpus. Alle anderen filtern entweder nur den Titel client-seitig oder nutzen eingeschränkte Server-Filter (WP + Datum).

Client-seitige Title-Filterung

Die Mehrheit (portala/eUI, ParlDok, StarFinder, BUND) holt einen breiten Satz von Treffern nach WP/Datum/Typ und filtert dann im Python-Code per all(t in title.lower() for t in query_terms). Das bedeutet:

  • Nur Titel-Matches — Inhalte der Drucksachen werden nicht durchsucht
  • AND-Logik — alle Suchbegriffe müssen im Titel vorkommen
  • Keine Fuzzy-Toleranz — Tippfehler oder Synonym-Drift werden nicht abgefangen
  • Performance ok — max. 1000-1500 Treffer pro Request (via chunksize)

Sonderfälle

BL Besonderheit
SN Kein Scraping möglich (robots.txt); manueller wöchentlicher XML-Export aus EDAS
BE document_type=None weil Berlin's ETYPF andere Values nutzt; 730-Tage-Fenster als Workaround
TH Anträge heißen "Antrag gemäß § 79 GO" → Substring-Match statt Exact-Match; kinds=["Drucksache", "Vorlage"]
BW Async 2-Step mit Search-ID-Polling (2-15 Versuche × 2s Pause), JSON-in-HTML-Comments
HE Perl-Data::Dumper in HTML-Comments, Hex-Escape-Decoding (\x{e9}é)
NI Nicht implementiert — NILAS-StarWeb braucht Session-Cookie, HAR-Capture nötig

Feld-Mapping: Woher kommen die Daten?

Pro Adapter: welches API-Feld wird zu welchem Drucksache-Feld, mit Beispiel.

NRW (NRWAdapter — OPAL HTML)

Feld Quelle Beispiel
title HTML .e-document-result-item__title <a> Text "Kostenloses Parken für E-Fahrzeuge aufheben"
datum <time> Element, DD.MM.YYYY → ISO "07.04.2026" → "2026-04-07"
fraktionen <p> mit "Urheber:" → extract_fraktionen() "Urheber: SPD, GRÜNE" → ["SPD", "GRÜNE"]
drucksache Regex aus href MMD18-12345.pdf → "18/12345" "18/18085"
link https://www.landtag.nrw.de{href} https://www.landtag.nrw.de/.../MMD18-18085.pdf
typ HTML .e-document-result-item__category "Antrag", "Kleine Anfrage"

LSA / BB / RP (PortalaAdapter — eUI Perl-Dump)

Feld Quelle (Perl-Dump-Feld) Beispiel
title WEV06[0].main "Energiewende und Klimaschutz"
datum WEV32[0].main → Regex, DD.MM.YYYY → ISO "01.10.2024" → "2024-10-01"
fraktionen WEV32[0].main Urheber-Text → extract_fraktionen() "CDU, SPD" → ["CDU", "SPD"]
drucksache WEV32[0].main → Regex "8/6645"
link {base_url}{pdf_url_prefix}{WEV32[0].5} https://padoka.landtag.sachsen-anhalt.de/files/drs/8/6645.pdf
typ Fest: "Antrag" (server-side gefiltert via ETYPF) "Antrag"

BE (PortalaAdapter — eUI HTML-Cards)

Feld Quelle (HTML-Element) Beispiel
title <h3 class="h5"> Text "Kinder- und Familienförderung"
datum <h6> Metadata-Zeile → Regex DD.MM.YYYY → ISO "31.03.2026" → "2026-03-31"
fraktionen <h6> Doctype-Zeile → extract_fraktionen() "Antrag CDU, SPD" → ["CDU", "SPD"]
drucksache <h6> → Regex "19/3104"
link <a href="…pdf"> (http→https, relativ→absolut) https://pardok.parlament-berlin.de/...
typ <h6> vor Fraktionsnamen "Antrag", "Vorlage"

MV / HH / TH (ParLDokAdapter — JSON-API)

Feld Quelle (JSON-Feld) Beispiel
title title "Weiterbildungsförderung"
datum date, DD.MM.YYYY → ISO "15.03.2026" → "2026-03-15"
fraktionen authorhtmlextract_fraktionen() "Klaus Meyer (CDU)" → ["CDU"]
drucksache f"{lp}/{number}" lp=8, number=1594 → "8/1594"
link {base_url}{prefix}{link} (Fragment #navpanes=0 gestrippt) https://dokumentation.landtag-mv.de/parldok/dokument/8
typ type (TH: Substring-Match auf "Antrag") "Antrag", "Antrag gemäß § 79 GO"

SH (StarFinderCGIAdapter — Legacy CGI)

Feld Quelle (HTML-Regex) Beispiel
title <b>…</b> in Tabellenzeile "Energiewende vorantreiben"
datum Nach </b>, DD.MM.YYYY → ISO "07.04.2026" → "2026-04-07"
fraktionen Urheber-Text → extract_fraktionen() "Christian Dirschauer (SSW)" → ["SSW"]
drucksache <a> Text "20/5136"
link <a href="…"> direkt http://lissh.lvn.parlanet.de/.../20-5136.pdf
typ Fest: "Antrag" (server-side dtyp=antrag) "Antrag"

HE (StarWebHEAdapter — eUI Perl-Dump)

Feld Quelle (Perl-Dump-Feld) Beispiel
title WEV01[0].main (Hex-Escape-Decoding \x{e9}é) "Schulinfrastruktur modernisieren"
datum WEV02[0].main, DD.MM.YYYY → ISO "29.02.2026" → "2026-02-29"
fraktionen WEV12[0].mainextract_fraktionen() "Klaus Dieter (GRÜNE)" → ["GRÜNE"]
drucksache WEV08[0].main "21/8532"
link WEV07[0].main (http→https) https://starweb.hessen.de/.../21_8532.pdf
typ WEV03[0].main "Antrag", "Antrag mit Änderung"

HB (PARiSHBAdapter — Java-Servlet HTML)

Feld Quelle (HTML-Regex) Beispiel
title <h2><a>…</a></h2> "Bremenpass für Kultur"
datum Nach Drucksache, DD.MM.YYYY → ISO "23.02.2026" → "2026-02-23"
fraktionen Nach Datum → extract_fraktionen() "SPD, BÜNDNIS 90/DIE GRÜNEN, Die Linke" → ["SPD", "GRÜNE", "LINKE"]
drucksache Drs <b>21/730</b> + optionaler Suffix (S/L) "21/730", "21/730S"
link <a href="…pdf" target="new"> https://www.bremische-buergerschaft.de/.../21/730.pdf
typ Regex vor Datum "Antrag", "Änderungsantrag"

BW (PARLISAdapter — eUI async Polling, JSON-in-HTML)

Feld Quelle (Perl/JSON-Feld) Beispiel
title WMV33 (Schlagworte, <i> gestrippt) / Fallback EWBV23 "Energiewirtschaft; Stromversorgung"
datum EWBV23 → Regex DD.MM.YYYY → ISO "16.03.2026" → "2026-03-16"
fraktionen WMV30 (Kurz-Urheber) → extract_fraktionen() "Felix Herkens (GRÜNE) u. a." → ["GRÜNE"]
drucksache EWBV22 oder EWBD01 → Regex "17/10323"
link EWBD05[0].main (direkte PDF-URL) https://parlis.landtag-bw.de/.../17_10323.pdf
typ Fest: document_typ="Antrag" (in lines.l4) "Antrag"

BY (BayernAdapter — TYPO3-Solr HTML)

Feld Quelle (HTML-Regex) Beispiel
title <h5><strong>…</strong></h5> "Kostenloses Parken für E-Fahrzeuge aufheben"
datum <h4> "Drucksache Nr. 19/11407 vom 08.04.2026" DD.MM.YYYY → ISO "08.04.2026" → "2026-04-08"
fraktionen <p> "Antrag AfD" → extract_fraktionen() "Antrag CSU, FREIE WÄHLER" → ["CSU", "FW-BAYERN"]
drucksache <h4> Regex "19/11407"
link <a href="…pdf"> (absolute URL) https://www.bayern.landtag.de/.../0000009107.pdf
typ Erstes Wort aus <p> "Antrag"

SL (SaarlandAdapter — Umbraco JSON)

Feld Quelle (JSON-Feld) Beispiel
title Title "Schule als Lern- und Bildungsort weiter stärken"
datum PublicDate ISO-Format, erste 10 Zeichen "2022-05-12T00:00:00" → "2022-05-12"
fraktionen Publisher + DocumentAuthorextract_fraktionen() Publisher "CDU" → ["CDU"]
drucksache DocumentNumber "17/11"
link FilePath mit /file.ashx/Downloadfile.ashx Rewrite https://www.landtag-saar.de/Downloadfile.ashx?FileId=14230&FileName=Ag17_0011.pdf
typ DocumentType "Antrag", "Anfrage", "Gesetzentwurf"

SN (SNEdasXmlAdapter — Manueller XML-Export)

Feld Quelle (XML-Element) Beispiel
title <Titel> (CDATA) "Geschäftsordnung des Sächsischen Landtags"
datum <Fundstelle> → Regex "datum"-Gruppe, DD.MM.YYYY → ISO "01.10.2024" → "2024-10-01"
fraktionen <Fundstelle> → Regex "urheber"-Gruppe → extract_fraktionen() "CDU, BSW, SPD" → ["CDU", "BSW", "SPD"]
drucksache f"{Wahlperiode}/{Dokumentennummer}" "8/2"
link Konstruiert: .../viewer.aspx?dok_nr={nr}&dok_art=Drs&leg_per={wp} (PDF wird on-demand aus Iframe gelöst) https://edas.landtag.sachsen.de/.../viewer.aspx?dok_nr=2&dok_art=Drs&leg_per=8
typ Fest: "Antrag" "Antrag"

BUND (BundestagAdapter — DIP REST-API)

Feld Quelle (JSON-Feld) Beispiel
title titel "Förderung von Genossenschaften im sozialen Bereich"
datum datum (bereits ISO YYYY-MM-DD) "2026-04-08"
fraktionen urheber[*].titelextract_fraktionen() "Fraktion der AfD" → ["AfD"]
drucksache dokumentnummer "21/5136"
link fundstelle.pdf_url https://dip.bundestag.de/documents/btd/21/051/2105136.pdf
typ drucksachetyp (server-side gefiltert) "Antrag"

Gemeinsames Pattern

Alle Adapter normalisieren Fraktionen über den zentralen parteien.extract_fraktionen(text, bundesland=...) Mapper (#55). Alle konvertieren DE-Datumsformat (DD.MM.YYYY) nach ISO (YYYY-MM-DD), außer BUND (schon ISO) und SL (schon ISO mit T-Suffix).

Historien-Tiefe (ältere WPs)

Alle Adapter sind aktuell auf eine feste Wahlperiode konfiguriert. Keiner unterstützt Queries über mehrere WPs hinweg. Ältere Drucksachen aus früheren WPs sind nicht abrufbar ohne Adapter-Rekonfiguration.

Für eine künftige Multi-WP-Suche müsste pro Adapter geprüft werden, ob das Backend WP-übergreifende Queries unterstützt:

API-Typ Multi-WP möglich?
portala/eUI Ja (WP-Term aus dem JSON-Tree weglassen)
ParlDok Ja (facet_lp weglassen)
StarFinder/PARiS Ja (WP-Param weglassen)
TYPO3-Solr (BY) Ja (wahlperiodeid[] weglassen)
DIP-API (BUND) Ja (f.wahlperiode weglassen)
Umbraco (SL) Ja (Filter.Periods=[])
EDAS-XML (SN) Nur innerhalb des exportierten Datenbestands

Fehlende Adapter

BL Status Blocker
NI (Niedersachsen) Issue #22 offen NILAS-StarWeb erfordert Session-Cookie, HAR-Capture vom User nötig