Project L - Download en verwerk API-data

01 - Projectoverzicht
  • In dit project maak je een Python-script dat gegevens ophaalt uit een online API en verwerkt tot een bruikbaar overzicht.
  • Het script helpt wanneer je actuele informatie niet handmatig van een website wilt kopiëren.
  • Je gebruikt een openbare API die JSON teruggeeft, bijvoorbeeld weergegevens, valutakoersen of voorbeelddata voor tests.
  • Het script downloadt de data, leest de JSON-structuur en haalt alleen de velden op die je nodig hebt.
  • Het resultaat is een terminaloverzicht of CSV-bestand met opgeschoonde API-data.
  • Je gebruikt AI om een eerste script te laten maken met duidelijke foutafhandeling voor internetproblemen en ontbrekende velden.
  • Je voert de code uit in VS Code en controleert de ruwe API-data voordat je de verwerking uitbreidt.
  • Als de API anders reageert dan verwacht, verbeter je de prompt met een voorbeeld van de JSON-uitvoer.
02 - Projectmap en Python-omgeving

Voorkennis: doorloop de voorgaande projecten. Het doel en gebruik van .venv zijn uitgelegd in project A, blok 02. Voor ieder nieuw project maak je een eigen omgeving; hieronder herhaal je die bekende stappen.

  • Maak een eigen projectmap project_l en open die map in VS Code. Maak daarin straks api_data.py.
  • Deze oefeningen voer je lokaal uit in de terminal van VS Code, omdat ze bestanden op je computer lezen of schrijven. Gebruik hiervoor de Python-installatie uit de basiscursus.
  • Controleer je Python-versie. Werkt python op macOS of Linux niet, gebruik dan python3 voor het aanmaken van de omgeving.
python --version
python -m venv .venv

Activeer de omgeving. In Windows PowerShell:

.venv\Scripts\Activate.ps1

In de Windows-opdrachtprompt (cmd):

.venv\Scripts\activate.bat

Op macOS of Linux:

source .venv/bin/activate

Kies in VS Code via Python: Select Interpreter de interpreter uit .venv. Gebruik vanaf nu de geactiveerde terminal. Je verlaat de omgeving later met deactivate.

Een package is een extra pakket met Python-modules. pip is het installatiehulpmiddel; python -m pip gebruikt het bij de actieve Python. Installeer requests nu in de projectomgeving. De werking van het pakket volgt vóór de opdracht in blok 04.

python -m pip install requests
03 - Testgegevens voorbereiden

We gebruiken JSONPlaceholder, een openbare oefen-API met fictieve gegevens. Voor deze oefening is geen account of API-sleutel nodig. Open https://jsonplaceholder.typicode.com/users in je browser en bekijk de structuur.

De response is een lijst met gebruikers. We bewaren id, name, email en address.city. Je hebt internet nodig; gebruikers.csv en gebruikers_bron.json worden naast het script gemaakt.

[
  {
    "id": 1,
    "name": "Voorbeeldgebruiker",
    "email": "voorbeeld@example.com",
    "address": {"city": "Voorbeeldstad"}
  }
]

Dit is een verkort, fictief structuurvoorbeeld; de live gegevens kunnen andere namen bevatten.

04 - Begrippen en hulpmiddelen vóór de opdracht
  • JSON opslaan en lezen ken je uit hoofdstuk 10. Een API is een afgesproken toegangspunt van een ander programma. Bij deze API vraagt jouw script via een URL gegevens op en krijgt het JSON terug.
  • HTTP is het protocol van die aanvraag. Een response bevat een statuscode en inhoud: 200 betekent gelukt, 404 betekent niet gevonden. Requests is het extra Python-pakket dat de aanvraag verzorgt.
  • requests.get haalt de response op, raise_for_status controleert fouten en json() zet JSON om naar Python-data. Een timeout begrenst wachten op verbinding en ontvangst.
  • isinstance(waarde, list) en isinstance(waarde, dict) controleren het datatype vóór verwerking. json.dumps maakt JSON-tekst; indent=2 springt twee spaties in en ensure_ascii=False bewaart letters zoals é leesbaar.
  • Een HTTP-response kan een foutstatus hebben terwijl er wel tekst terugkomt. raise_for_status() controleert de HTTP-status vóór de JSON-verwerking.
  • timeout=10 begrenst het wachten bij verbinding en ontvangst van data; het is geen totale maximale looptijd voor het hele script.
  • De adresgegevens zijn een genest object. get levert voor optionele velden een lege waarde; ontbrekende verplichte velden stoppen de verwerking. Bestaande uitvoerbestanden worden na geslaagde controle vernieuwd.
05 - Een gerichte AI-prompt maken

Geef AI eerst een concrete opdracht. Kopieer bijvoorbeeld deze prompt en vergelijk het antwoord met de voorbeeldcode in het volgende blok:

Maak met requests, json, csv en pathlib een beginnersscript dat
https://jsonplaceholder.typicode.com/users eenmaal ophaalt met timeout=10.
Roep raise_for_status aan en lees JSON. Controleer dat de response een lijst
met objecten is. Vereis id en name; gebruik lege tekst voor ontbrekende
email of address.city. Sla de ruwe JSON op als gebruikers_bron.json en de
selectie als gebruikers.csv. Toon de selectie in de terminal en meld
netwerk-, HTTP-, JSON-, structuur- en schrijffouten. Schrijf pas na
structuurcontrole.

Vraag om uitleg bij onbekende regels en controleer welke bestanden de code leest en schrijft voordat je haar uitvoert. Gebruik de oefengegevens uit dit project.

06 - Een werkende basisversie

Dit is een complete basisversie voor api_data.py. Neem de code over of vergelijk haar met het antwoord van AI.

from pathlib import Path
import csv
import json
import requests

BASIS = Path(__file__).resolve().parent
URL = "https://jsonplaceholder.typicode.com/users"

def main():
    response = requests.get(URL, timeout=10)
    response.raise_for_status()
    data = response.json()
    if not isinstance(data, list):
        raise ValueError("Verwacht een lijst met gebruikers")
    regels = []
    for nummer, gebruiker in enumerate(data, start=1):
        if not isinstance(gebruiker, dict):
            raise ValueError(f"Gebruiker {nummer} is geen object")
        if gebruiker.get("id") is None or not gebruiker.get("name"):
            raise ValueError(f"Gebruiker {nummer} mist id of name")
        adres = gebruiker.get("address")
        if not isinstance(adres, dict):
            adres = {}
        regels.append([gebruiker["id"], gebruiker["name"],
                       gebruiker.get("email") or "", adres.get("city") or ""])
    (BASIS / "gebruikers_bron.json").write_text(
        json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
    with (BASIS / "gebruikers.csv").open("w", newline="", encoding="utf-8") as bestand:
        schrijver = csv.writer(bestand)
        schrijver.writerow(["id", "naam", "email", "stad"])
        schrijver.writerows(regels)
    for regel in regels:
        print(*regel, sep=" | ")
    print(f"{len(regels)} gebruikers verwerkt. Bron: {URL}")

if __name__ == "__main__":
    try:
        main()
    except requests.exceptions.JSONDecodeError as fout:
        print(f"Response bevat geen geldige JSON: {fout}")
    except requests.RequestException as fout:
        print(f"Ophalen mislukt: {fout}")
    except (OSError, ValueError, csv.Error) as fout:
        print(f"Verwerken of opslaan mislukt: {fout}")
07 - Het script uitvoeren
  • Sla de volledige code op als api_data.py in je projectmap. Zet eventuele invoerbestanden op de plek die in blok 03 staat.
  • Open de geïntegreerde terminal in die projectmap en activeer .venv als dat nog niet is gebeurd.
  • Voer het script uit met:
python api_data.py

Lees eerst de terminaluitvoer en open daarna eventuele uitvoerbestanden. Controleer het resultaat met blok 08 voordat je met eigen gegevens verdergaat.

08 - Het resultaat controleren
  • Vergelijk een gebruiker uit de ruwe JSON met de terminal en de CSV: naam, e-mail en stad moeten bij dezelfde ID horen.
  • Gebruik voor één proef https://jsonplaceholder.typicode.com/bestaat-niet. Je krijgt een HTTP-foutmelding. Herstel daarna de URL.
  • Maak voor een lokale proef een kopie van het script en vervang de drie regels die downloaden en JSON lezen door data = json.loads((BASIS / "gebruikers_bron.json").read_text(encoding="utf-8")). Verwijder in een kopie van de JSON een optioneel veld en daarna name: eerst een lege CSV-waarde, daarna een duidelijke fout.
09 - Fouten herkennen en oplossen
  • Geen verbinding of timeout? Controleer internet en URL. Voer handmatig later opnieuw uit; maak geen snelle oneindige herhaallus.
  • CSV lijkt oud na een netwerkfout? Bij mislukken blijft eerdere uitvoer bestaan. Controleer de terminal en de wijzigingsdatum. Bij een schrijffout kan één uitvoerbestand al vernieuwd zijn.
10 - Uitbreiden en afronden

Probeer deze vervolgstap pas als de basis werkt:

Laat AI URL en ophaaltijd in een apart metadatabestand bewaren. Voeg daarna een expliciete offline-modus toe die de opgeslagen JSON gebruikt en duidelijk meldt dat het om eerder opgehaalde data gaat.

Bewaar je werkende basisversie en verander één onderdeel tegelijk. Geef AI bij een fout de foutmelding, het relevante stukje code, je testinvoer en de verwachte uitkomst.

Het project is afgerond wanneer de basiscontrole uit blok 08 slaagt en je in eigen woorden kunt uitleggen welke invoer wordt gebruikt, hoe de verwerking werkt en waar de uitvoer terechtkomt.

Naslag: Requests: quickstart.