Vierter produktiver Plenarprotokoll-Parser nach NRW + BUND + BE.
Hamburg publiziert kompakte Beschlussprotokolle (Tabellen-Form mit
Vote-Block pro Beschluss):
... mehrheitlich mit den Stimmen der SPD und GRUENEN gegen die
Stimmen der CDU und AfD bei Enthaltung der Linken angenommen
Pattern:
- einstimmig (angenommen|abgelehnt) — alle Fraktionen
- mehrheitlich mit den Stimmen X gegen die Stimmen Y bei Enthaltung Z
(angenommen|abgelehnt)
Fraktions-Mapping WP23: SPD, GRUENE, CDU, AfD, Linke
URL-Discovery laeuft ueber die Protokoll-Liste der Buergerschaft
(Blob-IDs via Index-Page-Scrape). Cron-Eintrag erst sobald
URL-Discovery-Skript hier integriert ist.
Stub-Test angepasst (HH raus aus STUB_BL_CODES).
Dritter vollwertiger Plenarprotokoll-Parser nach NRW + BUND.
URL-Pattern verifiziert (WP19 Sitzungen 1, 10, 50, 80, 100):
https://www.parlament-berlin.de/ados/{wp}/IIIPlen/protokoll/plen{wp}-{n:03}-pp.pdf
Anchor-Sprache (NRW-aehnlich, mit Berliner-Eigenheit 'pro forma'):
Wer den Antrag auf Drucksache 19/X annehmen moechte, ... – Das sind
die Fraktionen Buendnis 90/Die Gruenen und Die Linke.
Wer stimmt dagegen? – Das sind die Fraktionen der CDU, SPD und AfD.
Wer enthaelt sich, pro forma? – Das ist niemand.
Damit ist der Antrag abgelehnt.
Pattern:
- Result-Anchor: Damit ist [Antrag/Aenderungsantrag/Gesetzentwurf/...]
(angenommen|abgelehnt)
- Vote-Block: 3 Q+A-Paare im Reden-Stil (annehmen moechte / dagegen /
enthaelt sich)
- Drucksachen-Lookup: 'Drucksache 19/N(-suffix)' rueckwaerts (1500-char Fenster)
Fraktions-Mapping WP19:
- Buendnis 90/Die Gruenen → GRÜNE
- Die Linke → LINKE
- CDU, SPD, AfD, FDP
21 Tests in test_protokoll_parsers_be.py.
Cron-PROTO_TARGETS erweitert um BE WP19 (~80 Sitzungen).
Stub-Test angepasst.
905 Tests gruen (889 → 905, +16 fuer BE).
Vertiefte Probe (WP17 Sitzung 50): BW stimmt 'pro Artikel'
('Damit ist Artikel 1 einstimmig zugestimmt'), nicht pro Drucksache.
Das ist andere Datenmodellierung als NRW (Drucksache→Vote) und BUND
(Beschlussempfehlung→Vote). Ein BW-Parser braucht entweder:
- Aggregations-Heuristik: alle Artikel angenommen → DS angenommen
- Schema-Erweiterung um 'artikel'-Spalte fuer per-Artikel-Records
Implementer muss vor Start mit Maintainer abstimmen, welcher Weg
gegangen wird. BW bleibt Stub bis Designwahl getroffen ist.
Erste Probe (Sitzung 184) war Aussprache, daher 0 Beschluss-Anchors.
Sitzung 30 (572k chars, 5 angenommen-Anchors) zeigt die echte
BT-Vote-Sprache:
'Die Beschlussempfehlung ist mit den Stimmen der Koalitions-
fraktionen und der Fraktion Die Linke gegen die Stimmen der
CDU/CSU-Fraktion bei Enthaltung der AfD-Fraktion angenommen.'
Pattern-Erkennung:
- Anchor-Verb 'angenommen' oder 'abgelehnt' am Satzende
- Vote-Block: 'mit den Stimmen [...] gegen die Stimmen [...]
bei Enthaltung [...]'
- Fraktions-Phrasen: 'Fraktion X', 'X-Fraktion', 'Koalitionsfraktionen'
- Drucksachen rueckwaerts vom Anchor (oft 100+ Zeichen vorher)
Wichtig: BT-Anchor-Sprache ist viel laenger als NRW — Regex-Begrenzung
muss 200+ Zeichen tolerieren.
Sample-Sitzungen mit Beschluessen: WP20 30, 100, 150.
Heutige Probe von WP17 Sitzung 50 (618 KB PDF) ergab:
URL-Pattern bestaetigt:
https://www.landtag-bw.de/.../WP{wp}/Plp/{wp}_{n:04}.pdf
4-stellige Sitzungs-Nr mit Padding (anders als NRW unkpaddet)
Anchor-Phrasen-Stichprobe:
'einstimmig zugestimmt' x5 — Haupt-Anchor (NRW: 'angenommen')
'Damit ist [...] einstimmig' x2 — NRW-aehnliche Struktur
'angenommen' x1 — nur in einer Rede, KEIN Beschluss-Anchor!
'Drucksache 17/N' x35 — DS-Pattern wie NRW
'zugestimmt' x19 — dominierende Vote-Phrase
Fraktions-Auflistung pro Vote in BW deutlich weniger detailliert als
NRW — Parser wird oft nur 'einstimmig' / 'mit Mehrheit' extrahieren
koennen, kein ja/nein/enthaltung-Breakdown pro Fraktion.
Fuer den naechsten Implementer (BW-Session) wertvolle Vorarbeit.
Pro BL (BUND + 15 Laender) ein Modul app/protokoll_parsers/<bl>.py mit:
- Recherche-Findings im Docstring (Doku-System, Base-URL, Format,
URL-Discovery-Status, Familie, Aufwand-Schaetzung)
- parse_protocol() raised NotImplementedError mit Hinweis auf Issue-Tracker
- *Nicht* in PROTOKOLL_PARSERS-Registry → Auto-Ingest-Cron uebersieht sie
Tracking-Issues #148-#163 auf Gitea, jeweils mit den Recherche-Findings
und einer Checkliste fuer die Implementer-Session.
Roadmap-Doc (docs/protokoll-parser-roadmap.md) aktualisiert mit
Stub→Issue-Mapping-Tabelle.
Wenn der Implementer pro BL fertig ist:
1. NotImplementedError durch echten Parser ersetzen
2. Eintrag in app/protokoll_parsers/__init__.py::PROTOKOLL_PARSERS
3. PROTO_TARGETS in scripts/auto-ingest-protocols.sh ergaenzen
787 Tests gruen, NRW unveraendert.
Architektur-Refactor zur Vorbereitung BL-uebergreifender Parser:
- app/protokoll_parser_nrw.py → app/protokoll_parsers/nrw.py
- app/ingest_votes_nrw.py → app/ingest_votes.py (BL-uebergreifend)
- Neue app/protokoll_parsers/__init__.py mit:
- PROTOKOLL_PARSERS-Dict (BL-Code → Parser-Funktion, derzeit nur NRW)
- parse_protocol(bundesland, pdf_path) als BL-uebergreifender Einstieg
- supported_bundeslaender()-Helper
- NotImplementedError mit hilfreicher Message bei unbekanntem BL
CLI bekommt --supported-Flag fuer BL-Discovery:
python -m app.ingest_votes --supported → 'NRW'
ADR 0009 dokumentiert das Muster (Sub-Package + Funktions-Registry,
analog zu ADR 0002 fuer ParlamentAdapter). Folge-BL bekommen je
eine eigene Datei und einen Eintrag in PROTOKOLL_PARSERS — kein
Refactoring der Bestands-Logik.
Tests:
- 7 neue Tests in test_protokoll_parsers.py fuer Registry und Dispatch
- Bestehende NRW-Tests umbenannt zu test_protokoll_parsers_nrw.py,
Imports angepasst — keine Verhaltens-Aenderung
- Bestehende Ingest-Tests umbenannt zu test_ingest_votes.py
642 Tests gruen, kein Verhaltens-Drift.