Een Custom Proxy instellen in Scrapy (productiegeschikt)

Laatst bijgewerkt op August 11, 2026
Hand-drawn Scrapy crawler routing through a proxy pool, retrying a 503 route and completing through a 200 route
AI Samenvatting
- Bouw een custom Scrapy proxy middleware die goedgekeurde routes toewijst, authenticatie veilig toevoegt, foutredenen vastlegt en request-metadata behoudt over retries heen. - Begrijp de volgorde van downloader middleware, vooral hoe custom proxylogica samenwerkt met HttpProxyMiddleware, RetryMiddleware, redirects en exception handling. - Voeg rotatie toe met begrensde pogingen, afkoelperiodes, proxygezondheidsstatus en target-bewust beleid in plaats van voor elke request zomaar een willekeurige proxy te kiezen. - Maak onderscheid tussen proxy-authenticatiefouten, verbindingsfouten, DNS-problemen, 403-responses van de target en rate limits, zodat elke situatie de juiste afhandeling krijgt. - Gebruik productiebeveiligingen voor opslag van geheimen, concurrency, observability, sessieconsistentie en fail-closed gedrag wanneer er geen goedgekeurde proxy meer beschikbaar is.

Je Scrapy-spider vliegt moeiteloos door 100 testpagina’s heen en klapt daarna om bij 10.000 pagina’s. Dat is meestal geen scraping-bug, maar een netwerkprobleem dat zich voordoet als een scraping-bug. De standaardoplossing waar iedereen meteen naar grijpt is een proxy, en zo’n proxy in request.meta zetten kost je ongeveer dertig seconden.

Alleen: die dertig seconden zijn precies waar veel basisgidsen ophouden. Ze laten meta={"proxy": "http://IP:PORT"} zien, misschien nog een middleware-class, en noemen het dan klaar. Wat vaak ontbreekt, is wat er gebeurt als die proxy halverwege de crawl uitvalt, hoe inloggegevens in Git-geschiedenis blijven hangen, of waarom een retry zomaar opnieuw dezelfde mislukte proxy kan gebruiken. Dáár gaat deze gids over: fail-closed configuratie, geheimenbeheer, bewuste proxykeuze bij retries, protocolbeperkingen en meetbare kostenafwegingen.

Wat is een proxy middleware in Scrapy?

Een proxy middleware is code die in Scrapy’s downloader-pipeline zit en bepaalt via welk IP-adres een request lijkt te komen voordat het de deur uitgaat. Scrapy levert standaard al HttpProxyMiddleware mee, die een proxy-sleutel uit request.meta leest, waar nodig proxy-authenticatie toevoegt en de request doorgeeft aan de download handler die de verbinding echt opent. Aangepaste proxy middleware vervangt dat transportstapje niet — het is een selector die vóór de ingebouwde machine beslist welke proxy gebruikt moet worden. Dat onderscheid is belangrijker dan het misschien klinkt, en het verklaart een groot deel van de “mijn custom middleware doet niks”-meldingen.

Waarom proxies belangrijk zijn voor productie-Scrapy-projecten

Een proxy verandert de netwerkroute en het zichtbare bron-IP. Dat kan helpen bij legitieme geo-specifieke tests, geautoriseerde verkeersverdeling en het isoleren van netwerkfouten. Het geeft je geen toestemming, omzeilt geen rate limits en garandeert geen toegang. Of een crawl überhaupt een proxy nodig heeft, hangt af van het doel, de voorwaarden, de requestfrequentie en de betrouwbaarheidseisen van de klus.

Niet elke proxy is gelijk, en het verkeerde type kiezen kan op zichzelf al een productie-incident veroorzaken:

ProxytypeBetrouwbaarheidSnelheidDetectierisicoTypische kosten
Gratis publieke proxiesZeer wisselendWisselendVaak hoogGeen fee, maar grote beveiligings-/operationele risico’s
Datacenter proxiesAfhankelijk van provider en targetVaak snelAfhankelijk van targetVaak geprijsd per GB of IP
Residential proxiesAfhankelijk van provider en targetWisselendAfhankelijk van targetVaak geprijsd per GB
ISP proxiesAfhankelijk van provider en targetWisselendAfhankelijk van targetProvider-specifiek

