Scrapen zonder geblokkeerd te worden: een praktische gids met code
Geblokkeerd worden tijdens scraping betekent meestal een van drie dingen: je stuurde te veel requests te snel, je client zag er helemaal niet uit als een browser of als een bekende bot, of je IP-adres staat op een lijst die de site minder vertrouwt. Je kunt alle drie verkleinen met een paar gewoonten: merk de blokkade vroeg op, vertraag wanneer de site terugduwt, houd een consistente en eerlijke identiteit aan, en gebruik proxies alleen waar dat past. Deze gids behandelt elk daarvan met werkende code. Gebruik hem voor sites die je mag scrapen.
Herken een blokkade
Een blokkade ziet er niet altijd uit als een foutpagina. Let op:
- 403 Forbidden, wat vaak betekent dat de site je client heeft geweigerd. Stop en controleer of je er mag zijn voordat je het opnieuw probeert.
- 429 Too Many Requests, wat betekent dat je te veel verstuurt. Het komt vaak met een
Retry-After-header. - 503 Service Unavailable, wat kan betekenen dat de site overbelast is. Trek je terug.
- Een 200-antwoord met bijna geen inhoud, een redirect naar een login- of uitdagingspagina, of een pagina die de gegevens mist die je verwachtte.
Log bij elke fout de statuscode en een korte steekproef van de body. Een blokkade die je niet in je logs ziet, kun je ook niet oplossen.
Trek je terug met retries
Wanneer de site zegt "vertraag", moet je code meer dan een beetje vertragen. Exponentiële backoff, met een limiet op het aantal pogingen, is de standaardaanpak. Het respecteert ook Retry-After wanneer de site die stuurt:
import time
import requests
session = requests.Session()
session.headers.update({
"User-Agent": "ExampleBot/1.0 (+https://example.com/bot)",
"Accept-Language": "en-US,en;q=0.9",
})
def polite_get(url: str, max_attempts: int = 4) -> requests.Response:
delay = 2.0
resp = None
for _ in range(max_attempts):
resp = session.get(url, timeout=30)
if resp.status_code not in (429, 503):
return resp
retry_after = resp.headers.get("Retry-After", "")
wait = float(retry_after) if retry_after.isdigit() else delay
time.sleep(wait)
delay *= 2
return resp # nog steeds geblokkeerd: geef het laatste antwoord terug aan de aanroeper
resp = polite_get("https://example.com/products?page=1")
print(resp.status_code, len(resp.text))
Let op wat de functie niet doet. Ze probeert een 403 niet opnieuw, en ze wisselt niet door identiteiten om langs één blokkade te komen. Een 403 is een beslissing om te stoppen, geen puzzel om op te lossen.
Diagnosticeer een blokkade stap voor stap
Wanneer een run begint te falen, werk je deze controles af voordat je iets anders verandert:
- Bekijk de eerste mislukte URL en zijn statuscode. Een blokkade begint meestal op een specifiek punt, niet willekeurig.
- Vergelijk de aanvraagfrequentie in de minuten vóór de eerste fout. Een uitbarsting is de meest voorkomende oorzaak.
- Controleer of de fout aan één pad, één sectie of één tijdstip van de dag is gekoppeld.
- Haal dezelfde URL één keer met de hand op in een gewone browser. Laadt de browser hem, dan zit het verschil in je requestpatroon. Is de browser ook geblokkeerd, dan levert de site de pagina voorlopig niet aan jou.
- Pas pas daarna de code aan. Vertraag eerst, voeg backoff als tweede toe, en bekijk je identiteit als laatste.
Als je meerdere dingen tegelijk verandert, weet je niet meer welke iets heeft geholpen.
Houd een consistente, eerlijke identiteit
Scrapers worden geblokkeerd wanneer hun identiteit tussen requests verandert, of wanneer die niet overeenkomt met de rest van het verkeer. Eén sessie met één duidelijke User-Agent is de eenvoudigste stabiele identiteit. Noem je bot, voeg een contactlink toe en stuur alleen de headers die een gewone client zou sturen. User-Agents wijzigen om eruit te zien als veel verschillende bezoekers is een vorm van ontwijking, en dat maakt een blokkade eerder waarschijnlijker dan minder waarschijnlijk.
Als een site verschillende inhoud toont aan browsers en aan gewone HTTP-clients, gebruik dan voor die pagina's een echte browser en houd dezelfde snelheidslimiet aan. Dat is een legitieme route, en het houdt het requestpatroon redelijk.
Gebruik proxies met zorg
Een proxy verandert het adres waarvan een request komt. Het is een hulpmiddel voor legitieme behoeften, zoals testen vanuit een specifieke regio op een site die je mag testen, of het spreiden van belasting over je eigen infrastructuur. Het is geen manier om een limiet te ontlopen die de site voor jou heeft gesteld. Het formaat van een proxy is het formaat dat de proxy-tasktypes gebruiken:
proxies = {
"http": "http://user:pass@proxy.example.net:8000",
"https": "http://user:pass@proxy.example.net:8000",
}
resp = session.get("https://example.com/products", proxies=proxies, timeout=30)
Het kiezen van een proxytype is een aparte vraag, behandeld in residentiële versus datacenter-proxies en roterende proxies voor scraping.
Wanneer de blokkade een captcha wordt
Sommige sites beantwoorden een snelheidsprobleem met een captcha in plaats van een harde blokkade. De verstandige volgorde is: stop, vertraag, controleer de regels opnieuw, en overweeg pas daarna een solve. Voor PopularCaptcha-widgets geeft de live API van Scarnox een token terug dat je in het veld h-captcha-response indient. Voor andere captchatypen controleer je de live lijst, want ondersteuning voor reCAPTCHA, Cloudflare Turnstile, GeeTest, AWS WAF en Arkose komt binnenkort beschikbaar. De uitgebreide gids is webscraping en captchas.
Als je blokkades op een site begint te zien, is de oorzaak bijna altijd het requestpatroon. Captchas vermijden bij scraping behandelt de gewoonten die dat voorkomen.
Scrape verantwoord
- Controleer
robots.txten de voorwaarden van de site voordat je begint, en volg de paden en vertragingen die ze vragen. - Stop wanneer je een 403 of een duidelijk "niet scrapen"-bericht krijgt. Probeer niet door te gaan.
- Houd je frequentie laag genoeg dat een gewone bezoeker je verkeer niet zou opmerken.
- Verzamel geen persoonsgegevens waarvoor je geen reden hebt, en behandel wat je wel verzamelt volgens de privacyregels die voor jou gelden.
- Als je veel meer volume nodig hebt dan een site comfortabel levert, vraag de eigenaar dan om een feed of een API.