webscraping met python hoe doe ik dat

Webscraping met Python is het automatisch ophalen van gegevens uit webpagina's. Dit is een handige skill voor Data Scientists omdat de beschikbare informatie op het web exponentieel groeit.

Om webscraping te begrijpen is het van belang dat je:

  1. Snapt hoe een webpagina is opgebouwd in HTML (hypertext markup language)
  2. Snapt hoe een webpagina kan worden opgemaakt met CSS (cascading style sheets)
  3. De Python packages kent die van belang zijn

Op deze pagina zullen we eerst het bovenstaande behandelen, waarna we een tutorial doorlopen zodat je zelf de zoekresultaten van Bol.com kunt scrapen.

Hoe is een webpagina opgebouwd in HTML?

De basisstructuur
Webpagina's zijn opgebouwd in HTML volgens een vaste structuur. Zo heeft een webpagina bijvoorbeeld een header en een body. In de header komt o.a. de titel van de webpagina te staan. In de body komt de inhoud van de webpagina te staan.

<!DOCTYPE html>

<html>

<head>
<meta charset="utf-8">
<title>De titel van de pagina</title>
</head>

<body>
Hier komt de inhoud van de webpagina te staan.
</body>

</html>

In de body van de pagina
Binnen deze basisstructuur kan de webpagina gevuld worden met verdere inhoud. De meeste pagina's bestaan voor een groot deel uit 'headings', linkjes, en paragrafen normale text.

De volgende HTML tags gebruik je voor deze aanduidingen (links de HTML code, rechts hoe het er uit komt te zien op een webpagina):

<h1>Heading 1</h1>
<h2>Heading 2</h2>
<a href="#">Link</a>
<p>Paragraaf text</p>

Heading 1

Heading 2

Link

Paragraaf text

En zo zijn er nog veel meer HTML Tags die voor kunnen komen in een webpagina. Hier vind je een complete lijst.

Hoe worden webpagina's opgemaakt met CSS?

Waar HTML gebruikt wordt om de inhoud van een webpagina te beschrijven, wordt CSS gebruikt voor de opmaak.

Zo kun je alle Heading 1 groen opmaken met de volgende code:

h1 {
color: green;
}

Voor webscraping is het van belang om CSS classes en IDs te begrijpen. In een stuk CSS code worden classes en IDs opgesteld. Een class gebruik je om meerdere HTML elementen op te maken, terwijl je een ID gebruikt om één element op te maken.

.ditiseenclass {
color: blue;
}

#ditiseenid {
color: green;
}

Vervolgens kan een class of een ID worden toegevoegd aan een HTML element om deze op te maken. Dit doe je als volgt (links de HTML code, rechts het resultaat op een webpagina):

<p class="ditiseenclass">Paragraaf text</p>
<p id="ditiseenid">Paragraaf text nummer twee</p>
Paragraaf text

Paragraaf text nummer twee

Nu je weet hoe HTML en CSS code gestructureerd worden kun je hier je voordeel mee doen in het webscrapen met Python. Tijdens het scrapen zul je altijd op zoek zijn naar data die opgeslagen zitten binnen HTML en/of CSS elementen. Je gebruikt je kennis van HTML en CSS dus om bepaalde informatie die je wilt scrapen te localiseren.

Welke Python packages gebruik ik voor webscraping?

Wie een pagina wilt scrapen met Python heeft in ieder geval twee packages nodig. Een package om een webpagina op te halen en een package om de opgehaalde data te parsen en de gewenste data uit het bestand te pikken.

Requests package
Met het requests package kun je de inhoud van HTTPS en HTTP webpagina's ophalen op eenvoudige wijze. Hiervoor dien je het volgende te doen:

  1. Installeer het requests package (dit is een eenmalige handeling)
  2. Importeer het requests package (zie tutorial onderstaand)
  3. Met requests.get("URL") kun je vervolgens de inhoud van webpagina's ophalen

BeautifulSoup package
Met het Python package BeautifulSoup kun je de opgehaalde webpagina parsen zodat de output in gestructureerd en leesbaar HTML format komt te staan. Vervolgens geeft dit package je de mogelijkheid om de gewenste informatie uit de opgehaalde webpagina te destilleren. In onderstaande tutorial krijg je een idee van de mogelijkheden.

Met data leren werken in Python? Leg de noodzakelijke basis om met webscraping aan de slag te gaan.


