Captchas vermijden bij scrapen (zonder de regels te breken)
De meeste captchas tijdens het scrapen zijn een reactie op verkeer dat geautomatiseerd lijkt. De goedkoopste manier om ermee om te gaan is ze niet te veroorzaken. Dat betekent eerst zoeken naar een legitieme databron, nagaan wat de regels van de site toestaan, minder en langzamer verzoeken sturen, en niet dezelfde pagina twee keer ophalen. Een captcha oplossen is de terugvaloptie voor de gevallen die je niet kunt vermijden, niet het plan.
Controleer eerst op een officiële API of feed
Veel sites die worden gescraped bieden al een manier om dezelfde data zonder captcha op te halen: een publieke API, een dataexport, een RSS- of sitemapfeed, of een partnerprogramma. Een officiële bron is betrouwbaarder, minder snel onverwacht veranderd en geeft de siteeigenaar inspraak in hoe je hem gebruikt. Zoek naar:
- een developer- of API-sectie in de footer van de site,
sitemap.xmlvoor de lijst met pagina's,- RSS- of Atom-links in de
<head>van de pagina, - een "data"- of "download"-pagina voor bulkexports.
Als een van deze je behoefte dekt, gebruik hem dan. Je vermijdt de meeste captchas door helemaal geen HTML op te vragen.
Respecteer robots.txt en het tempo dat het vraagt
robots.txt vertelt je welke paden automatische clients mogen ophalen en soms hoe lang je moet wachten tussen verzoeken. De standaardbibliotheek van Python kan het voor je lezen:
import time
from urllib.robotparser import RobotFileParser
import requests
USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"
parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()
delay = parser.crawl_delay(USER_AGENT) or 5 # val terug op een voorzichtige 5 seconden
urls = [
"https://example.com/products?page=1",
"https://example.com/products?page=2",
]
last_request = 0.0
for url in urls:
if not parser.can_fetch(USER_AGENT, url):
print("skipped by robots.txt:", url)
continue
wait = delay - (time.monotonic() - last_request)
if wait > 0:
time.sleep(wait)
resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
last_request = time.monotonic()
print(url, resp.status_code)
Als robots.txt een pad verbiedt, is het eerlijke antwoord om het met rust te laten of de eigenaar te vragen. Er omheen routeren met een browser verandert niets aan wat de site heeft gevraagd.
Vertraag en spreid verzoeken
Een gelijkmatig, bescheiden tempo lokt zelden een uitdaging uit, terwijl een uitbarsting bijna altijd een uitdaging uitlokt. Enkele gewoonten maken een groot verschil:
- Kies per site één aanvraagtempo en houd je daaraan, in plaats van op volle snelheid te draaien.
- Voeg willekeurige jitter toe zodat de timing niet perfect regelmatig is.
- Stop en wacht even wanneer je een 429 of een captcha-pagina ziet.
- Draai taken buiten piekuren als de belasting van de site een zorg is.
Cache en haal niet opnieuw op
Elk verzoek dat je niet doet, is een verzoek dat de site niet hoeft af te handelen. Bewaar de pagina's die je ophaalt met hun datum en een hash van de inhoud, en haal ze alleen opnieuw op wanneer de inhoud waarschijnlijk is veranderd. Voorwaardelijke verzoeken met de headers If-Modified-Since of ETag laten de server goedkoop antwoorden "niet gewijzigd" wanneer hij dat ondersteunt.
Hergebruik sessies en stuur gewone headers
Een sessie die cookies tussen verzoeken bewaart, gedraagt zich meer als een bezoeker dan een script dat elke keer opnieuw begint. Gebruik requests.Session() per site, en stuur een duidelijke, eerlijke User-Agent die je bot en een contactpersoon noemt. Doe niet alsof je een browser bent om een regel te omzeilen. Als een site JavaScript nodig heeft om zijn inhoud te tonen, gebruik dan een browsertool voor die pagina's, en houd dezelfde limieten aan.
Wanneer er toch een captcha verschijnt
Sommige sites tonen een captcha, hoe zorgvuldig je ook werkt. Detecteer het in je code en stop die taak in plaats van de pagina te blijven bestoken. De detectie en de optionele oplossing voor PopularCaptcha worden behandeld in webscraping-captchas.
Plan de crawl voordat je begint
Een crawl die elke dag alles ophaalt, is de makkelijkste manier om een captcha uit te lokken. Plan het werk eerst:
- Prioriteer. Bepaal welke pagina's vaak veranderen en welke zelden. Crawl de vaak veranderende vaker en de rest zelden.
- Gebruik de datums uit de sitemap. Veel sitemaps bevatten een
lastmod-waarde. Sla URL's over die sinds je laatste bezoek niet zijn gewijzigd. - Crawl incrementeel. Bewaar de laatste geslaagde ophaalactie per URL, en hervat daar in plaats van na een fout opnieuw bij pagina één te beginnen.
- Spreid de belasting. Verdeel een grote lijst in batches en draai ze over de dag, niet allemaal tegelijk.
Een plan als dit verlaagt het aantal verzoeken, en dat is de grootste hefboom die je hebt.
Schrijf het plan op als een kort configuratiebestand of een tabel: de sites, de secties, het vernieuwingsinterval en het dagelijkse verzoekbudget per site. Wanneer het budget op is, stopt de taak tot het volgende tijdvenster. Het budget als harde limiet behandelen, in plaats van als richtlijn, is wat een crawler ervan weerhoudt af te glijden naar het verkeerspatroon dat captchas uitlokt. Bekijk het budget elke paar weken, want een site die groeit kan ook meer verkeer krijgen, en wat vorig kwartaal beleefd was, is nu misschien niet meer beleefd.
Scrape verantwoord
- Controleer
robots.txten de servicevoorwaarden voordat je begint, en respecteer wat ze zeggen. - Houd het aantal verzoeken laag en stop wanneer de site aangeeft dat hij het moeilijk heeft.
- Verzamel geen persoonsgegevens waarvoor je geen reden hebt om ze te bewaren, en verwijder ze zodra je ze niet meer nodig hebt.
- Publiceer beschermde content niet in bulk opnieuw. Gebruik de data voor analyse, vergelijking of je eigen product, en vermeld de bron waar dat past.
- Neem contact op met de siteeigenaar als je meer volume nodig hebt. Hij biedt mogelijk een feed aan.