Se ti occupi di scraping di marketplace, monitoraggio dei prezzi dei concorrenti o raccolta di dati dai siti, conosci il problema: i siti bloccano gli indirizzi IP, richiedono CAPTCHA o restituiscono pagine vuote. Il tasso di ban (percentuale di richieste bloccate) può raggiungere il 70-90%, rendendo impossibile il parsing. In questo articolo esamineremo metodi specifici che possono aiutarti a ridurre il tasso di ban al 5-10% e raccogliere dati in modo stabile.
Considereremo sia soluzioni tecniche (rotazione dei proxy, intestazioni HTTP, fingerprinting) che modelli comportamentali (ritardi, imitazione delle azioni dell'utente). Tutti i metodi sono stati testati nella pratica durante il parsing di Wildberries, Ozon, Avito e piattaforme estere.
Perché i siti bloccano i parser: i principali trigger
Prima di esaminare i metodi di protezione, è importante capire come i siti identificano il traffico automatizzato. I moderni sistemi anti-bot (Cloudflare, Akamai, DataDome, Imperva) analizzano decine di parametri di ogni richiesta. Ecco i principali trigger di blocco:
Trigger a livello di rete:
- Troppi richieste da un unico indirizzo IP (ad esempio, oltre 100 richieste al minuto)
- IP da intervalli noti di data center (AWS, Google Cloud, Hetzner)
- Incongruenza geografica: IP dalla Russia richiede la versione inglese del sito
- Assenza di un record DNS inverso per l'indirizzo IP
Trigger a livello HTTP:
- Assenza o intestazioni HTTP errate (User-Agent, Accept-Language, Referer)
- Ordine delle intestazioni diverso da quello standard per i browser
- Versione TLS/SSL non corrisponde al browser dichiarato
- Assenza di cookies o utilizzo errato degli stessi
Trigger a livello di browser (JavaScript):
- Assenza di esecuzione di JavaScript (se utilizzi un semplice client HTTP)
- Browser fingerprinting: Canvas, WebGL, AudioContext, font installati
- Assenza di movimento del mouse, scrolling, clic
- Dimensione della finestra del browser (i browser headless spesso hanno dimensioni non standard)
- Presenza di automazione: proprietà navigator.webdriver, window.chrome
Trigger comportamentali:
- Navigazione troppo rapida tra le pagine (meno di 1 secondo)
- Intervalli identici tra le richieste (ad esempio, esattamente ogni 2 secondi)
- Visita sequenziale delle pagine (1, 2, 3, 4...) senza salti
- Assenza di azioni tipiche dell'utente: ricerca, filtri, visualizzazione delle immagini
Ad esempio, durante il parsing di Wildberries, un errore tipico è inviare richieste ogni 0.5 secondi da un unico IP. Il sistema anti-bot Cloudflare identificherà immediatamente il modello e bloccherà l'IP per 24 ore. Un utente reale impiega 5-15 secondi per visualizzare una scheda prodotto, scorre la pagina, clicca sulle immagini.
Rotazione dei proxy: come cambiare correttamente gli indirizzi IP
L'uso di proxy è un metodo di base per ridurre il tasso di ban. Ma è importante non solo acquistare proxy, ma anche configurare correttamente la rotazione. Ecco strategie collaudate:
Scelta del tipo di proxy per il parsing
| Tipo di proxy | Tasso di ban | Velocità | Quando utilizzare |
|---|---|---|---|
| Proxy di data center | Alto (40-60%) | Molto alta | Siti semplici senza protezione, scraping di massa con un ampio pool di IP |
| Proxy residenziali | Basso (5-15%) | Media | Marketplace (Wildberries, Ozon), siti con Cloudflare, social media |
| Proxy mobili | Molto basso (2-8%) | Bassa | Siti con protezione aggressiva, versioni mobili delle applicazioni |
Per il parsing di marketplace (Wildberries, Ozon, Avito) si raccomandano i proxy residenziali: hanno IP di utenti domestici reali, che sono difficili da distinguere dal traffico normale. I proxy di data center sono adatti per siti meno protetti o quando è necessaria la massima velocità con un grande volume di dati.
Strategie di rotazione degli indirizzi IP
Strategia 1: Rotazione temporale
Cambia IP ogni 5-10 minuti. Questo è un equilibrio ottimale: abbastanza lungo da non suscitare sospetti per un cambio frequente, ma abbastanza breve da non accumulare una cronologia di richieste su un unico IP.
Esempio: Durante il parsing di un catalogo di 1000 prodotti con un intervallo di 3 secondi tra le richieste, un IP sarà attivo per circa 100 richieste, quindi avviene il cambio.
Strategia 2: Rotazione per numero di richieste
Cambia IP dopo 50-150 richieste. Questo aiuta a evitare l'accumulo di attività sospette su un unico indirizzo. Aggiungi casualità: non esattamente 100 richieste, ma da 80 a 120.
Esempio: Configura lo script in modo che dopo un numero casuale di richieste (80-120) avvenga la rotazione dei proxy dal pool.
Strategia 3: Sticky sessions (proxy di sessione)
Per i siti che richiedono autenticazione o che lavorano con il carrello, utilizza sticky sessions: fissare l'IP per la durata della sessione (10-30 minuti). Questo consente di mantenere i cookies e non suscitare sospetti durante il cambio di IP all'interno di una singola sessione.
Esempio: Durante il parsing dell'area personale su Ozon, utilizza un IP per l'accesso e tutte le richieste successive nell'ambito di una sessione di 15 minuti.
Importante: Non utilizzare lo stesso IP per compiti diversi. Se l'IP è stato bloccato durante il parsing di un sito, non usarlo subito per un altro - aspetta 24-48 ore.
Dimensione del pool di proxy
La dimensione minima del pool dipende dall'intensità del parsing:
- Bassa intensità (fino a 10.000 richieste al giorno): 10-20 proxy
- Intensità media (10.000 - 100.000 richieste al giorno): 50-100 proxy
- Alta intensità (oltre 100.000 richieste al giorno): 200+ proxy o residenziali con rotazione automatica
Per i proxy residenziali con rotazione per ogni richiesta (rotating proxies) la dimensione del pool può essere minore, poiché il fornitore inserisce automaticamente un nuovo IP dal proprio pool di milioni di indirizzi.
User-Agent e intestazioni HTTP: imitazione di un browser reale
Anche con buoni proxy, potresti essere bloccato se le intestazioni HTTP sembrano sospette. I siti analizzano non solo l'User-Agent, ma anche l'ordine delle intestazioni, i loro valori e la corrispondenza tra di esse.
Corretto User-Agent
Non utilizzare lo stesso User-Agent per tutte le richieste. Crea un elenco di browser popolari e scegli casualmente da esso:
user_agents = [
# Chrome su Windows
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
# Chrome su macOS
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
# Firefox su Windows
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
# Safari su macOS
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
# Edge su Windows
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
]
Errore: Utilizzare versioni obsolete dei browser (ad esempio, Chrome 80) susciterà immediatamente sospetti. Aggiorna l'elenco degli User-Agent ogni 2-3 mesi, monitorando le versioni attuali su whatismybrowser.com.
Set completo di intestazioni HTTP
I moderni browser inviano 15-20 intestazioni. Ecco il set minimo necessario per imitare Chrome:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
"Accept-Encoding": "gzip, deflate, br",
"DNT": "1",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Cache-Control": "max-age=0",
"sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"'
}
Fai attenzione alle intestazioni Sec-Fetch-* e sec-ch-ua-* - sono apparse nelle nuove versioni di Chrome e la loro assenza può rivelare l'automazione.
L'ordine delle intestazioni è importante
I browser inviano le intestazioni in un ordine specifico. Ad esempio, Chrome posiziona sempre Host per primo, seguito da Connection, User-Agent e così via. Se utilizzi la libreria Python requests, l'ordine potrebbe essere alfabetico, il che rivelerebbe l'automazione.
Soluzione: utilizza librerie che formano correttamente le intestazioni (curl_cffi per Python, got per Node.js) o browser headless (Puppeteer, Playwright, Selenium) che generano intestazioni come un vero browser.
Ritardi tra le richieste: intervalli ottimali
Uno dei metodi più semplici ma efficaci per ridurre il tasso di ban è impostare correttamente i ritardi tra le richieste. Un utente reale non può aprire 10 pagine al secondo, quindi richieste troppo rapide provocano immediatamente un blocco.
Ritardi casuali invece di fissi
Non utilizzare un ritardo fisso (ad esempio, esattamente 2 secondi tra le richieste). I sistemi anti-bot identificano facilmente tale modello. Utilizza un intervallo casuale:
import random
import time
# Invece di un ritardo fisso
time.sleep(2) # ❌ Male
# Utilizza un intervallo casuale
delay = random.uniform(2.5, 5.5) # ✅ Bene
time.sleep(delay)
Intervalli raccomandati per diversi siti
| Tipo di sito | Ritardo minimo | Ritardo raccomandato | Esempi |
|---|---|---|---|
| Marketplace con protezione | 3-5 sec | 5-10 sec | Wildberries, Ozon, Lamoda |
| Siti di annunci | 2-4 sec | 4-8 sec | Avito, Yula, CIAN |
| Siti di notizie | 1-2 sec | 2-4 sec | RBC, Kommersant, Vedomosti |
| API senza limiti | 0.5-1 sec | 1-2 sec | API aperti, feed RSS |
Ritardi adattivi basati sulle risposte del server
Un approccio avanzato è modificare dinamicamente i ritardi in base alle risposte del server:
base_delay = 3.0 # Ritardo di base
delay_multiplier = 1.0
response = requests.get(url, headers=headers, proxies=proxies)
# Se riceviamo un CAPTCHA o 429 - aumentiamo il ritardo
if response.status_code == 429 or 'captcha' in response.text.lower():
delay_multiplier *= 1.5
print(f"Protezione rilevata, aumentiamo il ritardo a {base_delay * delay_multiplier}sec")
# Se va tutto bene - possiamo accelerare un po'
elif response.status_code == 200:
delay_multiplier = max(1.0, delay_multiplier * 0.95)
time.sleep(random.uniform(base_delay * delay_multiplier, base_delay * delay_multiplier * 1.5))
Questo approccio consente di rallentare automaticamente quando viene rilevata una protezione e di accelerare quando il sito non mostra aggressività.
Protezione dal fingerprinting: Canvas, WebGL, font
Se un sito utilizza JavaScript per il controllo, le semplici intestazioni HTTP non sono sufficienti. I moderni sistemi anti-bot creano un "impronta" del browser (fingerprint) basata su decine di parametri: Canvas, WebGL, font installati, fuso orario, risoluzione dello schermo e altri.
Principali parametri del fingerprinting
Canvas fingerprinting
Il sito disegna un'immagine invisibile nel Canvas e la legge. Diversi browser e sistemi operativi rendono l'immagine in modo diverso, creando un'impronta unica. I browser headless spesso generano lo stesso Canvas, rivelando l'automazione.
WebGL fingerprinting
Simile al Canvas, ma utilizza il rendering 3D. Viene letta l'informazione sulla scheda video, i driver, le estensioni supportate. I browser headless spesso mostrano il rendering software (SwiftShader) invece della vera GPU.
Font installati
JavaScript può determinare l'elenco dei font installati. I browser headless di solito hanno un set minimo di font di sistema, che differisce da un utente reale con Microsoft Office, Adobe e altri programmi installati.
Proprietà del navigator
Le proprietà navigator.webdriver, navigator.plugins, navigator.languages rivelano l'automazione. Ad esempio, in Selenium navigator.webdriver === true, il che viene immediatamente identificato dai sistemi anti-bot.
Strumenti per superare il fingerprinting
Per superare il fingerprinting, utilizza strumenti specializzati:
- Undetected ChromeDriver (Python) - versione modificata di Selenium che nasconde i segni di automazione
- Puppeteer Stealth (Node.js) - plugin per Puppeteer che sostituisce i parametri del fingerprint
- Playwright con stealth - simile a Puppeteer, ma con un migliore supporto per diversi browser
- Browser anti-detect (Dolphin Anty, AdsPower, Multilogin) - per chi non vuole scrivere codice, questi browser sostituiscono automaticamente il fingerprint
Esempio di utilizzo di undetected-chromedriver in Python:
import undetected_chromedriver as uc
# Creiamo un browser con protezione contro il rilevamento
options = uc.ChromeOptions()
options.add_argument('--disable-blink-features=AutomationControlled')
driver = uc.Chrome(options=options)
driver.get('https://example.com')
# Verifichiamo che navigator.webdriver === undefined
webdriver_status = driver.execute_script("return navigator.webdriver")
print(f"navigator.webdriver: {webdriver_status}") # Dovrebbe essere None/undefined
Gestione di cookies e sessioni
Molti siti utilizzano cookies per monitorare il comportamento degli utenti. Una corretta gestione dei cookies aiuta a evitare blocchi e a sembrare un utente reale.
Salvataggio e riutilizzo dei cookies
Invece di creare una nuova sessione per ogni richiesta, salva i cookies e riutilizzali. Questo imita il comportamento di un utente reale che torna sul sito:
import requests
import pickle
session = requests.Session()
# Prima visita - otteniamo i cookies
response = session.get('https://example.com')
# Salviamo i cookies in un file
with open('cookies.pkl', 'wb') as f:
pickle.dump(session.cookies, f)
# Più tardi carichiamo i cookies
with open('cookies.pkl', 'rb') as f:
session.cookies.update(pickle.load(f))
# Ora le richieste sembrano provenire da un utente tornato
response = session.get('https://example.com/catalog')
Riscaldamento della sessione prima del parsing
Non iniziare il parsing direttamente dalle pagine target. Imita il comportamento di un utente reale:
- Apri la homepage del sito
- Aspetta 2-5 secondi
- Apri la pagina di categoria o sezione
- Aspetta 3-7 secondi
- Solo dopo inizia a fare parsing delle pagine target
Questo crea una cronologia di attività nei cookies e riduce la probabilità di blocco.
Gestione dei session cookies e dei token
Alcuni siti generano token unici alla prima visita e li verificano nelle richieste successive. Ad esempio, Wildberries utilizza un token nell'intestazione x-requested-with. Salva sempre tali token dalla prima risposta e inviali nelle richieste successive.
Rendering JavaScript: quando è necessario
Molti siti moderni caricano contenuti tramite JavaScript. Se utilizzi un semplice client HTTP (requests in Python, axios in Node.js), riceverai una pagina vuota o un segnaposto. In questi casi, è necessario il rendering di JavaScript.
Quando è necessario il rendering di JavaScript
- Il sito utilizza React, Vue, Angular - il contenuto viene caricato dopo il caricamento iniziale della pagina
- I dati vengono caricati tramite richieste AJAX/Fetch
- Il sito richiede l'esecuzione di JavaScript per generare token o cookies
- È presente una protezione contro i bot che richiede l'esecuzione di codice JS (ad esempio, Cloudflare Challenge)
Strumenti per il rendering di JavaScript
| Strumento | Lingua | Velocità | Superamento della protezione |
|---|---|---|---|
| Selenium | Python, Java, C# | Lenta | Media (con undetected-chromedriver) |
| Puppeteer | Node.js | Media | Buona (con puppeteer-extra-plugin-stealth) |
| Playwright | Python, Node.js, Java | Veloce | Ottima |
| Splash | HTTP API | Media | Debole |
Per la maggior parte delle attività, si raccomanda Playwright: è più veloce di Selenium, supera meglio la protezione e ha un'API più comoda.
Alternativa: intercettazione delle richieste API
Spesso è possibile evitare il rendering di JavaScript se trovi le richieste API che il sito utilizza per caricare i dati. Apri DevTools (F12) → scheda Network → filtro XHR/Fetch e guarda quali richieste invia il sito. Poi ripeti queste richieste direttamente tramite il client HTTP.
Esempio: Wildberries carica i dati dei prodotti tramite API https://catalog.wb.ru/catalog/.... Invece di eseguire il rendering dell'intera pagina, puoi richiedere direttamente questa API, il che è 10-20 volte più veloce.
Superamento del CAPTCHA: soluzioni automatiche
Anche con proxy e intestazioni corretti, potresti incontrare un CAPTCHA. Esistono diversi approcci per risolverlo:
Tipi di CAPTCHA e metodi di risoluzione
reCAPTCHA v2 (casella "Non sono un robot")
Si risolve tramite servizi di riconoscimento: 2Captcha, Anti-Captcha, CapMonster. Costo: $1-3 per 1000 soluzioni. Tempo di risoluzione: 10-30 secondi.
reCAPTCHA v3 (invisibile, basata su punteggio)
Più complessa. Analizza il comportamento dell'utente e assegna un punteggio da 0 a 1. Superamento: utilizzo di browser headless con fingerprint corretto + imitazione delle azioni dell'utente (movimento del mouse, clic).
hCaptcha
Analogo di reCAPTCHA, utilizzato su molti siti. Si risolve tramite gli stessi servizi di riconoscimento. Costo: $0.5-2 per 1000 soluzioni.
Cloudflare Challenge
Sfida JavaScript che verifica il browser. Superamento: utilizzo di librerie specializzate (cloudscraper per Python, cloudflare-scraper per Node.js) o servizi (FlareSolverr).
Integrazione del servizio di riconoscimento CAPTCHA
Esempio di integrazione di 2Captcha in Python:
from twocaptcha import TwoCaptcha
solver = TwoCaptcha('YOUR_API_KEY')
try:
# Risolviamo reCAPTCHA v2
result = solver.recaptcha(
sitekey='6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
url='https://example.com'
)
# Otteniamo il token di soluzione
captcha_token = result['code']
# Inviamo il modulo con il token
response = requests.post('https://example.com/submit', data={
'g-recaptcha-response': captcha_token
})
except Exception as e:
print(f"Errore nella risoluzione del CAPTCHA: {e}")
Importante: Risolvere il CAPTCHA rallenta il parsing di 10-30 volte e aumenta i costi. Utilizzalo solo quando altri metodi non funzionano. Prima prova a migliorare i proxy, il fingerprint e i ritardi.
Rate limiting: come non superare i limiti del sito
Molti siti hanno limiti espliciti o impliciti sul numero di richieste. Superare questi limiti porta a un blocco temporaneo o permanente dell'IP.
Determinazione dei limiti del sito
Fai attenzione alle intestazioni HTTP nelle risposte del server:
X-RateLimit-Limit- numero massimo di richieste in un periodoX-RateLimit-Remaining- quante richieste rimangonoX-RateLimit-Reset- quando il limite verrà azzerato (timestamp Unix)Retry-After- dopo quanti secondi è possibile ripetere la richiesta
Se ricevi un codice di stato 429 (Troppe richieste), ciò significa che hai superato il limite. Leggi l'intestazione Retry-After e aspetta il tempo indicato prima della prossima richiesta.
Implementazione di un rate limiter
Crea un meccanismo di controllo della velocità delle richieste: