De stemmen zijn geteld en het formeren kan beginnen! De Tweede Kamerverkiezingen van 2021 zijn tot een einde gekomen. Er is voldoende data beschikbaar over de verkiezingen maar ik heb nog weinig visualisaties hiervan gezien. Door middel van Python en Google Data Studio heb ik deze data verzameld en gevisualiseerd in een dashboard. Scroll snel verder!
Het dashboard van de Tweede Kamerverkiezingen 2021
Hieronder vind je de verzamelde data van kandidaten, partijen, het aantal stemmen en het aantal zetels wat zij hebben behaald. Als databron is een tabel van RTL nieuws gebruikt. Let op, de data kan wellicht afwijken van de werkelijkheid. Als de data van RTL nieuws niet volledig up-to-date is dan zal het dashboard dat ook niet zijn.
Voor de beste ervaring adviseer ik het dashboard via een desktop te bekijken. Klik op de onderstaande knop om naar het Google Data Studio dashboard te gaan.
Hoe werkt het dashboard?
Het dashboard laat in eerste instantie de volledige gegevens zien. Dit zijn het totaal aantal uitgebrachte stemmen, het totaal aantal stemmen op een lijsttrekker en het aantal zetels wat is behaald. Dit is gebaseerd op de data van RTL nieuws. Je kunt filteren op een bereik van een aantal stemmen, filteren op specifieke kandidaten of partijen en de positie op de kieslijst. Je kunt dus gemakkelijk filteren op data van een specifieke partij, op alle lijsttrekkers of een kandidaat.
Klik op de afbeelding om deze te vergroten.
Hoe werd deze data verzameld? Python!
Door middel van Python en Selenium is het mogelijk om de data van RTL nieuws uit de tabel te ‘scrapen‘ en deze vervolgens te verwerken in een Google Data Studio dashboard. Het script kan ook worden toegepast op andere online datasets door een aantal variabelen aan te passen. Aangezien deze data voor een langere tijd actueel blijft, ongeveer 4 jaar, leek dit me een interessante case.
Hoe werkt werkt Webscraping met Selenium?
Vrijwel iedere Python applicatie begint met het importeren van de benodigde modules. Om de data te verzamelen wordt Selenium gebruikt om de data te ‘scrapen’, Pandas wordt gebruikt om de opgehaalde data te ordenen en os wordt gebruikt om het bestand direct na uitvoering te openen.
from selenium import webdriver
import pandas as pd
import os
Vervolgens moeten we Selenium een URL geven om te scrapen. Dit is de ‘datawrapper‘ url. RTL nieuws gebruikt deze site/iFrame om data van de Tweede Kamerverkiezingen te bundelen in een tabel. Verder heeft Selenium een webdriver, het type browser, nodig om de data mee te verzamelen. In dit geval wordt Google Chrome gebruikt. Omdat Selenium deze zelf niet kon vinden geven we Selenium de locatie van de Chrome Webdriver.
url = 'https://datawrapper.dwcdn.net/vzezR/6/'
driver = webdriver.Chrome('G:/Python Projects/venv/Lib/site-packages/chromedriver.exe')
driver.get(url)
Nu de modules zijn geïmporteerd en de juiste URL is aangewezen wordt het tijd om de data te verzamelen. Hiervoor wordt een lege lijst gebruikt om al onze data in op te slaan. Dit gaat om de scraped_data variabele. Daaronder wordt het paginanummer van de tabel gegeven. Onderaan de While Loop wordt hier telkens één pagina bij opgeteld. Zodra de data op een pagina is verzameld gaat de scraper door naar de volgende pagina.
scraped_data = []
page = 1
Het verzamelen van de data gaat middels een Infinite Loop. Omdat de While Loop altijd waar is (True) zal deze altijd blijven lopen totdat ik deze zelf afbreek. In de While Loop wordt iedere rij (row) aangeduid met een CSS selector en de elementen in deze row worden opgehaald middels een Xpath. Vervolgens wordt de opgehaalde data omgezet naar een Nederlandse, leesbare ‘key‘. Zo wordt ‘party’ omgezet naar ‘Partij’.
Als deze data is opgehaald gaat de scraper door naar de volgende pagina. Dit gaat ook weer middels een CSS selector in de variabele ‘nextPage‘ en wordt uitgevoerd met ‘nextPage.click()‘. Als de scraper niet naar de volgende pagina kan, zodra de laatste pagina is bereikt, dan wordt de Infinite While Loop gebroken.
while True: data = [] try: row = driver.find_elements_by_css_selector('tr.css-kfswhc') for item in row: party = item.find_element_by_xpath('.//td[1]') party = party.text name = item.find_element_by_xpath('.//td[2]') name = name.text votes = item.find_element_by_xpath('.//td[3]') votes = votes.text listPosition = item.find_element_by_xpath('.//td[4]') listPosition = listPosition.text partyData = { 'Partij': party, 'Naam': name, 'Aantal stemmen': votes, 'Positie op lijst': listPosition, 'Tabelpagina': f'Pagina {page}' } scraped_data.append(partyData) nextPage = driver.find_element_by_css_selector('button.next') nextPage.click() except: print('All data has been scraped') break page+=1
Pandas Dataframe en export
Nu de opgehaalde data in de scraped_data variabele is onderbebracht kunnen we dit visualiseren en printen in Python. Voordat het dataframe wordt geprint geef ik de waarden ‘display.max_rows”, None, “display.max_columns”, None’ mee. Het gaat namelijk om een aanzienlijk aantal rijen en kolommen. Vervolgens print ik het dataframe en exporteer ik het als CSV bestand.
Klik op de afbeelding om deze te vergroten.
Vervolgens laat ik Python het bestand automatisch openen middels ‘os.startfile‘. Zodra alles is afgerond wordt ‘driver.quit()‘ gebruikt om de Webdriver af te sluiten. Kies ‘driver.quit()‘ in plaats van ‘driver.close()‘. De regel ‘driver.close()’ sluit de Webdriver niet volledig af. Deze blijft actief in het taakbeheer en kost dus extra RAM geheugen.
pd.set_option("display.max_rows", None, "display.max_columns", None) df = pd.DataFrame(scraped_data) df.to_csv('data_voorkeursstemmen.csv') print(df)os.startfile('data_voorkeursstemmen.csv')driver.quit()
Volledige Selenium Webscraper code
Benieuwd naar de volledige Selenium Webscraper die ik heb gebruikt om de data van de tweede kamer verkiezingen te verzamelen? Hieronder vind je de volledige Python code. Zorg ervoor dat je de juiste Python Libraries hebt geïnstalleerd voordat je hieraan begint.
Heb je een vraag? Stel deze gerust in de comments of op LinkedIn! Succes!