Configurazione proxy in Python requests, collegamento di proxy SOCKS5 e HTTP
Questa guida spiega passo passo come collegare i proxy HTTP e SOCKS5 di Socks5Proxy alla libreria Python requests, autenticazione con username e password, codice per ruotare liste e riprovare.
Cosa preparare?
Sono necessari Python 3.8 o superiore e la libreria requests. Per usare SOCKS5, devi installare anche il pacchetto di supporto SOCKS. Installando requests[socks], PySocks viene installato automaticamente, permettendo di usare indirizzi socks5 e socks5h.
Le informazioni sul proxy sono disponibili nella schermata 'I miei proxy' del dashboard. In questo esempio, usiamo IP 198.51.100.23, porta HTTP 8000, porta SOCKS5 1080, username spx_user e password spx_pass. Sostituisci con i valori effettivi.
pip install "requests[socks]"Come ci si connette a un proxy HTTP?
requests invia le richieste attraverso il proxy se l'indirizzo è aggiunto al dizionario proxies. È importante inserire lo stesso indirizzo proxy HTTP per le chiavi http e https. Se manca la chiave https, le richieste HTTPS non passano attraverso il proxy.
Le richieste ai siti HTTPS passano attraverso il proxy tramite il metodo CONNECT, mantenendo i dati crittografati dall'inizio alla fine. Il codice seguente richiede un indirizzo di verifica IP e controlla se l'IP del proxy appare nella risposta.
import requests
proxy = "http://spx_user:spx_pass@198.51.100.23:8000"
proxies = {"http": proxy, "https": proxy}
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.status_code, r.json()) # the "ip" field should show the proxy IPCome si connette un proxy SOCKS5?
Per SOCKS5 consigliamo di usare il prefisso socks5h. socks5h fa risolvere i nomi di dominio dal lato proxy, evitando che le richieste DNS del tuo server siano esposte e risolvendo i nomi in base al paese del proxy. Usando socks5, la risoluzione avviene sul tuo server e solo l'IP viene inviato al proxy.
Devi utilizzare la porta SOCKS5. Se inserisci un indirizzo SOCKS5 nella porta HTTP, la connessione non funzionerà.
import requests
proxy = "socks5h://spx_user:spx_pass@198.51.100.23:1080"
proxies = {"http": proxy, "https": proxy}
r = requests.get("https://api.ipify.org?format=json", proxies=proxies, timeout=20)
print(r.json())Come ruotare più proxy per le richieste?
Quando raccogli molte pagine, il metodo di base è ricevere una lista e utilizzare il proxy successivo per ogni richiesta. Il codice seguente riceve una lista SOCKS5 tramite API e utilizza i proxy in sequenza, riprovando fino a 3 volte con un proxy diverso in caso di fallimento. È stato aggiunto anche un breve intervallo di pausa per evitare di inviare richieste troppo velocemente allo stesso dominio.
Invece di scartare subito un proxy fallito, è meglio metterlo in pausa e riprovare più tardi. Spesso gli errori temporanei dipendono dallo stato del sito di destinazione.
import itertools
import time
import requests
API = "https://socks5proxy.io/api/v1"
KEY = "YOUR_API_KEY"
lines = requests.get(
API + "/proxies/download",
params={"format": "user:pass@ip:port", "protocol": "socks5"},
headers={"Authorization": "Bearer " + KEY},
timeout=30,
).text.split()
pool = itertools.cycle(lines)
def fetch(url, tries=3):
for _ in range(tries):
p = "socks5h://" + next(pool)
try:
r = requests.get(url, proxies={"http": p, "https": p}, timeout=20)
if r.status_code == 200:
return r.text
except requests.RequestException:
pass
time.sleep(1)
return None
for page in range(1, 6):
html = fetch("https://example.com/list?page=" + str(page))
print(page, "ok" if html else "failed")
time.sleep(0.5)Come mantenere sessioni e cookie?
Per flussi che richiedono la continuità dei cookie, come l'accesso o la navigazione tra pagine, utilizza una requests.Session con un proxy fisso. Inserisci l'indirizzo nella proprietà proxies dell'oggetto sessione per far sì che tutte le richieste della sessione utilizzino lo stesso IP. Chiudi la sessione al termine del flusso e crea una nuova sessione con il proxy successivo.
Impostando anche header User-Agent e Accept-Language per sessione, l'aspetto verso i siti target sarà consistente.
import requests
s = requests.Session()
s.proxies = {
"http": "http://spx_user:spx_pass@198.51.100.23:8000",
"https": "http://spx_user:spx_pass@198.51.100.23:8000",
}
s.headers.update({"User-Agent": "Mozilla/5.0", "Accept-Language": "en-US,en;q=0.9"})
s.get("https://example.com/", timeout=20) # cookies are stored in the session
r = s.get("https://example.com/account", timeout=20) # same IP, same cookies
print(r.status_code)
s.close()Come si usa l'autorizzazione IP per connettersi?
Se registri l'IPv4 del server che esegue questo codice nel dashboard, puoi usare l'indirizzo senza username e password. Questo rende più facile distribuire lo stesso codice su più server senza dover memorizzare le password nel codice o nei file di configurazione. Puoi anche scegliere il formato ip:port per scaricare l'elenco.
import requests
proxy = "http://198.51.100.23:8000" # no user or password, server IP is authorized in the dashboard
r = requests.get("https://api.ipify.org", proxies={"http": proxy, "https": proxy}, timeout=20)
print(r.text)Come inviare più richieste contemporaneamente?
requests attende il completamento di una richiesta prima di procedere, quindi per ottenere molte pagine rapidamente è necessario eseguire più attività contemporaneamente. Il metodo più semplice è utilizzare ThreadPoolExecutor di concurrent.futures. Mantenere il numero di attività inferiore al numero di proxy evita di sovraccaricare un singolo IP.
Il codice qui sotto divide la lista di indirizzi tra 20 worker, e ogni worker sceglie il proxy successivo dalla lista. itertools.cycle può essere usato da più thread senza problemi per ottenere il valore successivo, ma se serve un ordine preciso usate un lock.
import itertools
from concurrent.futures import ThreadPoolExecutor
import requests
lines = open("proxies.txt").read().split() # user:pass@ip:port per line
pool = itertools.cycle(lines)
def get(url):
p = "http://" + next(pool)
try:
return url, requests.get(url, proxies={"http": p, "https": p}, timeout=20).status_code
except requests.RequestException as e:
return url, type(e).__name__
urls = ["https://example.com/item/" + str(i) for i in range(200)]
with ThreadPoolExecutor(max_workers=20) as ex:
for url, result in ex.map(get, urls):
print(url, result)È possibile utilizzare librerie asincrone come httpx o aiohttp?
Sì. httpx accetta l'indirizzo proxy come argomento quando crei un client, e installando httpx[socks] puoi utilizzare indirizzi SOCKS5. Anche il client asincrono AsyncClient accetta lo stesso argomento.
aiohttp richiede l'indirizzo del proxy HTTP nell'argomento proxy per ogni richiesta e passa aiohttp.BasicAuth a proxy_auth. aiohttp non supporta SOCKS di default, quindi per SOCKS5 è necessario utilizzare il connettore del pacchetto aiohttp-socks.
Il metodo asincrono può gestire migliaia di richieste con poche risorse, ma se non limiti il numero di richieste simultanee, il sito di destinazione e il proxy potrebbero essere sovraccaricati. Utilizza asyncio.Semaphore per impostare il numero di richieste simultanee.
import httpx
with httpx.Client(proxy="http://spx_user:spx_pass@198.51.100.23:8000", timeout=20) as client:
print(client.get("https://api.ipify.org").text)Come risolvere gli errori più frequenti?
L'errore 'Missing dependencies for SOCKS support' significa che requests[socks] non è installato. Reinstallalo nello stesso ambiente virtuale.
407 Proxy Authentication Required indica che username o password sono errati, o che stai usando l'autorizzazione IP ma l'IP del server non è registrato. Se la password contiene caratteri speciali, devi codificarli con urllib.parse.quote.
I timeout di connessione sono spesso causati da porte non corrispondenti. Verifica di utilizzare la porta HTTP per gli indirizzi HTTP e la porta SOCKS5 per gli indirizzi socks5h. Inserire un valore timeout previene che richieste senza risposta blocchino l'intero processo.
- Errore SOCKS: pip install "requests[socks]"
- 407: verifica username/password o IP registrato
- Timeout: distingui porta HTTP da SOCKS5
- Aggiungere timeout a tutte le richieste