Scraper SH: Schleswig-Holstein (StarWeb, Wahl 2027-04-18) #20

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

Wahltermin

2027-04-18 — Schleswig-Holstein (SH), aktuell 20. Wahlperiode.

Backend

Feld Wert
Doku-System StarWeb
Base-URL https://www.landtag.ltsh.de
dokukratie-Scraper sh
Drucksachen-Format 20/1234

Adapter-Strategie

StarWeb (1/6) — die anderen StarWeb-Bundesländer sind NI, HE, TH, BB, RP. Wenn das SH-Issue zuerst angegangen wird, soll der Adapter als generischer StarWebAdapter mit Konstruktor-Parametern (base_url, wahlperiode, drucksache_format, db_id) entstehen, sodass die anderen 5 Bundesländer nur einen Registry-Eintrag brauchen — analog zur PortalaAdapter-Wiederverwendung für LSA+BE.

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["SH"].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["SH"] 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 **2027-04-18** — Schleswig-Holstein (SH), aktuell 20. Wahlperiode. ## Backend | Feld | Wert | |---|---| | Doku-System | `StarWeb` | | Base-URL | https://www.landtag.ltsh.de | | dokukratie-Scraper | `sh` | | Drucksachen-Format | `20/1234` | ## Adapter-Strategie **StarWeb (1/6)** — die anderen StarWeb-Bundesländer sind NI, HE, TH, BB, RP. Wenn das SH-Issue zuerst angegangen wird, soll der Adapter als generischer **StarWebAdapter** mit Konstruktor-Parametern (`base_url`, `wahlperiode`, `drucksache_format`, `db_id`) entstehen, sodass die anderen 5 Bundesländer nur einen Registry-Eintrag brauchen — analog zur PortalaAdapter-Wiederverwendung für LSA+BE. ## 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["SH"].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["SH"]` 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/sh.yml

Backend ist alte Starfinder-CGI (anders als die anderen 5 StarWeb-Bundesländer!):

  • Suchendpoint: http://lissh.lvn.parlanet.de/cgi-bin/starfinder/0?path=lisshfl.txt&id=FASTLINK&pass=&search=WP%3d{wp}+AND+dtyp%3dkleine&format=WEBKURZFL
  • Query-Sprache: WP=20 AND dtyp=kleine (URL-encoded), Format WEBKURZFL
  • Response: HTML-Tabelle, kein moderner JSON-API
  • Items: .//table[@class='tabcol']//tr
  • Title: .//td[2]/b/text()
  • Drucksache + Datum aus Metadata-<td>-Block via Regex:
    Kleine\s+Anfrage\s+(?P<originators_raw>.*)\s+und\s+Antwort\s+(?P<answerers>.*)\s+(?P<published_at>\d{2}\.\d{2}\.\d{4})?\s*Drucksache\s+(?P<reference>\d{1,2}\/\d+)
    

Synergie-Korrektur: SH ist NICHT die richtige StarWeb-Vorlage, weil es nicht das moderne servlet.starweb?path=...&__action=N-Schema nutzt. Die anderen 5 StarWeb-BL (BB, HE, NI, RP, HB) haben das modernere Servlet — also lieber #27 BB als StarWeb-Template nehmen, nicht SH. SH bekommt einen eigenständigen StarFinderCGIAdapter.

## Hinweise aus dokukratie/sh.yml **Backend ist alte Starfinder-CGI** (anders als die anderen 5 StarWeb-Bundesländer!): - Suchendpoint: `http://lissh.lvn.parlanet.de/cgi-bin/starfinder/0?path=lisshfl.txt&id=FASTLINK&pass=&search=WP%3d{wp}+AND+dtyp%3dkleine&format=WEBKURZFL` - Query-Sprache: `WP=20 AND dtyp=kleine` (URL-encoded), Format `WEBKURZFL` - Response: HTML-Tabelle, kein moderner JSON-API - Items: `.//table[@class='tabcol']//tr` - Title: `.//td[2]/b/text()` - Drucksache + Datum aus Metadata-`<td>`-Block via Regex: ``` Kleine\s+Anfrage\s+(?P<originators_raw>.*)\s+und\s+Antwort\s+(?P<answerers>.*)\s+(?P<published_at>\d{2}\.\d{2}\.\d{4})?\s*Drucksache\s+(?P<reference>\d{1,2}\/\d+) ``` **Synergie-Korrektur:** SH ist NICHT die richtige StarWeb-Vorlage, weil es nicht das moderne `servlet.starweb?path=...&__action=N`-Schema nutzt. Die anderen 5 StarWeb-BL (BB, HE, NI, RP, HB) haben das modernere Servlet — also lieber **#27 BB als StarWeb-Template** nehmen, nicht SH. SH bekommt einen eigenständigen `StarFinderCGIAdapter`.
tobias added the
phase-2
scraper
labels 2026-04-08 23:16:35 +02:00
Author
Owner