Gratis proxies verdienen een aparte waarschuwing, omdat de gemeten risico’s aanzienlijk zijn. De 30 maanden durende Free Proxies Unmasked-studie volgde meer dan 640.000 adressen van 11 aanbieders: 34,5% was minstens één keer actief en 16.923 manipuleerden content. Die populatie onderstreept een stevige beveiligingswaarschuwing voor publieke lijsten; het is geen overdraagbaar faalpercentage voor elke actuele lijst, betaalde pool, target of workload.

Proxies verslaan moderne botdetectie ook niet automatisch. Diensten zoals Cloudflare scoren requests op basis van tientallen signalen — TLS-fingerprints, headerconsistentie, JavaScript-uitvoering, gedragspatronen — waarbij je IP-adres maar één factor is. Een schone residential proxy met inconsistente headers en zonder cookie jar wordt nog steeds gemarkeerd. Houd die verwachting dus realistisch voordat je een hele architectuur bouwt rond “gewoon de IP’s roteren”.

Voor je begint

  • Moeilijkheid: Gemiddeld
  • Benodigde tijd: ongeveer 30–45 minuten voor de volledige productieopzet, ongeveer 5 minuten voor de snelle test
  • Wat je nodig hebt: Python 3.9+, Scrapy geïnstalleerd (deze gids is getest met Scrapy 2.17.0, uitgebracht in juli 2026), een werkende spider uit scrapy startproject, en minstens één proxy-endpoint (een gratis trial van een datacenter-proxyprovider is prima voor tests)

Stap 1: Test een proxy met de request meta-parameter

De snelste manier om te checken of een proxy werkt, is even alle middleware-architectuur buitenspel zetten en het rechtstreeks proberen.

Scrapy’s ingebouwde HttpProxyMiddleware leest direct een proxy-key uit request.meta en routeert de request erdoorheen. Geen settings-aanpassingen, geen middleware-class — alleen één keyword argument.

import scrapy

class ProxyTestSpider(scrapy.Spider):
    name = "proxy_test"
    start_urls = ["https://httpbin.org/ip"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url,
                meta={"proxy": "http://203.0.113.10:8080"},
                callback=self.parse,
            )

    def parse(self, response):
        self.logger.info(response.text)

Start het met scrapy runspider proxy_test.py. Als de proxy werkt, geeft httpbin.org/ip het IP-adres van de proxy terug in plaats van je eigen IP — dat is je bevestiging. Als de response blijft hangen en uiteindelijk een TCP connection timed out-fout geeft, is de proxy dood of onbereikbaar. En ja, dat gebeurt vaker dan proxy-aanbieders graag toegeven.

Deze methode is prima voor een losse spider of een snelle test. Maar zodra je meer dan één spider hebt, loopt het fout, omdat je dan dezelfde proxy-string in vijf verschillende bestanden hardcodeert.

Stap 2: Bouw een custom proxy middleware

Voor alles wat verder gaat dan één enkele spider wil je de proxylogica op één centrale plek hebben. Maak een ProxyMiddleware-class in middlewares.py:

from scrapy.exceptions import NotConfigured

class ProxyMiddleware:
    def __init__(self, proxy_url):
        self.proxy_url = proxy_url

    @classmethod
    def from_crawler(cls, crawler):
        proxy_url = crawler.settings.get("PROXY_URL")
        if not proxy_url:
            raise NotConfigured("PROXY_URL is vereist; we vallen niet stilletjes terug op direct verkeer")
        return cls(proxy_url=proxy_url)

    def process_request(self, request, spider):
        if "proxy" not in request.meta:
            request.meta["proxy"] = self.proxy_url

En registreer die in settings.py:

import os

PROXY_URL = os.environ.get("PROXY_URL")

DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.ProxyMiddleware": 350,
}

Let op de from_crawler-classmethod in plaats van een gewone __init__. Dit is het patroon dat Scrapy zelf aanbeveelt voor het uitlezen van settings, en dezelfde hook gebruiken we in stap 4 opnieuw bij secrets. Het voordeel is simpel: verander één instelling, en elke spider in het project gebruikt meteen de nieuwe proxy. Niet meer vijf bestanden doorspitten om een dode IP te vervangen.

Stap 3: Begrijp de middleware-volgorde, zodat je proxy niet stilletjes niets doet

Dit is het deel dat bijna elke andere tutorial wegwuift met “zet de prioriteit gewoon op 350, vertrouw me maar”. Downloader middleware in Scrapy draait in een vaste, voorspelbare volgorde. Begrijp je die niet, dan krijg je bugs die totaal niets met proxies lijken te maken.

Request-hooks (process_request) lopen in oplopende prioriteit — laagste nummer eerst. Response-hooks (process_response, process_exception) lopen in aflopende prioriteit — hoogste nummer eerst, en werken terug door de keten.

Request flow (oplopend):
  Spider → [100] RobotsTxt → [300] HttpAuth → [350] JOUW PROXY MIDDLEWARE
         → [500] UserAgent → [550] Retry → [700] Cookies → [750] HttpProxy
         → Downloader

Response flow (aflopend):
  Downloader → [750] HttpProxy → [700] Cookies → [550] Retry
             → [500] UserAgent → [350] JOUW PROXY MIDDLEWARE → [300] HttpAuth
             → [100] RobotsTxt → Spider

Hier is de actuele standaard-prioriteitentabel voor Scrapy’s ingebouwde middleware (geverifieerd tegen 2.17.0):

MiddlewareStandaardprioriteit
RobotsTxtMiddleware100
HttpAuthMiddleware300
DownloadTimeoutMiddleware350
DefaultHeadersMiddleware400
UserAgentMiddleware500
RetryMiddleware550
RedirectMiddleware600
CookiesMiddleware700
HttpProxyMiddleware750
DownloaderStats850
HttpCacheMiddleware900

Wanneer RetryMiddleware een retry plant, kopieert het de mislukte request — inclusief metadata — en die nieuwe request komt opnieuw de downloader middleware-keten binnen. De numerieke relatie van je selector tot prioriteit 550 garandeert geen rotatie. Rotatie gebeurt alleen wanneer de selector-code de retry herkent en bewust de gekopieerde meta["proxy"] overschrijft. Prioriteit 350 is een handige plek voor een selector omdat die vóór de ingebouwde transportstap op 750 draait, maar het is op zichzelf geen rotatiemechanisme.

Scrapy request- en responsepaden door prioriteiten 350, 550 en 750, met een 503-retry die opnieuw de middleware-keten ingaat

Veelvoorkomende fouten bij middleware-volgorde

  • Je middleware op dezelfde prioriteit zetten als HttpProxyMiddleware (750): dit creëert een race condition waarbij Scrapy’s dict-volgorde (niet jouw logica) bepaalt welke middleware de request eerst verwerkt. Symptom: af en toe, onverklaarbaar proxygedrag.
  • setdefault() of if "proxy" not in request.meta gebruiken in een roterende selector: de gekopieerde retry behoudt de oude proxy. Symptom: elke retry gebruikt opnieuw dezelfde mislukte route. Oplossing: detecteer een retry (bijvoorbeeld retry_times > 0) en vervang expliciet de proxywaarde waar jouw selector eigenaar van is.
  • HttpProxyMiddleware volledig uitschakelen: sommige tutorials zeggen dat je "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None moet zetten omdat “de custom middleware het afhandelt.” Dat klopt niet — je custom middleware is een selector, geen transportlaag. Schakel je de ingebouwde middleware uit, dan worden proxy-authenticatieheaders nooit toegevoegd en gaan je requests stilletjes ongeauthenticeerd weg (of helemaal niet).

Stap 4: Stop met proxy-inloggegevens hardcoden

Bij vrijwel elke top-ranking Scrapy-proxy tutorial die ik vond, staat http://username:password@proxy.example.com:8080 rechtstreeks in een Python-bestand. Dat is een credential die voor altijd in je Git-geschiedenis blijft staan, en die overal opduikt: in clones, forks en logdumpjes als iemand nonchalant met print() werkt.

Er zijn grofweg drie manieren om dit aan te pakken:

