Scraping educato che scala: un manuale sul rate-limiting

Martellare un sito ti fa bannare; effettuare il crawling di una richiesta alla volta non ti porta da nessuna parte. La via di mezzo scalabile è un ritmo adattivo per dominio, distribuito su IP puliti — educato per il sito, veloce per te.

Quasi la metà di tutto il traffico internet è ora automatizzato, e i siti web lo sanno. Il rate limiting è la loro prima e più basilare difesa — un limite di velocità che decide quanto puoi prendere e quanto velocemente. La tentazione è trattarlo come un ostacolo da superare con la forza bruta, ma questo ti fa bannare. L'errore opposto, effettuare il crawling di una richiesta alla volta con attenzione, non ti porta da nessuna parte su larga scala. La risposta scalabile è scraping educato: regola il ritmo di ogni obiettivo come farebbe un utente legittimo ma pesante, distribuisci il carico su IP puliti e lascia che le risposte del sito regolino la tua velocità. Questo è il modo per rimanere veloci senza diventare il traffico che blocca tutti.

Sapere quale limite stai colpendo

I server contano le tue richieste rispetto a un identificatore — di solito il tuo IP, a volte una chiave API o un account — su una finestra temporale, e agiscono quando superi una soglia. I tre modelli comuni si comportano diversamente: una finestra fissa conta le richieste per minuto di calendario; un token bucket ti consegna un numero fisso di token (ad esempio 100 al minuto) e ne spende uno per richiesta, costringendoti ad aspettare quando il secchio si svuota; una finestra scorrevole conta sugli ultimi 60 secondi mobili in qualsiasi istante. Il risultato pratico è che un picco è più pericoloso di un flusso costante — dieci richieste in un secondo possono superare un limite che cento distribuite su un minuto non supererebbero.