Tutorial: Bol.com zoekresultaten scrapen met Python

Omdat er een run is op hand sanitizers in tijden van Corona willen we nauwlettend in de gaten houden welke producten er voor welke prijs beschikbaar zijn. We gaan daarom productnamen en prijzen scrapen uit de zoekresultaten van Bol.com.

Allereerst importeren we de benodigde packages. We vragen de inhoud van de verschillende pagina's van de zoekresultaten op met een for loop en het requests package. Vervolgens parsen we de content met een HTML parser van het package BeautifulSoup. Met .find_all() zoeken we op de class die ieder product meekrijgt zodat we een volledige lijst krijgen van alle producten van alle 15 pagina's zoekresultaten.

In [1]:
import pandas as pd
import numpy as np
import requests
from bs4 import BeautifulSoup

producten_alle_paginas = []

for i in range(1,15):
    response = requests.get(f"https://www.bol.com/nl/s/?page={i}&searchtext=hand+sanitizer&view=list")
    content = response.content
    parser = BeautifulSoup(content, 'html.parser')
    body = parser.body
    producten = body.find_all(class_="product-item--row js_item_root")
    producten_alle_paginas.extend(producten)
    
len(producten_alle_paginas)
Out[1]:
336

We zien dat we in totaal 336 producten in de lijst hebben. NB: als jij dezelfde code runt kan de uitkomst anders zijn omdat in de tussentijd het aanbod op Bol.com kan wijzigen.

Met onderstaande code kun je een productnaam en de productprijs uit onze lijst met producten halen. We doen dit door binnen een product de juiste data te lokaliseren aan de hand van HTML tags of CSS classes.

In [2]:
prijs = float(producten_alle_paginas[1].meta.get('content'))
productnaam = producten_alle_paginas[1].find(class_="product-title--inline").a.getText()
print(prijs)
print(productnaam)
8.29
Reinigende Handgel 250 ml - Hand Sanitizer - Glycerine - Geparfumeerd - handgel

Nu we weten hoe we een productnaam en -prijs uit onze lijst halen, kunnen we dit voor ieder product doen. We passen een for loop toe om de data voor ieder product op te halen. Hierbij houden we rekening met producten die niet op voorraad zijn. Deze producten krijgen een andere CSS class mee. Als een product deze andere CSS class heeft en niet leverbaar is dan wordt er geen prijs meegegeven aan het product.

In [3]:
productlijst = []

for item in producten_alle_paginas:
    if item.find(class_="product-prices").getText() == '\nNiet leverbaar\n':
        prijs = None
    else:
        prijs = float(item.meta['content'])
    product = item.find(class_="product-title--inline").a.getText()
    productlijst.append([product, prijs])
    
print(productlijst[:3])
[['50ml Handgel Anti-Bacteriën Anti-virus Hydraterende Reizen Draagbare Instant Outdoor Cleansing Hand Sanitizer', None], ['Reinigende Handgel 250 ml - Hand Sanitizer - Glycerine - Geparfumeerd - handgel', 8.29], ['Cobeco Disinfect Hand Sanitizer - Dispenser Refill 5 liter (nl/en)', 37.65]]

We hebben nu een lijst van lijsten met productnamen en prijzen (wanneer bekend). Deze lijst kunnen we omzetten in een DataFrame zodat we er makkelijk berekeningen op uit kunnen voeren. Dit is de laatste stap van deze tutorial.

In [4]:
df = pd.DataFrame(productlijst, columns=["Product", "prijs"])
print(df.shape)
df["prijs"].describe()
(336, 2)
Out[4]:
count    331.000000
mean      16.184924
std        9.461911
min        0.990000
25%       13.500000
50%       15.990000
75%       17.990000
max      129.000000
Name: prijs, dtype: float64

Wil je leren hoe je met data werkt in Python?

In onze tweedaagse Python cursus voor data science nemen we je mee in de mogelijkheden van Python. Je leert de basis van waaruit je gemakkelijk aan de slag kunt met webscraping. In onderstaande brochure vind je meer informatie.

Voor in-company groepen kunnen we een speciale verdieping in webscraping aanbieden naast de basis Python vaardigheden. Bij interesse in in-company trainingen of consultancy diensten is het het makkelijkst om even contact op te nemen.

Download één van onze opleidingsbrochures voor meer informatie

by: