Als de data niet open is

Alle gegevens over de stemmingen in de Tweede Kamer zijn online beschikbaar. Maar dat maakt het nog niet tot open data. Hoe verzamel je dan die data om er toch iets mee te kunnen doen?

maandag 30 mei 2016 | Parlement, opendata

Het script draaide 12 uur om alles op te halen

Er zijn nu twee officiële wegen om de stemmingen in te zien. De eerste is via de site officiële bekendmakingen. Daar zijn alle handelingen op te vragen waarin de stemmingen opgenomen zijn. Dat is de meest omslachtige weg. De tweede weg loopt via de site van de Tweede Kamer zelf. Daarop staan alle stemmingen geordend naar dossier per stemmingsdag. En dan kan je per pagina de individuele stemmingen openen.

Maar wil je meer dan een individuele stemming bekijken, moet je een behoorlijke inspanning leveren om alle data bij elkaar te sprokkelen. Hier een beknopt verslag met een knipoog. Vooral om duidelijk te maken dat het toch echt de hoogste tijd is dat deze data echt open en gestructureerd aangeboden wordt.

Goed, we hebben dus de webpagina's met stemmingen op de site van de Tweede Kamer. Een eerste stap is het verzamelen van alle stemmingen. We zijn geïnteresseerd in alles vanaf 2013. Er is geen API. Dus het is niet mogelijk om de pagina's of data met 1 duidelijke opdracht op te halen.
De eerste stap die we zetten is een paar zoekopdrachten geven en kijken hoe de resultaten er uit zien. Dan blijkt al snel dat alle stemmingen in een document zitten waar de URL als volgt is opgebouwd:
https://www.tweedekamer.nl/kamerstukken/stemmingsuitslagen/detail?id=yyyyPxxxxx

yyyy staat voor het jaar en xxxxx voor het volgnummer. Zoeken op einde jaar leert wat het hoogste volgnummer is per jaar.
Overigens zitten hier dan ook veel pagina's tussen met alleen maar besluiten zonder dat er sprake is van stemmingen. Maar die gooien we dan later weg.

In essentie zijn we nu begonnen met een overheidssite te "hacken". Omdat we de informatie ophalen op een manier die niet standaard aangeboden wordt. Gelukkig is deze vorm niet strafbaar.

Tijd voor het eerste script. Met Python (3) op een kleine host ergens in de cloud maken we een klein script die heel bot voor alle yyyy van 2013 tot en met 2016 de xxxxx van 00001 tot en met 24000 laat lopen. Iedere pagina downloaden (scrapen) we. Hiervoor gebruiken we urllib.request en schutil. Om de server van de Tweede Kamer niet teveel te belasten, wachten we na iedere actie een halve seconde. Uiteindelijk draaide het script 12 uur om alles op te halen.

Dan is het even puzzelen. Eerste vraag is, hoe herkennen we eenduidig in de html-pagina's wat een stemming is. Eerst checken we of de pagina überhaupt het woord "stemverhouding" in zich heeft. Want dat staat er alleen als er een uitgewerkte stemming is. Zo kunnen we de helft van de pagina's gelijk weer negeren.

Nu bevat een pagina vaak meerdere stemmingen. Een blok met een stemming blijkt altijd met <div class="search-result-content"> te beginnen. Met de BeautifulSoup library voor Python knippen we die blokken er uit. Per blok moeten we dan eerst even kijken of de stemming niet aangehouden of ingetrokken is. Dit doen we met eenvoudig zoeken op die twee woorden. Dan blijken we er nog niet te zijn. Want heel soms heeft de stemming wel plaatsgevonden, maar blijken de resultaten nog niet verwerkt te zijn. Dus checken we eerst of "bekijk de stemverhoudingen in detail" in het blok voorkomen.
Overigens sluiten we hiermee de moties uit die "overgenomen" worden zonder feitelijke stemming. We kunnen daarbij namelijk niet eenvoudig bepalen wie aanwezig was en hoe groot de fracties op dat moment waren.

Nu komt de grote truc. We hebben nu de stemblokken. U kunt er eentje zelf bekijken hier door op een plusje te drukken.
Dan valt op dat er wel een getal staat voor de fractiegrootte, maar niet voor het aantal stemmen voor of tegen.
In een groot deel van de stemmingen geen probleem, omdat de hele fractie voor of tegen is. Maar soms zijn mensen afwezig, soms is er een hoofdelijke stemming en soms geeft iemand een stemverklaring af. Hoe dan te zien hoeveel mensen er precies wat gestemd hebben?
Dat halen we dan toch maar weer uit de html-code. Want de grijze balkjes die u ziet zijn feitelijk allemaal hetzelfde plaatje. Alleen dit plaatje wordt afhankelijk van het aantal stemmen breder gemaakt. In de code staat dan iets als width="20". Daarnaast staat er ook nog alt="20 stemmen". We hebben voor het width-stuk gekozen. En zo lopen we het lijstje partijen af en schrijven in een bestand weg bij de stemming hoeveel stemmen voor/tegen/onthouden er per partij waren.
Intussen hebben we ook het dossiernummer er uit geplukt, de datum van de stemming,of het verworpen of aangenomen was en of de stemming met handopsteken of hoofdelijk was.

Bovenstaande doen we dus voor iedere verzamelde pagina. Het resultaat komt in een CSV te staan voor verdere bewerking.

Zo hebben we ruim 10.000 stemmingen opgehaald. Bij elkaar kostte dit een uur of 16 qua werk en een doorlooptijd van ruim een week. Volgende ronde gaat natuurlijk sneller. Dit zijn de twee artikelen die er tot nu toe uit zijn gekomen.
Maar nog veel sneller gaat het als de data gewoon gelijk in een bruikbare vorm wordt aangeboden.


Helaas ga ik de ruwe data noch de python-scripts vrij met u delen. Daar is werk in gaan zitten. En voor werk vraag ik een vergoeding zoals u zult begrijpen.

Ook interessant om te lezen

Open Data chaos

We werken graag en vaak met Open Data van de overheid. Maar niet altijd gaat dit soepel. Daarom delen we soms ook onze mindere ervaringen ter lering. Dit keer lopen we vast in de data van het Meldingenregister Autoriteit Persoonsgegevens.

maandag 30 mei 2016 | Parlement, opendata