Wie die AfD die Landesregierung mit Anfragen flutet — und wie man die Anfragen scraped


tl;dr: Wir haben die Kleinen Anfragen der Parlamentarier im Landtag von Baden-Württemberg gescraped und ausgewertet. Die Geschichten und Analysen dazu sind hier zu finden. Die benutzen Scripte dazu gibt es auf meinem Github-Account.


Für unser letztes DDJ-Projekt haben wir uns mit den Kleinen Anfragen im Landtag von Baden-Württemberg beschäftigt. Kleine Anfragen sind ein Kontrollmittel der Parlamentarier, um die Arbeit der Landesregierung abzuklopfen. Die Geschichte ist vor allem deswegen interessant, weil das erste Jahr der laufenden Wahlperiode auch das erste Jahr der AfD im baden-württembergischen Landtag war.

Es gibt ein paar formelle und ein paar informelle Regeln, wie solche Anfragen gestaltet sein sollten. Wir haben das alles unter anderem hier beschrieben. Kurzer Spoiler: Die AfD stellt Anfragen ohne Ende und hält sich an keine informellen Regeln. Aber das nur am Rande.

In diesem Text soll es schließlich nicht um Inhalt oder Analyse der Anfragen gehen, sondern darum, wie man an sie rankommt. Es gibt da zwei Möglichkeiten: Man ruft bei der Parlamentsdokumentation an, bittet um genaue Zahlen und Daten und bekommt eine Absage, weil das ja alles gar nicht möglich und sowieso viel zu aufwändig sei. Oder man besorgt sich die Daten einfach selbst. Schließlich stehen alle Drucksachen des Parlaments, die nicht vertraulich sind und keiner Geheimhaltung unterliegen, frei im Netz.

Bockschlechte Struktur

Das Problem ist nur: Die Seite ist bockschlecht strukturiert. Wer sich alle Kleinen Anfragen des ersten Jahres anzeigen lassen möchte, bekommt erst mal eine Fehlermeldung. Maximal 150 Vorgänge — warum auch immer, es gibt dafür bestimmt total triftige Gründe.

Welche auch immer das sein mögen, es gibt ja noch die Möglichkeit, die Anfragen einfach monatsweise abzufragen. Das macht das scrapen zwar ein bisschen komplizierter, aber das ist bei weitem nicht das größte Problem. Viel schlimmer ist es — zumindest für mich, gute Coder hätten da bestimmt einen eleganten Weg gefunden — dass die Daten nicht in einer ordentlichen Tabelle, sondern nur in vielen Zeilen vorliegen.

So fies sieht die Suche dann aus.

Die verschiedenen Anfragen sind lediglich mit einem Querstrich voneinander getrennt. Zu allem Überfluss werden Name des fragenden MdL, seine Fraktion, das Datum und — ganz wichtig für spätere Datenbanken — die eindeutige Drucksachennummer in einer einzigen Zeile ohne weitere Unterteilung ausgegeben.

Gelöst habe ich das ganze letztlich mit dem Python-Modul Scrapy. Das Script habe ich auf meinem Github-Account hochgeladen, es steht jedem frei zur Verfügung. Bei Benutzung wäre eine bescheidene Nennung des Urhebers aber schön.

Ganz wichtig: Die Parlamentsdokumentation weist am 10.2.2017 einen Datenbankfehler auf. Das Script ignoriert diesen Tag komplett. Die neun Anfragen dieses Tages müssen manuell nachgetragen werden. Außerdem müssen Anfragen, die von mehreren Abgeordneten abgegeben wurden, manuell auseinandergepflückt werden.

Die Funktion des Scripts

Kurz zur Funktion des Scriptes: Der obere Teil dürfte selbsterklärend sein. Man importiert zunächst das Scrapy-Modul, das natürlich vorher per pip3 install scrapy installiert werden muss.

In Zeile 4 kriegt der Crawler zunächst seinen Klassennamen, in diesem Fall AnfragenSpider, in Zeile 5 schließlich seinen eigentlichen Namen, mit dem er via Kommandozeile angesprochen werden kann, in diesem Fall klanfrage. Es folgen die URLs, die ausgelesen werden sollen. Diese können beliebig angepasst werden, wer andere Wahlperioden analysieren will, muss einfach nur zwei Dinge anpassen: Die Wahlperiode WP=16 und natürlich das Startdatum Datvon und das Enddatum Datbis.

