Saarland publiziert keine Wortprotokolle, sondern eigene HTML-Seiten
mit strukturierten Abstimmungsergebnissen pro Sitzung:
<p>Drucksache 17/2076 ... in Erster Lesung mit Stimmenmehrheit
angenommen ... [SPD: dafür; CDU und AfD: dagegen]</p>
Daher Input ist HTML, nicht PDF. Parser nutzt LI-Block-Iteration und
extrahiert pro Block:
- Drucksache aus "Drucksache N/M"
- Status aus "(einstimmig|mit Stimmenmehrheit)? (angenommen|abgelehnt)"
- Vote-Block aus "[SPD: dafür; CDU: dagegen; AfD: Enthaltung]"
- einstimmig=True falls Status enthaelt "einstimmig"
Vote-Bracket-Parser (eigenstaendig vs. Reden-Stil-Parser anderer BL):
- Splits per ; → "Phrase: Status"
- Phrase per Wortgrenzen-Regex auf {SPD,CDU,AfD} matchen
- Status-Map: dafür→ja, dagegen→nein, Enthaltung→enthaltung
URL-Pattern (nicht direkt vorhersagbar wegen Datums-Slug):
https://www.landtag-saar.de/aktuelles/mitteilungen/abstimmungsergebnisse-der-{n}-landtagssitzung-vom-{datum}/
Auto-Ingest via Index-Scrape (analog HH/HE/SH):
- /aktuelles/mitteilungen/ scrape
- WP16-URLs (mit "wahlperiode-vom") ueberspringen
- Pro neue Sitzung: HTML herunterladen, ingest_pdf-API auf .html-Datei
Tests: 18 SL-Tests (Verifikation Sitzung 46 → 18 Votes mit korrekten
JA/NEIN/ENTH-Listen). Stand: 9 produktive Parser
(NRW, BUND, BE, HH, TH, HE, SH, HB, SL).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.5 KiB
Plenarprotokoll-Parser Roadmap pro Bundesland
Stand 2026-04-28. Architektur fertig (ADR 0009), NRW-Parser produktiv,
Cron-Infrastruktur (scripts/auto-ingest-protocols.sh) BL-erweiterbar.
Pro weiterem BL ist ein eigener Parser zu implementieren — das ist
deterministische Reverse-Engineering-Arbeit, keine LLM-Calls, keine Kosten.
Stub-Module + Folge-Issues
Pro BL ein Modul app/protokoll_parsers/<bl>.py mit Recherche-Findings
im Docstring und NotImplementedError als Body. Stubs sind nicht
in PROTOKOLL_PARSERS registriert — der Auto-Ingest-Cron ueberspringt
sie. Sobald ein Parser implementiert ist, verschwindet der NotImplementedError-
Body und der Eintrag wird in PROTOKOLL_PARSERS ergaenzt.
| BL | Modul | Tracking-Issue | Status |
|---|---|---|---|
| NRW | nrw.py |
(#106) | ✅ produktiv (2700+ Votes, 217+ Protokolle WP17+WP18) |
| BUND | bund.py |
#148 | ✅ produktiv (112 Votes, 39 Protokolle WP20) |
| BE | be.py |
#150 | ✅ produktiv (200 Votes, 63 Protokolle WP19) |
| HH | hh.py |
#155 | ✅ produktiv (18+ Votes WP23, Cron via Index-Scrape) |
| BB | bb.py |
#149 | 📋 Stub (Portala 403 ohne Cookie-Session) |
| BW | bw.py |
#151 | ⚠ Stub (Datenmodell-Inkompatibilitaet) |
| BY | by.py |
#152 | 📋 Stub |
| HB | hb.py |
#153 | ✅ produktiv (Status-Only, 402 Votes 33 Protokolle WP21 Land, URL-Pattern direkt) |
| HE | he.py |
#154 | ✅ produktiv (Status-Only, 794 Votes 58 Protokolle WP21, Index-Scrape) |
| LSA | lsa.py |
#156 | 📋 Stub (padoka SPA, JS-rendered) |
| MV | mv.py |
#157 | 📋 Stub (ParlDok SPA) |
| NI | ni.py |
#158 | 📋 Stub (NILAS Login) |
| RP | rp.py |
#159 | 📋 Stub (OPAL extern, kein direktes URL-Pattern) |
| SH | sh.py |
#160 | ✅ produktiv (575 Votes 110 Protokolle WP20, Index-Scrape) |
| SL | sl.py |
#161 | ✅ produktiv (HTML-Abstimmungsergebnisse, WP17, Index-Scrape) |
| SN | sn.py |
#162 | 📋 Stub (XML-Manuell-Export) |
| TH | th.py |
#163 | ✅ produktiv (459 Votes 96 Protokolle WP8, URL-Pattern) |
Pattern fuer neue BL
- Sample-PDF/HTML/XML besorgen und Vote-Anchor-Phrasen identifizieren.
app/protokoll_parsers/<bl>.pyanlegen mitparse_protocol(path) -> list[dict]nach Vertrag aus ADR 0009.- Eintrag in
PROTOKOLL_PARSERS(in__init__.py). - Tests in
tests/test_protokoll_parsers_<bl>.py. PROTO_TARGETSinscripts/auto-ingest-protocols.shergaenzen.- Backfill einmal manuell laufen lassen.
Pro Bundesland: bekannter Stand
NRW ✅ produktiv
- URL:
https://www.landtag.nrw.de/portal/WWW/dokumentenarchiv/Dokument/MMP{wp}-{n}.pdf - Format: PDF mit deterministischen Anchor-Phrasen ("Damit ist X angenommen/abgelehnt")
- Parser:
app/protokoll_parsers/nrw.py - Tests: 38 Tests, Fixture-Garantie 19/19 auf MMP18-119
Bundestag (BUND) — anderer Vote-Sprache als NRW
- URL:
https://dserver.bundestag.de/btp/{wp}/{wp}{n:03}.pdf(z.B.20184= WP20 Sitzung 184) - Format: PDF, ~1 MB pro Sitzung, ~600k Zeichen Text.
- Vote-Anchor-Phrasen unterscheiden sich von NRW:
- Bundestag nutzt: „Wer dem Gesetzentwurf seine Zustimmung gibt, den bitte ich, sich zu erheben", „Damit ist der Gesetzentwurf in zweiter Beratung angenommen", „... mit den Stimmen der Koalition gegen die Stimmen der Opposition abgelehnt"
- „angenommen" und „überwiesen" haeufig in „in zweiter Beratung angenommen" oder „zur federführenden Beratung an den Ausschuss"
- Vote-Daten: bei „namentliche Abstimmung" als separate XML-Datei
unter
https://dserver.bundestag.de/.../btp{wp}-{n}-namentlich.xml(alternative datenquelle, strukturiert!) - Empfehlung: Statt PDF-Parsen den XML-Endpoint fuer namentliche Abstimmungen nutzen — dort liegt fraktions-aggregiertes Vote bereits als Struktur vor.
- Aufwand: ~1-2 Tage
MV — ParlDok 8.x SPA
- URL-Pattern:
https://www.dokumentation.landtag-mv.de/parldok/dokument/{id}/{slug}.pdf - Format: PDF, aber
{id}ist nicht-vorhersagbar — braucht Listen-API von ParlDok-Suche - Workaround: Suche via Plenarprotokoll-Filter, Liste der IDs holen
- Aufwand: ~2 Tage (URL-Discovery + Parser-Bau)
Bayern (BY) — Pfad-Pattern noch zu verifizieren
- Format: PDF
- URL aus dokukratie-yml ziehen (nicht direkt dokumentiert)
- Aufwand: ~2 Tage
Brandenburg (BB)
- URL-Pattern:
https://www.landtag.brandenburg.de/...mit eigenem Schema - Format: PDF mit Vote-Tabellen
- Aufwand: ~2-3 Tage (Tabellen-Parsing aufwendiger als reine Text-Anchors)
Berlin (BE)
- Pardok-Plattform (analog LSA, BE)
- URL via Search-API
- Aufwand: ~2 Tage
Bremen (HB), Hamburg (HH), Saarland (SL)
- Stadtstaaten, kleinere Landtage
- Format-Recherche pro Stadt; oft PDFs mit weniger formalen Anchors
- Aufwand: je ~1-2 Tage
Hessen (HE)
- Webseiten-Plenarprotokolle z.T. als HTML strukturiert (semantische Tags pro Beschluss)
- Wenn HTML zugaenglich: einfacher als PDF
- Sample-URL muss recherchiert werden
- Aufwand: ~1-2 Tage
Niedersachsen (NI)
- nilas-Portal Login-protected (siehe
feedback_silent_excepts.md) - Plenarprotokolle ggf. auf eigener Seite ohne Login
- Aufwand: ~2-3 Tage (Login-Workaround pruefen)
Rheinland-Pfalz (RP)
- OPAL_extern, abweichend zu NRW-OPAL
- PDF-URLs dokumentiert in dokukratie-yml
- Aufwand: ~2 Tage
Sachsen (SN)
- ASP.NET-Webforms — Postback-Handling fuer Suche noetig
- Plenarprotokoll-Liste via XML-Export
- Synergie mit bestehendem
app/sn_xml_export-Workflow moeglich - Aufwand: ~1-2 Tage
Sachsen-Anhalt (LSA)
- Padoka-Plattform (analog BE)
- URL via Search-API
- Aufwand: ~2 Tage
Schleswig-Holstein (SH)
- Starfinder-CGI-Backend
- Format: PDF
- Aufwand: ~2 Tage
Thüringen (TH)
- ParlDok-Plattform (analog MV)
- Synergien mit MV-Parser hoch
- Aufwand: ~1-2 Tage (nach MV)
Baden-Württemberg (BW)
- PARLIS-Eigensystem
- Format: PDF
- Aufwand: ~2 Tage
Implementations-Reihenfolge nach Aufwand-Nutzen
- MV + TH parallel (gleiche ParlDok-Plattform, Synergien)
- BUND (XML-Endpoint!) — strukturierte Daten leichter als PDF-Parser
- HE wenn HTML-Plenarprotokolle existieren
- Rest nach Bedarf
Cron-Erweiterung pro neuem BL
In scripts/auto-ingest-protocols.sh einen PROTO_TARGETS-Eintrag
ergaenzen:
PROTO_TARGETS=(
"NRW|18|https://www.landtag.nrw.de/.../MMP18-{n}.pdf"
"BUND|20|https://dserver.bundestag.de/btp/20/20{n:03}.pdf"
...
)
Format-Spec: BL_CODE|WAHLPERIODE|URL_MIT_{n}_PLACEHOLDER. Das Skript
erkennt automatisch das letzte ingestete Protokoll dieses BL/WP und
inkrementiert.