MethodeBeveiligingFlexibiliteitHet best voor
Hardcoded in spider/settings.pySlecht — secrets staan in de repoLaagAlleen snelle lokale tests
Omgevingsvariabele http_proxy (Scrapy-native)Beter — buiten de codeLaag (één proxy)CI/CD-pipelines, Docker
.env-bestand + python-dotenv + from_crawlerBeste — buiten de code, per omgevingHoog (meerdere proxies, rotatie)Productiescrapers

De derde optie is de moeite waard om goed op te zetten. Installeer python-dotenv, maak een .env-bestand aan en voeg het meteen toe aan .gitignore — serieus, doe dit nu:

PROXY_USER=myuser
PROXY_PASSWORD=my$ecret!Pass
PROXY_HOST=proxy.example.com
PROXY_PORT=8080

Laad het bovenaan in settings.py:

from dotenv import load_dotenv
import os

load_dotenv()

PROXY_USER = os.getenv("PROXY_USER")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
PROXY_HOST = os.getenv("PROXY_HOST")
PROXY_PORT = os.getenv("PROXY_PORT")

Lees het daarna veilig in je middleware via from_crawler — precies het patroon dat de verwarring oplost die ik op fora vaak zie, waar mensen vragen: “hoe zet ik dit vóór scrapy crawl als de credentials per run kunnen veranderen?”

import os
from urllib.parse import quote

class SecureProxyMiddleware:
    def __init__(self, user, password, host, port):
        self.user = quote(user, safe="")
        self.password = quote(password, safe="")
        self.host = host
        self.port = port

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(
            user=settings.get("PROXY_USER"),
            password=settings.get("PROXY_PASSWORD"),
            host=settings.get("PROXY_HOST"),
            port=settings.get("PROXY_PORT"),
        )

    def process_request(self, request, spider):
        proxy_url = f"http://{self.user}:{self.password}@{self.host}:{self.port}"
        request.meta["proxy"] = proxy_url

Let op de urllib.parse.quote()-aanroep rond de credentials. Als je wachtwoord een @, : of / bevat — en wachtwoordgeneratoren gooien die tekens er graag in — dan breekt de URL-parsing tenzij het eerst percent-encoded wordt. Dit is zo’n één-regel-fix die je een gênant uur debuggen bespaart van “invalid proxy URL”-fouten die niets met je proxy zelf te maken hebben.

Houd credentials uit logs en test percent-encoding met representatieve, maar neppe waarden. HTTPS-tunneling, SOCKS5 en niet-Latijnse credentials hebben handler-specifieke grenzen; ga er niet van uit dat een authenticatiepatroon overal werkt zonder een vastgepinde integratietest.

Veilige flow van een vergrendeld omgevingsbestand via gepercentencodeerde proxy-instellingen naar Scrapy request metadata

Stap 5: Voeg proxyrotatie toe

Zelfs een goede proxy die 5.000 requests naar dezelfde site stuurt, wordt uiteindelijk gemarkeerd. Je hebt een pool nodig.

Optie A — bouw het zelf. Dit is echt heel eenvoudig:

import random

class RotatingProxyMiddleware:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def process_request(self, request, spider):
        request.meta["proxy"] = random.choice(self.proxy_pool)

Dit werkt voor basaal gebruik, maar heeft geen enkel inzicht in welke proxies nog leven. Je gooit eigenlijk voor elke request de dobbelstenen.

Optie B — gebruik scrapy-rotating-proxies. Deze third-party package voegt standaard ban-detectie en automatische backoff toe:

pip install scrapy-rotating-proxies

Ik wil hier wel eerlijk over zijn: de laatste release op PyPI is versie 0.6.2 uit 2019, en het project is als Alpha getagd. Het is niet per se kapot op moderne Scrapy-versies, maar “niet actief onderhouden sinds 2019” is niet hetzelfde als “beproefd voor productieverkeer in 2026”. Pin de versie, test tegen je echte target-sites en ga er niet van uit dat het geauthenticeerde proxy-endpoints goed afhandelt — dat doet het grotendeels niet.

Stap 6: Bouw een fault-tolerant proxy middleware (detectie van dode proxies)

Dit is het onderdeel dat concurrenten meestal volledig overslaan, en het is precies het verschil tussen een demo en iets dat een crawl van 6 uur zonder toezicht overleeft.