I limiti hanno anche diverse sfumature. I limiti soft sono gentili: il server ti rallenta, o restituisce 429 Too Many Requests con un header Retry-After che ti dice esattamente quanto tempo aspettare (l'Errore 1015 di Cloudflare è questo). Alcuni siti tollerano piccoli picchi — permettendo 100 al minuto ma limitando solo a 120 — mentre altri limitano presto, ad esempio a 15 al minuto, e bloccano duramente solo a 30. I limiti hard sono soglie rigide: un'API che permette 1.000 richieste all'ora ti blocca completamente una volta superato il limite. Spingere ripetutamente un limite soft lo fa aumentare: 429 diventa 403, poi un ban temporaneo di minuti o ore la cui finestra cresce ogni volta che lo superi, e infine una blacklist permanente del tuo IP o dell'intera subnet.

Leggi la risposta, non indovinare

Il miglior upgrade per uno scraper è reagire a ciò che il server ti dice invece di sparare a una velocità fissa. Impara il vocabolario: 429 significa rallentare e rispettare Retry-After; 403 significa che questa identità è segnalata, quindi ruota invece di riprovare; 503 è spesso una sfida o un rifiuto temporaneo; e un 200 che restituisce una pagina CAPTCHA è un blocco soft, non un successo. Tratta ciascuno in modo diverso. La mossa sbagliata — riprovare lo stesso IP bruciato su un 403, o ignorare Retry-After e insistere su un 429 — è ciò che trasforma un avviso soft in un ban permanente. I nostri approfondimenti su come risolvere i 429 coprono in dettaglio la gestione delle risposte.

import time, requests

def polite_get(session, url, max_tries=4):
    for attempt in range(max_tries):
        r = session.get(url, timeout=20)
        if r.status_code == 200 and "captcha" not in r.text.lower():
            return r
        if r.status_code == 429:                       # obey the server
            wait = int(r.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        if r.status_code in (403, 503):                # this exit is burned
            rotate_ip(session)                         # fresh IP, then retry
            time.sleep(2 ** attempt)                    # exponential backoff
            continue
        return r
    return None
Diagramma di un ciclo di ritmo adattivo che invia una richiesta, legge il codice di stato, ruota l'IP e rallenta, quindi regola il ritmo
Lascia che i codici di risposta del sito guidino la tua velocità: accelera sui 200, rispetta Retry-After sui 429, ruota sui 403.

Pianifica le richieste per dominio

Un crawler che tocca molti siti non dovrebbe mai applicare un unico ritmo globale a tutti. Un piccolo blog e un marketplace rinforzato tollerano carichi molto diversi, quindi assegna a ciascun dominio il proprio budget. Un token bucket per host è il modello pulito: assegna un ritmo conservativo per dominio, ricaricalo nel tempo e lascia che le richieste a diversi host funzionino in parallelo mentre le richieste allo stesso host rimangono entro il suo limite. Inizia lentamente su un nuovo obiettivo e lascia che i codici di risposta ti dicano se puoi accelerare.

import time
from collections import defaultdict

class DomainLimiter:
    def __init__(self, per_min=30):
        self.gap = 60.0 / per_min          # min seconds between hits per host
        self.last = defaultdict(float)
    def wait(self, host):
        now = time.time()
        delay = self.gap - (now - self.last[host])
        if delay > 0:
            time.sleep(delay)
        self.last[host] = time.time()

# 30 req/min to any single host; different hosts proceed independently
limiter = DomainLimiter(per_min=30)
limiter.wait("example.com")

Distribuisci il carico in modo che ogni IP rimanga educato

Ecco la mossa che riconcilia "educato" con "scala": l'educazione si misura per IP, ma il tuo throughput totale è la somma su IP. Se un obiettivo tollera 30 richieste al minuto per indirizzo, un IP ti limita a 30 — ma dieci IP puliti, ciascuno che fa 30, ti danno 300 al minuto mentre ogni singola uscita rimane cortese. Un gateway residenziale rotante fa questo automaticamente, fornendo un IP fresco per richiesta su oltre 90M+ indirizzi in modo che nessuna uscita singola sembri aggressiva. Questo non è un trucco per martellare più forte; è distribuire un carico genuino in modo che nessun server sopporti un picco sospetto. I fondamenti della rotazione IP sono in cosa è la rotazione IP e perché è importante.

Distribuisci il carico su IP rotanti puliti

Prendi meno, memorizza di più, scegli le tue ore

La richiesta più educata è quella che non invii mai. Tre abitudini riducono il carico senza costarti dati. Primo, memorizza in modo aggressivo e usa richieste condizionali — invia If-Modified-Since o If-None-Match in modo che una pagina invariata restituisca un piccolo 304 invece del corpo completo, risparmiando il server e la tua larghezza di banda. Secondo, pianifica la concorrenza deliberatamente: un semaforo che limita le richieste in volo per dominio ti impedisce di esplodere accidentalmente. Terzo, programma lavori pesanti per le ore di bassa attività dell'obiettivo, quando il tuo traffico è una parte minore del loro e meno probabile di superare una soglia. Combinati, questi possono dimezzare le richieste necessarie per un lavoro — la disciplina dietro la nostra più ampia lista di controllo anti-ban.

Un'altra cosa che vale la pena dire chiaramente: controlla robots.txt e rispetta le aspettative di crawling dichiarate di un sito. L'educazione non è solo autoconservazione — essere un buon cittadino mantiene il web aperto e accessibile per tutti. La nostra guida su robots.txt in pratica copre cosa vincola e cosa no.

Diagramma della scala di escalation da un limite soft 429 fino a 403, un ban temporaneo e una blacklist permanente di IP o subnet
Spingi ripetutamente un limite soft e si indurisce: 429 diventa 403, poi un ban temporaneo crescente, poi una blacklist permanente.

Domande frequenti

Come evito il rate limiting nello scraping?

Regola il ritmo di ogni dominio con il proprio budget di richieste, rispetta Retry-After sui 429, rallenta esponenzialmente e distribuisci il carico su un pool rotante di IP puliti in modo che nessun singolo indirizzo sembri aggressivo. Aggiungi caching e richieste condizionali per inviare meno richieste in totale e programma lavori pesanti per le ore di bassa attività dell'obiettivo.

Cosa significa HTTP 429 e come dovrei gestirlo?

429 Too Many Requests è un limite di velocità soft — il server ti chiede di rallentare, non ti sta bannando. Leggi l'header Retry-After e aspetta esattamente quel tempo prima di riprovare; se è assente, rallenta esponenzialmente. Non ignorarlo mai e continuare a martellare, perché ripetuti 429 si trasformano in 403 e poi in ban temporanei o permanenti.

Quante richieste al minuto sono sicure?

Non esiste un numero universale — dipende interamente dall'obiettivo. Un sito piccolo può tollerare solo poche richieste al minuto; uno grande, molte di più. Inizia in modo conservativo (diciamo 20–30 al minuto per IP), osserva i 429 e regola in base alle risposte. Scala il throughput totale aggiungendo IP, non aumentando il ritmo su uno solo.

I proxy rotanti sono considerati scortesi?

Non quando vengono usati per distribuire un carico genuino. La rotazione mantiene ogni singolo IP entro un ritmo cortese mentre il tuo throughput aggregato cresce — il server non vede mai un picco sospetto da un singolo indirizzo. Diventa scortese solo se lo usi per superare ciò che il sito può ragionevolmente gestire in totale; regola l'aggregato, non solo il ritmo per IP.

Educato e scalabile non sono opposti. Leggi i segnali, rispetta Retry-After, pianifica per dominio, memorizza ciò che puoi e distribuisci il resto su IP rotanti puliti. Finisci per essere più veloce dello scraper sconsiderato — perché sei quello che non viene mai bannato.

Scala educatamente con proxy residenziali rotanti