Configurazione proxy in Scrapy, usare IP diversi per ogni richiesta con meta proxy
Questa guida spiega come collegare i proxy HTTP di Socks5Proxy a Scrapy con meta proxy, ruotare le liste ricevute via API per ogni richiesta con un downloader middleware e impostare la velocità adatta al sito target.
Come gestisce i proxy Scrapy?
Scrapy ha HttpProxyMiddleware attivo di default. Aggiungendo l'indirizzo proxy alla chiave proxy nel meta della richiesta, questa uscirà tramite quel proxy, e username e password nell'indirizzo vengono convertiti dal middleware in header Proxy-Authorization. Gli indirizzi HTTPS passano attraverso un tunnel CONNECT.
Il gestore di download predefinito di Scrapy supporta proxy HTTP. Se serve SOCKS5, serve un gestore separato, quindi in Scrapy consigliamo di usare la porta HTTP dello stesso IP. Il sito target vedrà lo stesso IP.
L'esempio usa IP 198.51.100.23, porta HTTP 8000, username spx_user e password spx_pass.
pip install scrapy
scrapy startproject shop
cd shopCome inserisco un proxy in una singola richiesta?
Aggiungi proxy a meta quando crei Request in start_requests. Utilizza lo stesso metodo per aggiungere proxy quando richiedi la pagina successiva nel callback. Se devi mantenere la stessa sessione, passa il valore proxy da meta della risposta precedente per mantenere lo stesso IP.
import scrapy
PROXY = "http://spx_user:spx_pass@198.51.100.23:8000"
class IpCheckSpider(scrapy.Spider):
name = "ip_check"
def start_requests(self):
yield scrapy.Request("https://api.ipify.org?format=json", meta={"proxy": PROXY})
def parse(self, response):
self.logger.info("seen as %s", response.json()["ip"])Come ruoto l'IP per ogni richiesta?
Un middleware per lo scaricatore può ruotare i proxy senza modificare il codice dello spider. Questo middleware recupera la lista via API all'avvio e, se meta contiene già un proxy, lo mantiene per combinare sessioni fisse e rotazione.
Salva le chiavi API in settings.py o leggi da variabili d'ambiente. Registrale con un numero inferiore a HttpProxyMiddleware(750) per evitare che vengano sovrascritte.
import itertools
import requests
class RotatingProxyMiddleware:
def __init__(self, key):
text = requests.get(
"https://socks5proxy.io/api/v1/proxies/download",
params={"format": "user:pass@ip:port", "protocol": "http"},
headers={"Authorization": "Bearer " + key},
timeout=30,
).text
self.pool = itertools.cycle(["http://" + l.strip() for l in text.splitlines() if l.strip()])
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings.get("SPX_API_KEY"))
def process_request(self, request, spider):
if "proxy" not in request.meta: # keep a proxy that was set on purpose (sticky sessions)
request.meta["proxy"] = next(self.pool)SPX_API_KEY = "YOUR_API_KEY"
DOWNLOADER_MIDDLEWARES = {
"shop.middlewares.RotatingProxyMiddleware": 740,
}
CONCURRENT_REQUESTS = 32
CONCURRENT_REQUESTS_PER_DOMAIN = 16
DOWNLOAD_DELAY = 0.25
AUTOTHROTTLE_ENABLED = True
RETRY_TIMES = 3
RETRY_HTTP_CODES = [429, 500, 502, 503, 504, 522, 524, 408]
DOWNLOAD_TIMEOUT = 30Come si gestiscono velocità e tentativi di riconnessione?
CONCURRENT_REQUESTS_PER_DOMAIN è il numero di richieste simultanee allo stesso dominio. Con più proxy IP puoi aumentare questo valore senza sovraccaricare i singoli IP. Ad esempio, con 500 IP e 50 richieste simultanee, ogni IP viene usato in media una volta ogni 10 richieste.
AUTOTHROTTLE regola automaticamente l'intervallo tra richieste in base alla velocità di risposta. Con molti errori 429, usa RETRY_HTTP_CODES per riprovare, rimuovendo il proxy dai meta per usare il proxy successivo.
Includere un passaggio di verifica nella pipeline per controllare che i risultati raccolti siano pagine effettive e non di conferma migliora la qualità dei dati. Se una risposta manca degli elementi desiderati, puoi ripetere la richiesta con un IP diverso.
- Regola il numero di richieste simultanee per dominio in base al numero di IP
- Intervallo AUTOTHROTTLE basato sulla velocità di risposta
- 429 e 5xx: riprova con un IP diverso
- Filtra schermate di verifica controllando il contenuto della risposta
Cosa cambia quando ci si connette con l'autorizzazione IP?
Se registri l'IPv4 del server che esegue Scrapy nel dashboard, puoi usare il meta proxy senza username e password, ad esempio http://198.51.100.23:8000. Puoi anche scaricare l'elenco in formato ip:port. Se esegui spider su più server, registra gli IP di tutti i server, fino a un massimo di 10.
Come raggruppare richieste che richiedono sessione sotto lo stesso IP?
Per flussi che richiedono la continuità dei cookie, come l'accesso o il carrello, è necessario utilizzare lo stesso IP. Inserisci direttamente il meta proxy nella prima richiesta e passa il valore del proxy da response.meta nella richiesta successiva per evitare che il middleware ciclico lo cambi. Utilizzando anche la chiave meta cookiejar di Scrapy, i cookie vengono separati per ogni sessione.
Associando un proxy e un set di cookie a ciascuna sessione, puoi eseguire più sessioni contemporaneamente senza mescolarle.
import scrapy
PROXIES = [
"http://spx_user:spx_pass@198.51.100.23:8000",
"http://spx_user:spx_pass@198.51.100.24:8000",
]
class SessionSpider(scrapy.Spider):
name = "sessions"
def start_requests(self):
for i, proxy in enumerate(PROXIES):
yield scrapy.Request("https://example.com/", meta={"proxy": proxy, "cookiejar": i}, dont_filter=True)
def parse(self, response):
# follow-up request keeps the same proxy and the same cookie jar
yield response.follow("/account", meta={"proxy": response.meta["proxy"], "cookiejar": response.meta["cookiejar"]}, callback=self.parse_account)
def parse_account(self, response):
self.logger.info("status %s via %s", response.status, response.meta["proxy"])Come mettere temporaneamente in pausa un proxy fallito?
Nel middleware process_response, se ricevi una risposta 403 o 429, puoi far riposare quel proxy per alcuni minuti e inviare la stessa richiesta con un altro proxy. Copia la richiesta, rimuovi il proxy dai meta, attiva dont_filter e restituiscila per far sì che il proxy successivo prenda il suo posto.
Gestire l'elenco dei proxy in pausa e l'orario di riutilizzo è semplice. Non riutilizzare immediatamente lo stesso IP permette di ridurre i tempi di blocco del sito target.
Quali impostazioni usare in Scrapy per risparmiare banda?
Scrapy riceve solo HTML per impostazione predefinita, usando molta meno banda rispetto agli strumenti browser. Inoltre HttpCompressionMiddleware è attivo di default per risposte compresse, riducendo ulteriormente il traffico. Ecco perché puoi raccogliere molte pagine entro la banda mensile dei piani condivisi.
Per evitare di ricevere più volte la stessa pagina, attiva HTTPCACHE_ENABLED durante lo sviluppo per non sovraccaricare il sito target e il proxy durante i test. In produzione, mantieni il filtro duplicati (attivo di default) e usa dont_filter solo per richieste che devono essere ripetute.
È importante limitare l'ambito dei link per evitare di espandersi in pagine secondarie non necessarie. Definire chiaramente l'ambito della raccolta riduce il tempo, la larghezza di banda e il carico sul sito di destinazione.
Come risolvere i problemi più comuni?
Se ricevi 407, controlla username e password nell'URL. Se la password ha caratteri speciali, codificali con percent encoding. TunnelError significa che il proxy non ha ricevuto la richiesta CONNECT: verifica che la porta sia quella HTTP.
Se tutte le richieste vengono inviate dallo stesso IP, potrebbe essere perché l'ordine del middleware è dopo HttpProxyMiddleware o perché il meta proxy è impostato direttamente nello spider. Controlla l'ordine in settings.py e il codice dello spider.