ScenarioWat de meeste tutorials laten zienWat deze middleware toevoegt
Proxy geeft 407 terugNiet behandeldBehandelt dit als proxy-authenticatiefout
Target geeft 403/429 terugVaak op één hoop gegooidHoudt beleids-/ratefeedback gescheiden van proxygezondheid
Proxy time-outNiet behandeldInstelbare time-outdrempel, afbouw van health score
Alle proxies doodNiet behandeldGraceful fallback of crawl-pauze met gelogde waarschuwing
Proxy flapt (intermitterend)Niet behandeldAfkoelperiode vóór opnieuw toevoegen aan de pool
import time
import random
from scrapy.exceptions import IgnoreRequest

class FaultTolerantProxyMiddleware:
    MAX_FAILURES = 3
    COOLDOWN_SECONDS = 300

    def __init__(self, proxy_pool):
        self.pool = {p: {"failures": 0, "banned_until": 0} for p in proxy_pool}

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def _healthy_proxies(self):
        now = time.time()
        return [p for p, s in self.pool.items() if s["banned_until"] < now]

    def process_request(self, request, spider):
        healthy = self._healthy_proxies()
        if not healthy:
            spider.logger.warning("Alle proxies zijn ongezond — crawl wordt gepauzeerd")
            raise IgnoreRequest("Geen gezonde proxies beschikbaar")
        request.meta["proxy"] = random.choice(healthy)

    def process_response(self, request, response, spider):
        proxy = request.meta.get("proxy")
        if proxy and response.status == 407:
            self._mark_failure(proxy)
        return response

    def process_exception(self, request, exception, spider):
        proxy = request.meta.get("proxy")
        if proxy:
            self._mark_failure(proxy)

    def _mark_failure(self, proxy):
        state = self.pool[proxy]
        state["failures"] += 1
        if state["failures"] >= self.MAX_FAILURES:
            state["banned_until"] = time.time() + self.COOLDOWN_SECONDS
            state["failures"] = 0

Een paar opmerkingen uit de praktijk: behandel niet elke 403 als bewijs dat de proxy zelf dood is — RFC 9110 definieert 403 als “de server begreep het verzoek maar weigert het”, wat net zo goed kan betekenen dat je headers of sessie verdacht ogen, los van de proxy. Een 407 betekent daarentegen dat de proxy zelf je authenticatie afwijst — een sterker en specifieker signaal. Als je die signalen op één hoop gooit, verbrand je gezonde proxies zonder reden.

Maak Scrapy’s tijdelijke retry-defaults expliciet in productie, zodat reviewers het beleid kunnen zien:

RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
RETRY_TIMES = 2

Dit zijn de defaults van Scrapy 2.17. Voeg 403 of 407 niet zomaar toe: een 403 is een weigering door de target met meerdere mogelijke oorzaken, terwijl 407 een proxy-authenticatieprobleem is dat met generieke retries niet wordt opgelost. Als een specifiek targetcontract een andere status rechtvaardigt, documenteer die reden en test het apart.

Afzonderlijke afhandeling voor 407-authenticatiefout, 429 rate limiting, 503 retry, 200 succes en een gesloten poort wanneer proxies niet beschikbaar zijn

Stap 7: Een meetbaar proxy-bij-retry-patroon

Sommige geautoriseerde targets leveren direct geldige content en hebben alleen een proxy nodig na een gedocumenteerde tijdelijke fout. Dat kan het aantal geproxiede bytes verlagen, maar er bestaat geen verdedigbaar universeel besparingspercentage of overdraagbaar direct-succespercentage. Meet je eigen workload voordat je dit patroon gebruikt.

Gebruik Scrapy’s publieke get_retry_request()-helper en beperk escalatie tot targetspecifieke statussen die je expliciet hebt geclassificeerd. Dit voorbeeld behandelt 429 en 503 als herprobeerbare druksignalen; 403 en 407 worden bewust uitgesloten.

from scrapy.downloadermiddlewares.retry import get_retry_request

