Scraper BW: Baden-Württemberg (PARLIS, Wahl 2031-03-08) #29

Closed
opened 2026-04-08 22:22:12 +02:00 by tobias · 2 comments
Owner

Wahltermin

2031-03-08 — Baden-Württemberg (BW), aktuell 17. Wahlperiode.

Backend

Feld Wert
Doku-System PARLIS
Base-URL https://parlis.landtag-bw.de
dokukratie-Scraper bw
Drucksachen-Format 17/12345

Adapter-Strategie

PARLIS — eigenständiges System, kein direkter Adapter wiederverwendbar. BWAdapter existiert als Stub in parlamente.py Z. ~833. Vor 2031 noch viel Zeit; vermutlich erst nach dem 18. Landtag (Konstituierung Mai 2026 laut Anmerkung) sinnvoll, weil sich danach die WP ändert.

Was zu tun ist

  1. Live-Backend anschauen — falls SPA, HAR-Trace einer realen Suche aus DevTools ziehen (siehe Vorgehen in #12 für ParlDok bzw. #13 für eUI).
  2. Adapter in webapp/app/parlamente.py implementieren — entweder als neue Subklasse von ParlamentAdapter oder als zweiter Registry-Eintrag eines existierenden parametrisierbaren Adapters.
  3. Eintrag in der ADAPTERS-Registry am Ende der Datei.
  4. Smoke-Test lokal: ADAPTERS["BW"].search("Schule", limit=10) liefert echte Anträge mit Datum + Fraktionen, sortiert newest-first.
  5. Aktivierung via Folge-Issue (siehe Hängt mit … zusammen unten) — dieses Issue ist nur der Adapter selbst, nicht das Indexieren der Wahlprogramme oder das Frontend-aktiv-Setzen.

Akzeptanzkriterien

  • parlamente.py::ADAPTERS["BW"] existiert und ist instanziierbar
  • search(query="Schule", limit=10) liefert ≥3 echte Drucksachen mit korrektem Datum, Fraktionen, PDF-Link
  • get_document(drucksache) für eine reale Drucksache der laufenden WP liefert das Dokument zurück
  • download_text(drucksache) extrahiert Text aus dem PDF
  • Folge-Issue für Frontend-Aktivierung verlinkt
## Wahltermin **2031-03-08** — Baden-Württemberg (BW), aktuell 17. Wahlperiode. ## Backend | Feld | Wert | |---|---| | Doku-System | `PARLIS` | | Base-URL | https://parlis.landtag-bw.de | | dokukratie-Scraper | `bw` | | Drucksachen-Format | `17/12345` | ## Adapter-Strategie PARLIS — eigenständiges System, kein direkter Adapter wiederverwendbar. `BWAdapter` existiert als Stub in `parlamente.py` Z. ~833. Vor 2031 noch viel Zeit; vermutlich erst nach dem 18. Landtag (Konstituierung Mai 2026 laut Anmerkung) sinnvoll, weil sich danach die WP ändert. ## Was zu tun ist 1. Live-Backend anschauen — falls SPA, HAR-Trace einer realen Suche aus DevTools ziehen (siehe Vorgehen in #12 für ParlDok bzw. #13 für eUI). 2. Adapter in `webapp/app/parlamente.py` implementieren — entweder als neue Subklasse von `ParlamentAdapter` oder als zweiter Registry-Eintrag eines existierenden parametrisierbaren Adapters. 3. Eintrag in der `ADAPTERS`-Registry am Ende der Datei. 4. Smoke-Test lokal: `ADAPTERS["BW"].search("Schule", limit=10)` liefert echte Anträge mit Datum + Fraktionen, sortiert newest-first. 5. Aktivierung via Folge-Issue (siehe `Hängt mit … zusammen` unten) — dieses Issue ist nur der Adapter selbst, nicht das Indexieren der Wahlprogramme oder das Frontend-aktiv-Setzen. ## Akzeptanzkriterien - [ ] `parlamente.py::ADAPTERS["BW"]` existiert und ist instanziierbar - [ ] `search(query="Schule", limit=10)` liefert ≥3 echte Drucksachen mit korrektem Datum, Fraktionen, PDF-Link - [ ] `get_document(drucksache)` für eine reale Drucksache der laufenden WP liefert das Dokument zurück - [ ] `download_text(drucksache)` extrahiert Text aus dem PDF - [ ] Folge-Issue für Frontend-Aktivierung verlinkt
Author
Owner

Hinweise aus dokukratie/bw.yml + portala.query.bw.json — PARLIS ist portala-Engine!

Riesige Wiederverwendungs-Möglichkeit: PARLIS auf parlis.landtag-bw.de läuft auf demselben portala/eUI-Framework wie LSA-PADOKA und BE-PARDOK. Der existierende PortalaAdapter aus #2/#3 ist direkt wiederverwendbar.

  • Endpoint: https://parlis.landtag-bw.de/parlis/browse.tt.json
  • Report: https://parlis.landtag-bw.de/parlis/report.tt.html
  • Data Source: "Star" (laut portala.query.bw.json)
  • Format: "suchergebnis-vorgang-full"
  • Sort: "SORT01/D SORT02/D SORT03" (vs. WEVSO1/D WEVSO2 WEVSO3 bei LSA/BE)
  • Search-Lines:
    • l1: legislative_term
    • l2: start_date
    • l3: end_date
    • l4: document_type
  • Items: .//div[contains(@class, "efxRecordRepeater")] — gleicher class-Name wie BE-Cards
  • Title: .//a[@class="efxZoomShort-Vorgang"]
  • Originators: .//dl/dt[contains(text(), "Initiative")]/following-sibling::dd[1]/text()
  • Procedure-ID: .//dl/dt[contains(text(), "Vorgangs-ID")]/following-sibling::dd[1]/text()

Adapter-Patch: Im _build_search_body muss BW eine eigene Variante haben weil lines-Schema (l1/l2/l3/l4) und format/sort anders sind als LSA. Vermutlich am sinnvollsten als optionaler Parameter in PortalaAdapter.__init__ oder als Subklasse PARLISAdapter(PortalaAdapter).

Registry-Eintrag (ungefährer Vorschlag):

"BW": PortalaAdapter(
    bundesland="BW",
    name="Landtag von Baden-Württemberg (PARLIS)",
    base_url="https://parlis.landtag-bw.de",
    db_id="Star",
    wahlperiode=17,
    portala_path="/parlis",
    document_type=None,  # ETYPF-Schema unklar
    pdf_url_prefix="/files/",
    # NEW: Subklasse oder Flag für PARLIS-spezifisches Body-Schema
)

Zeitlicher Kontext: Wahl ist 2031, der 18. Landtag konstituiert sich nach der vorherigen Wahl im März 2026 (aktuell geschäftsführend) — die WP 17 endet bald, 18 fängt an. Vor Implementierung muss bundeslaender.py::BW.wahlperiode aktualisiert werden.

## Hinweise aus dokukratie/bw.yml + portala.query.bw.json — **PARLIS ist portala-Engine!** **Riesige Wiederverwendungs-Möglichkeit:** PARLIS auf `parlis.landtag-bw.de` läuft auf demselben **portala/eUI-Framework** wie LSA-PADOKA und BE-PARDOK. Der existierende `PortalaAdapter` aus #2/#3 ist direkt wiederverwendbar. - Endpoint: `https://parlis.landtag-bw.de/parlis/browse.tt.json` - Report: `https://parlis.landtag-bw.de/parlis/report.tt.html` - Data Source: `"Star"` (laut `portala.query.bw.json`) - Format: `"suchergebnis-vorgang-full"` - Sort: `"SORT01/D SORT02/D SORT03"` (vs. `WEVSO1/D WEVSO2 WEVSO3` bei LSA/BE) - Search-Lines: - `l1`: legislative_term - `l2`: start_date - `l3`: end_date - `l4`: document_type - Items: `.//div[contains(@class, "efxRecordRepeater")]` — gleicher class-Name wie BE-Cards - Title: `.//a[@class="efxZoomShort-Vorgang"]` - Originators: `.//dl/dt[contains(text(), "Initiative")]/following-sibling::dd[1]/text()` - Procedure-ID: `.//dl/dt[contains(text(), "Vorgangs-ID")]/following-sibling::dd[1]/text()` **Adapter-Patch:** Im `_build_search_body` muss BW eine eigene Variante haben weil `lines`-Schema (`l1/l2/l3/l4`) und `format`/`sort` anders sind als LSA. Vermutlich am sinnvollsten als optionaler Parameter in `PortalaAdapter.__init__` oder als Subklasse `PARLISAdapter(PortalaAdapter)`. **Registry-Eintrag (ungefährer Vorschlag):** ```python "BW": PortalaAdapter( bundesland="BW", name="Landtag von Baden-Württemberg (PARLIS)", base_url="https://parlis.landtag-bw.de", db_id="Star", wahlperiode=17, portala_path="/parlis", document_type=None, # ETYPF-Schema unklar pdf_url_prefix="/files/", # NEW: Subklasse oder Flag für PARLIS-spezifisches Body-Schema ) ``` **Zeitlicher Kontext:** Wahl ist 2031, der 18. Landtag konstituiert sich nach der vorherigen Wahl im März 2026 (aktuell geschäftsführend) — die WP 17 endet bald, 18 fängt an. Vor Implementierung muss `bundeslaender.py::BW.wahlperiode` aktualisiert werden.
tobias added the
phase-1
scraper
labels 2026-04-08 23:16:38 +02:00
Author
Owner

Erledigt in db5a875.

Was im Commit ist

Neue Klasse PARLISAdapter (statt PortalaAdapter-Subklasse, weil Body-Schema, Polling und Hit-Format alle anders sind als bei LSA/BE).

Aspekt LSA/BE PortalaAdapter BW PARLISAdapter
Body-Schema lines.2/3/4/10/11/20.x/90.x + parsed + json-Tree minimales lines.l1/l2/l3/l4, kein parsed/json
serverrecordname sr_generic1 vorgang
format generic1-full suchergebnis-vorgang-full
sort WEVSO1/D WEVSO2 WEVSO3 SORT01/D SORT02/D SORT03
sources lsa.lissh / lah.lissh Star
Async nein, report_id sofort ja, polling search_id → report_id
Hit-Format Perl-Dump (LSA) oder HTML-Cards (BE) JSON-in-HTML-Comments

Reverse-Engineering-Quellen

  1. dokukratie/scrapers/portala.query.bw.json für das Body-Skelett
  2. esearch-ui.main.js Z. ~1268 (requestReportOK) für das Polling-Pattern: wenn nur search_id zurückkommt, mit action=SearchAndDisplay, id=<search_id> ohne search-Component re-posten bis report_id da ist
  3. Live-HAR gegen parlis.landtag-bw.de für die Hit-Format-Bestätigung

Smoke-Test

Lokal (im BW-Backend ~17s pro Suche wegen Polling + Server-Latenz):

BW q="":       8 hits, jüngste WP17-Anträge sortiert newest-first
BW q="Schule": 8 hits, alle wirklich Schul-bezogen
BW q="Klima":  8 hits, Klimaschutz/CO2/Energieberatung
get_document(17/10323): roundtrip OK

Live auf https://gwoe.toppyr.de/api/search-landtag?q=Schule&bundesland=BW:

13 Treffer, z.B.:
  17/10160 | 2026-01-19 | [FDP] | Hochschule für Rechtspflege Schwetzingen
  17/10029 | 2025-12-09 | [FDP] | Grundschule; Schwimmbad; Schwimmunterricht
  17/10028 | 2025-12-09 | [SPD] | Ethikunterricht; Grundschule; Lehrerbedarf
  17/10019 | 2025-12-08 | [FDP] | Eingruppierung; Förderunterricht; Grundschule

Akzeptanzkriterien

  • parlamente.py::ADAPTERS["BW"] existiert und ist instanziierbar
  • search(query="Schule", limit=10) liefert ≥3 echte Drucksachen mit korrektem Datum, Fraktionen, PDF-Link
  • get_document(drucksache) für eine reale Drucksache der laufenden WP liefert das Dokument zurück
  • download_text(drucksache) extrahiert Text aus dem PDF (PyMuPDF-Standard, identisch zu MV-Adapter)
  • Folge-Issue #41 für Frontend-Aktivierung verlinkt (BW-Wahlprogramme der WP17)

Phase-1-Status (#49)

  • #29 BW ← dieser Commit
  • #28 HH (ParlDok 8.x verifizieren — vermutlich ParLDokAdapter-Reuse)
  • #25 TH (ParlDok 8.x verifizieren — analog HH)

bundeslaender.py::BW.aktiv=True. Wahlprogramme der WP17 sind noch nicht indexiert (Folge-Issue #41). Aktuell läuft die Bewertung mit den föderalen Grundsatzprogrammen als Fallback — gleicher Status wie BE bis #10 fertig war.

Erledigt in db5a875. ## Was im Commit ist Neue Klasse `PARLISAdapter` (statt PortalaAdapter-Subklasse, weil Body-Schema, Polling und Hit-Format alle anders sind als bei LSA/BE). | Aspekt | LSA/BE PortalaAdapter | BW PARLISAdapter | |---|---|---| | Body-Schema | `lines.2/3/4/10/11/20.x/90.x` + parsed + json-Tree | minimales `lines.l1/l2/l3/l4`, kein parsed/json | | serverrecordname | `sr_generic1` | `vorgang` | | format | `generic1-full` | `suchergebnis-vorgang-full` | | sort | `WEVSO1/D WEVSO2 WEVSO3` | `SORT01/D SORT02/D SORT03` | | sources | `lsa.lissh` / `lah.lissh` | `Star` | | Async | nein, report_id sofort | **ja, polling search_id → report_id** | | Hit-Format | Perl-Dump (LSA) oder HTML-Cards (BE) | **JSON-in-HTML-Comments** | ## Reverse-Engineering-Quellen 1. `dokukratie/scrapers/portala.query.bw.json` für das Body-Skelett 2. `esearch-ui.main.js` Z. ~1268 (`requestReportOK`) für das Polling-Pattern: wenn nur `search_id` zurückkommt, mit `action=SearchAndDisplay, id=<search_id>` ohne search-Component re-posten bis `report_id` da ist 3. Live-HAR gegen `parlis.landtag-bw.de` für die Hit-Format-Bestätigung ## Smoke-Test **Lokal** (im BW-Backend ~17s pro Suche wegen Polling + Server-Latenz): ``` BW q="": 8 hits, jüngste WP17-Anträge sortiert newest-first BW q="Schule": 8 hits, alle wirklich Schul-bezogen BW q="Klima": 8 hits, Klimaschutz/CO2/Energieberatung get_document(17/10323): roundtrip OK ``` **Live** auf https://gwoe.toppyr.de/api/search-landtag?q=Schule&bundesland=BW: ``` 13 Treffer, z.B.: 17/10160 | 2026-01-19 | [FDP] | Hochschule für Rechtspflege Schwetzingen 17/10029 | 2025-12-09 | [FDP] | Grundschule; Schwimmbad; Schwimmunterricht 17/10028 | 2025-12-09 | [SPD] | Ethikunterricht; Grundschule; Lehrerbedarf 17/10019 | 2025-12-08 | [FDP] | Eingruppierung; Förderunterricht; Grundschule ``` ## Akzeptanzkriterien - [x] `parlamente.py::ADAPTERS["BW"]` existiert und ist instanziierbar - [x] `search(query="Schule", limit=10)` liefert ≥3 echte Drucksachen mit korrektem Datum, Fraktionen, PDF-Link - [x] `get_document(drucksache)` für eine reale Drucksache der laufenden WP liefert das Dokument zurück - [x] `download_text(drucksache)` extrahiert Text aus dem PDF (PyMuPDF-Standard, identisch zu MV-Adapter) - [x] Folge-Issue #41 für Frontend-Aktivierung verlinkt (BW-Wahlprogramme der WP17) ## Phase-1-Status (#49) - [x] **#29 BW** ← dieser Commit - [ ] #28 HH (ParlDok 8.x verifizieren — vermutlich ParLDokAdapter-Reuse) - [ ] #25 TH (ParlDok 8.x verifizieren — analog HH) `bundeslaender.py::BW.aktiv=True`. Wahlprogramme der WP17 sind noch nicht indexiert (Folge-Issue #41). Aktuell läuft die Bewertung mit den föderalen Grundsatzprogrammen als Fallback — gleicher Status wie BE bis #10 fertig war.
Sign in to join this conversation.
No description provided.