Erledigt in f82c60e.

SH läuft auf der ältesten der vier Backend-Familien: Starfinder-CGI auf lissh.lvn.parlanet.de. Im Gegensatz zum modernen StarWeb-Servlet (BB/HE/NI/RP/HB) ist es URL-basiert und stateless — eine GET-Anfrage genügt, kein mehrstufiges Form-POST. Eigener Adapter StarFinderCGIAdapter (analog zu PARLISAdapter aus #29 — eigenständige Klasse statt Subklasse, weil Schema fundamental anders).

Endpoint

http://lissh.lvn.parlanet.de/cgi-bin/starfinder/0
  ?path=lisshfl.txt&id=FASTLINK&pass=&search=WP=20+AND+dtyp=antrag
  &format=WEBKURZFL

Hit-Format

Pro <tr class="tabcol|tabcol2|tabcol3">:

<b>{TITLE}</b><br>
Antrag {URHEBER} {DD.MM.YYYY} Drucksache <a href="{PDF}">{N/M}</a>

Edge-Cases

  • Encoding: Server liefert ISO-8859-1 ohne korrektes Content-Type-Header. Adapter dekodiert resp.content explizit als latin-1.
  • SSW-Detection: SH ist das einzige BL mit SSW-Fraktion (befreit von der 5%-Hürde), Pattern \bSSW\b analog zu \bAfD\b.
  • Free-Text-Suche: client-seitig (siehe #18). Server-side (term)-Syntax im starfinder-search-Param wird vom Server nicht als Volltext interpretiert.

Smoke-Test

Lokal:

SH q="":         8 hits in 14.4s
SH q="Schule":   8 hits (Schulentwicklung Westküste, Hochschulen, queere Vielfalt)
SH q="Klima":    8 hits (klimafreundlich, Klimafolgen, Aktionsplan)
SH q="Bildung":  8 hits (berufliche Bildung, Holocaust-Wissen)

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

20 Treffer, z.B.:
  20/4281 | 2026-03-24 | [SPD] | Für eine gute Schulentwicklung an der Westküste
  20/4222 | 2026-03-06 | [SPD] | Mündlicher Bericht zur Lage an den Hochschulen
  20/4106 | 2026-02-13 | [SPD] | Sensibilität für queere Vielfalt an Schule fördern
  20/3682 | 2025-10-08 | [SSW] | Tarifvertrag für studentische Beschäftigte

Akzeptanzkriterien

  • parlamente.py::ADAPTERS["SH"] existiert und ist instanziierbar
  • search(query="Schule", limit=10) liefert echte Drucksachen mit korrektem Datum, Fraktionen, PDF-Link
  • get_document(drucksache) funktioniert
  • download_text(drucksache) funktioniert
  • Folge-Issue #32 für Frontend-Aktivierung verlinkt

Phase-2-Status (#49)

  • #27 BB als StarWebAdapter-Template — deferred: das StarWeb-Servlet (BB/HE/NI/RP/HB) ist mehrstufig und stateful, Form-Submit braucht das genaue __action-Code-Pattern, das ohne HAR-Trace nicht klar reverse-engineerbar war (Probing mit 74/112/201/78/75/76/108 lieferte 500/leer)
  • #20 SH (f82c60e) ← dieser Commit — Starfinder-CGI ist eigenständig und URL-basiert
  • #21 HB, #22 NI, #24 HE, #30 RP — alle blocken auf #27 BB-Template

Empfehlung: vor #27 BB einen HAR-Trace gegen die Live-Form auf parlamentsdokumentation.brandenburg.de ziehen (analog zu PARLIS in #29). Dann ist der StarWebAdapter ein 4-Stunden-Job; ohne HAR mehrere Tage Trial-and-Error.

Erledigt in f82c60e. SH läuft auf der ältesten der vier Backend-Familien: Starfinder-CGI auf `lissh.lvn.parlanet.de`. Im Gegensatz zum modernen StarWeb-Servlet (BB/HE/NI/RP/HB) ist es URL-basiert und stateless — eine GET-Anfrage genügt, kein mehrstufiges Form-POST. Eigener Adapter `StarFinderCGIAdapter` (analog zu PARLISAdapter aus #29 — eigenständige Klasse statt Subklasse, weil Schema fundamental anders). ## Endpoint ``` http://lissh.lvn.parlanet.de/cgi-bin/starfinder/0 ?path=lisshfl.txt&id=FASTLINK&pass=&search=WP=20+AND+dtyp=antrag &format=WEBKURZFL ``` ## Hit-Format Pro `<tr class="tabcol|tabcol2|tabcol3">`: ```html <b>{TITLE}</b><br> Antrag {URHEBER} {DD.MM.YYYY} Drucksache <a href="{PDF}">{N/M}</a> ``` ## Edge-Cases - **Encoding**: Server liefert ISO-8859-1 ohne korrektes Content-Type-Header. Adapter dekodiert `resp.content` explizit als `latin-1`. - **SSW-Detection**: SH ist das einzige BL mit SSW-Fraktion (befreit von der 5%-Hürde), Pattern `\bSSW\b` analog zu `\bAfD\b`. - **Free-Text-Suche**: client-seitig (siehe #18). Server-side `(term)`-Syntax im starfinder-search-Param wird vom Server nicht als Volltext interpretiert. ## Smoke-Test **Lokal:** ``` SH q="": 8 hits in 14.4s SH q="Schule": 8 hits (Schulentwicklung Westküste, Hochschulen, queere Vielfalt) SH q="Klima": 8 hits (klimafreundlich, Klimafolgen, Aktionsplan) SH q="Bildung": 8 hits (berufliche Bildung, Holocaust-Wissen) ``` **Live** auf https://gwoe.toppyr.de/api/search-landtag?q=Schule&bundesland=SH: ``` 20 Treffer, z.B.: 20/4281 | 2026-03-24 | [SPD] | Für eine gute Schulentwicklung an der Westküste 20/4222 | 2026-03-06 | [SPD] | Mündlicher Bericht zur Lage an den Hochschulen 20/4106 | 2026-02-13 | [SPD] | Sensibilität für queere Vielfalt an Schule fördern 20/3682 | 2025-10-08 | [SSW] | Tarifvertrag für studentische Beschäftigte ``` ## Akzeptanzkriterien - [x] `parlamente.py::ADAPTERS["SH"]` existiert und ist instanziierbar - [x] `search(query="Schule", limit=10)` liefert echte Drucksachen mit korrektem Datum, Fraktionen, PDF-Link - [x] `get_document(drucksache)` funktioniert - [x] `download_text(drucksache)` funktioniert - [x] Folge-Issue #32 für Frontend-Aktivierung verlinkt ## Phase-2-Status (#49) - [ ] **#27 BB** als StarWebAdapter-Template — **deferred**: das StarWeb-Servlet (BB/HE/NI/RP/HB) ist mehrstufig und stateful, Form-Submit braucht das genaue `__action`-Code-Pattern, das ohne HAR-Trace nicht klar reverse-engineerbar war (Probing mit 74/112/201/78/75/76/108 lieferte 500/leer) - [x] **#20 SH** (f82c60e) ← dieser Commit — Starfinder-CGI ist eigenständig und URL-basiert - [ ] #21 HB, #22 NI, #24 HE, #30 RP — alle blocken auf #27 BB-Template **Empfehlung:** vor #27 BB einen HAR-Trace gegen die Live-Form auf `parlamentsdokumentation.brandenburg.de` ziehen (analog zu PARLIS in #29). Dann ist der StarWebAdapter ein 4-Stunden-Job; ohne HAR mehrere Tage Trial-and-Error.
Sign in to join this conversation.
No description provided.