class CostAwareEscalationMiddleware:
    def process_response(self, request, response, spider):
        if response.status not in {429, 503}:
            return response

        retry = get_retry_request(
            request,
            spider=spider,
            reason=f"proxy_escalation_{response.status}",
            max_retry_times=2,
        )
        if retry is None:
            return response

        current_tier = request.meta.get("proxy_tier", "direct")
        if current_tier == "direct":
            retry.meta["proxy"] = spider.settings["DATACENTER_PROXY"]
            retry.meta["proxy_tier"] = "datacenter"
        elif current_tier == "datacenter":
            retry.meta["proxy"] = spider.settings["RESIDENTIAL_PROXY"]
            retry.meta["proxy_tier"] = "residential"
        else:
            return response
        return retry

Log het direct geldige-contentpercentage, het geproxiede geldige-contentpercentage, bytes per succesvol record, retries per succes en extra latency. Een direct-first ontwerp is alleen acceptabel wanneer directe toegang geautoriseerd is en het systeem fail-closed werkt zodra een proxy nodig is. De besparing is de gemeten daling in geproxied verkeer — niet een aangenomen percentage.

Wanneer zelf proxybeheer niet de moeite waard is

Ik wil hier eerlijk over zijn in plaats van te doen alsof de rest van dit artikel zinloos was: alles hierboven is echte, nuttige engineering, en voor veel projecten — crawls met hoge volumes, custom pipelines, alles waarbij je volledige controle over request scheduling nodig hebt — is dit gewoon de juiste keuze.

Maar als je echte doel is “gestructureerde data van deze pagina halen” in plaats van “proxy-infrastructuur beheren”, dan kan een extraction API een betere grens zijn. Thunderbit’s huidige POST /extract documentatie accepteert een pagina-URL en optioneel een JSON Schema; als je het schema weglaat, kan de service er zelf één genereren op basis van de pagina-inhoud. De endpoint biedt ook none, basic en full render-modi, plus instellingen voor time-out en wachten na laden. Prompt-only extractie maakt geen deel uit van de huidige ondersteunde request-surface, dus bouw productie-integraties rond het gedocumenteerde schema-contract. Dit verplaatst de extractie-interface achter één request; het is geen universele belofte voor elk anti-bot- of CAPTCHA-target.

FactorDIY Scrapy + proxiesAPI-gebaseerde extractie (bijv. Thunderbit)
OpzetinspanningHoog — middleware, rotatie, retry-logicaLaag — één API-call met een schema
Netwerk-/rendergedragJij configureert handlers, proxies, headers en delaysGereguleerd via gedocumenteerde API-opties
OnderhoudJij beheert selectors, poolgezondheid en targetwijzigingenJij beheert schema-kwaliteit, validatie en integratiegedrag
KostenmodelProxykosten + compute + engineeringtijdHuidige docs vermelden 20 units per pagina (gecontroleerd 2026-08-10)
ControleVolledig — custom pipelines, middleware-ketenBeperkt tot API-mogelijkheden
Het best voorComplexe crawls, hoge volumes, custom logicaGerichte extractie, prototyping, verrijking

Als je vooral gestructureerde pagina’s extraheert voor leadlijsten, productdata of onderzoek, doe dan een representatieve pilot met de Thunderbit Chrome Extension of de API en vergelijk valide records, latency, units en onderhoudstijd. Heeft je project custom crawl-graphs en pipelinecontrole nodig, dan blijft Scrapy de sterkere keuze.

Meer lezen

Tips en veelvoorkomende valkuilen

  • Tip: Test proxies eerst op httpbin.org/ip voordat je ze op een echte target loslaat. Dat is de snelste manier om te checken of routing werkt voordat je extra complexiteit toevoegt.
  • Valkuil: Een proxy instellen in request.headers in plaats van request.meta. Dit is een verrassend vaak voorkomende typfoutachtige bug — HttpProxyMiddleware leest alleen meta["proxy"], en een header-gebaseerde poging mislukt stilletjes zonder duidelijke fout.
  • Valkuil: Aannemen dat HTTP- en HTTPS-proxies identiek geconfigureerd worden. Een HTTP-proxy-URL die naar een HTTPS-doel routeert, werkt doorgaans via CONNECT-tunneling onder een compatibele handler, maar een https://-schema voor het proxy-endpoint zelf is een andere, minder goed ondersteunde configuratie — haal die twee niet door elkaar.
  • Tip: Als je SOCKS5-ondersteuning nodig hebt, check dan eerst de download-handler-mogelijkheden van je Scrapy-versie. Scrapy 2.17’s experimentele Httpx handler voegde SOCKS5-ondersteuning toe via httpx[socks], maar dit blijft experimenteel — bouw hier geen productieafhankelijkheid op zonder eigen tests.