Ab Zeile 22 lernt der Crawler schließlich, was er auslesen soll. Er geht die Zeilen der URLs einzeln durch, sucht nach den Begriffen Schlagwort, Betreff und KlAnfr und gibt den Text aus, der danach folgt. Mit dem Kommendozeilen-Befehl scrapy crawl klanfrage -o Kleine_Anfragen.json schreibt das Script alles, was es so findet in eine Json-Datei. Die Bereinigung der mitgelieferten html-Tags und die Trennung der Zeile “Behandlung”, um MdL, Fraktionen, Datum, Drucksache und betreffendes Ministerium auswerten zu können, erfolgt in OpenRefine.

So sieht die ganze Sache in OpenRefine aus

Folgendes war meine Vorgehensweise in OpenRefine

  • html-Tags killen mit Edit cells -> Transform und dem Befehl replace(value,/<\/?\w+((\s+\w+(\s*=\s*(?:”.*?”|’.*?’|[^’”>\s]+))?)+\s*|\s*)\/?>/,’’)
  • Die Spalte mit der Behandlung trennen mit Edit Column -> Split into several columns. Zunächst schneiden wir die Drucksache ab, indem wir nach Drs 16/ trennen, danach destillieren wir die betroffenen Ministerien mit dem Split nach und Antw.
  • Ach ja: Ihre Doktortitel nehmen wir den Damen und Herren auch noch weg, für die interessiert sich nämlich niemand. Das funktioniert per Edit cells -> Transform und dann mit dem Befehl value.replace(“Dr. ”,””)
  • Als nächstes werden per Text filter alle Zeilen gefiltert, die den Ausdruck u.a. enthalten. Denen geben wir mit Edit column -> Add column based on this column eine neue Spalte namens mehrere, die den Wert Ja erhält. Die ganze Chose sieht jetzt so aus:
Jetzt wird es ein bisschen kompliziert…
  • Bei der Kontrolle fällt uns auf, dass wir einen Beitrag ohne Drucksachennummer haben. Es handelt sich um die Anfrage mit dem Betreff Ausschreibung für das Netz 3a auf der Murrbahn, die von Parlamentariern aller Fraktionen außer der AfD gestellt wurde. Die Zeile muss händisch ergänzt werden, sie bekommt ein Ja bei mehrere und die Drucksachennummer 374. Außerdem löschen wir alle MdL bis auf einen aus der Spalte Behandlung und geben am Ende das Datum 27.07.2016 dazu.
  • Jetzt wird es ein bisschen kompliziert, weil wir ein paar MdL umbenennen müssen. Das Ziel ist, danach die komplette Spalte Behandlung einfach bei jedem Leerzeichen zu trennen und dadurch am Ende die Namen der MdL, der Fraktion und des Datums der Anfrage in jeweils einer Spalte zu haben. 
    Das funktioniert aber nur, wenn die Namen keine Doppelnamen enthalten. Also spendieren wir den Abgeordneten Hans Peter Stauch, Arnulf Freiherr von Eyb, Daniel Lede Abal, Lars Patrick Berg ein paar Bindestriche zwischen ihre Vornamen. Stellvertretend funktioniert das via Edit cells -> Transform und dann mit dem Befehl value.replace(“Hans Peter Stauch”,”Hans-Peter Stauch”)
  • Jetzt per Edit Column -> Split into several columns einfach bei jedem Leerzeichen die Spalte trennen. Jetzt können wir allen Spalten auch sinnvolle Bezeichnungen geben, via Edit column -> Rename this column.
  • Jetzt noch die Spalten Vorname und Nachname zusammenfügen. Das geht mit dem Befehl: cells[“Vorname”].value + “ “ + cells[“Nachname”].value, den wir bei Edit column -> Add column based on this column eingeben müssen.
  • Am Ende machen wir die oben beschriebenen Namensänderungen noch Rückgängig und fertig ist der Datensatz, dem aber, um das nochmal zu wiederholen, noch neun Datensätze vom 10.2.2017 fehlen. Die müssen noch händisch nachgetragen werden. Außerdem ist es ratsam, unter Edit cells -> Common transforms etwaige die Weißräume vorne und hinten, sowie doppelte Leerzeichen zu entfernen.

Wem das alles zu kompliziert und/oder zu langwierig ist, kann auch einfach mein Extract benutzen. Auch das steht auf meinem Github-Account zur Verfügung. Die genaue Unterteilung der Anfragen, die von mehreren Parlamentariern gemeinsam gestellt wurden, habe ich händisch in Excel vorgenommen. Das war die eigentliche Si­sy­phus­ar­beit. Aber so ist das halt manchmal im Datenjournalismus.