Alternatieve methoden

Naast scrapy-rotating-proxies sturen sommige teams alle proxylogica via een provider-gateway: één proxy-URL waarbij de aanbieder rotatie, sessiestickiness en geo-targeting achter de schermen regelt. Dat geeft wat minder controle op, maar aanzienlijk minder middleware-code, en het is de moeite waard om de kosten te vergelijken met een zelf beheerde pool voordat je alles vanaf nul bouwt.

Conclusie

Een proxy instellen in Scrapy kost één regel. Maar die setup echt overeind houden tijdens een productie-crawl vraagt om expliciet foutbeleid, afgeschermde credentials, geteste handler-grenzen en selector-code die gekopieerde proxy-metadata bij een retry bewust vervangt. Neem twee gewoontes mee: fail closed wanneer een proxy vereist is, en commit nooit een proxywachtwoord in een Python-bestand.

FAQ’s

Hoe stel ik een custom proxy met authenticatie in Scrapy in?
Gebruik de URL-notatie protocol://username:password@host:port, maar percent-encode de gebruikersnaam en het wachtwoord eerst met urllib.parse.quote() als er speciale tekens in zitten. Lees die credentials in productie via een from_crawler-classmethod uit omgevingsvariabelen in plaats van ze hard te coderen.

Welke prioriteitswaarde moet ik gebruiken voor mijn custom proxy middleware in Scrapy?
350 is een veelgebruikte selectorprioriteit omdat die vóór HttpProxyMiddleware op 750 draait. Dat garandeert geen rotatie. Een retry krijgt pas een nieuwe proxy als de selector de gekopieerde retry-request herkent en de eerdere meta["proxy"]-waarde overschrijft.

Hoe handel ik dode proxies automatisch af in Scrapy?
Bouw een middleware die per proxy failure-counts bijhoudt in process_response en process_exception, proxies na een drempel uit de actieve pool haalt en ze na een afkoelperiode weer terugzet in plaats van ze permanent te blokkeren.

Kan ik Scrapy gebruiken met SOCKS5-proxies?
Scrapy 2.17’s experimentele HttpxDownloadHandler documenteert SOCKS5-ondersteuning wanneer httpx[socks] is geïnstalleerd. De standaard HTTP/1.1-handler ondersteunt geen SOCKS-proxies. Pin de handler en versie vast en voer een integratietest uit voordat je dit pad productiegeschikt noemt.

Hoeveel kan het proxy-bij-retry-patroon echt besparen op proxykosten?
Er is geen overdraagbaar percentage. Meet welk deel van de geautoriseerde requests direct geldige content oplevert, hoeveel bytes via elke proxylaag lopen, hoeveel retries er per succesvol record nodig zijn en hoeveel latency erbij komt. De geobserveerde daling in geproxied verkeer is je besparing; als direct-first toegang niet geautoriseerd of niet geldig is, gebruik dit patroon dan niet.

Ke
Ke
CTO bij Thunderbit | Senior Data Scientist & ML-expert Met bijna tien jaar ervaring in machine learning en data science is Ke Shen alumnus van Columbia University en voormalig Senior Data Scientist bij Walmart Labs. Met diepgaande, door vakgenoten erkende expertise in Python, R, Java en statistiek deelt hij praktijkgerichte inzichten over hoe je complexe AI-algoritmen van theorie naar productieklare architectuur brengt.
Topics
Scrapy proxy middlewarePython web scrapingProxyrotatie
Inhoudsopgave
Thunderbit · AI webdata-agent

Extraheer gegevens van elke pagina in 1 klik

Vertrouwd door meer dan 250.000 gebruikers
Gratis abonnement beschikbaar
Extraheer gegevens met AI
Zet gegevens eenvoudig over naar Google Sheets, Airtable of Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week