Il web scraping è un metodo efficace per estrarre dati dal web. Molti sviluppatori preferiscono usare la libreria request di Python per realizzare progetti di web scraping, perché è semplice ed efficace. Tuttavia, per quanto ottima, la libreria request ha i suoi limiti. Un problema tipico che si può incontrare nello scraping del web sono le richieste fallite, che spesso portano a un'estrazione instabile dei dati. In questo articolo, vedremo come implementare i tentativi di richiesta in Python, in modo da poter gestire gli errori HTTP e mantenere gli script di web scraping stabili e affidabili.
Per prima cosa configuriamo il nostro ambiente. Assicuratevi di avere installato Python e un IDE di vostra scelta. Quindi installate la libreria requests, se non l'avete già.
pip install requests
Una volta installato, inviamo una richiesta a example.com utilizzando il modulo requests di Python. Ecco una semplice funzione che fa proprio questo:
import requests
def send_request(url):
"""
Invia una richiesta HTTP GET all'URL specificato e stampa il codice di stato della risposta.
Parameters:
url (str): L'URL a cui inviare la richiesta.
"""
response = requests.get(url)
print('Response Status Code: ', response.status_code)
send_request('https://example.com')
L'output del codice è mostrato di seguito:
Diamo un'occhiata più da vicino ai codici di stato HTTP per comprenderli meglio.
Il server risponde a una richiesta HTTP con un codice di stato che indica l'esito della richiesta. Ecco un rapido riepilogo:
Nel nostro esempio, il codice di stato 200 significa che la richiesta a https://example.com è stata completata. È il modo in cui il server dice: "È tutto a posto, la richiesta è andata a buon fine".
Questi codici di stato possono anche svolgere un ruolo nel rilevamento dei bot e indicare quando l'accesso è limitato a causa di un comportamento simile a quello dei bot.
Di seguito è riportata una rapida carrellata di codici di errore HTTP che si verificano principalmente a causa di problemi di rilevamento e autenticazione dei bot.
Scriviamo ora un semplice meccanismo di retry in Python per effettuare richieste HTTP GET con la libreria requests. A volte le richieste di rete falliscono a causa di qualche problema di rete o del sovraccarico del server. Quindi, se la nostra richiesta non va a buon fine, dobbiamo riprovare.
La funzione send_request_with_basic_retry_mechanism effettua richieste HTTP GET a un determinato URL con un meccanismo di retry di base, che viene riprovato solo se si verifica un'eccezione di rete o di richiesta, come un errore di connessione. Riproverebbe la richiesta per un massimo di max_tentativi. Se tutti i tentativi falliscono con un'eccezione, viene sollevata l'ultima eccezione incontrata.
import requests
import time
def send_request_with_basic_retry_mechanism(url, max_retries=2):
"""
Invia una richiesta HTTP GET a un URL con un meccanismo di riprova di base.
Parameters:
url (str): L'URL a cui inviare la richiesta.
max_retries (int): Il numero massimo di volte in cui riprovare la richiesta.
Raises:
requests.RequestException: Solleva l'ultima eccezione se tutti i tentativi falliscono.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
print('Response status: ', response.status_code)
break # Esce dal ciclo se la richiesta è andata a buon fine
except requests.RequestException as error:
print(f"Attempt {attempt+1} failed:", error)
if attempt < max_retries - 1:
print(f"Retrying...")
time.sleep(delay) # Aspettare prima di riprovare
else:
print("Max retries exceeded.")
# Rilanciare l'ultima eccezione se il massimo dei tentativi è stato raggiunto
raise
send_request_with_basic_retry_mechanism('https://example.com')
Adattiamo ora il meccanismo di base di retry per gestire gli scenari in cui il sito web che stiamo cercando di scrappare implementa meccanismi di rilevamento dei bot che possono risultare in un blocco. Per affrontare tali scenari, è necessario riprovare la richiesta più volte, poiché i blocchi potrebbero non essere solo dovuti al rilevamento dei bot, ma anche a problemi di rete o di server.
Adattiamo ora il meccanismo di base di retry per gestire gli scenari in cui il sito web che stiamo cercando di scrappare implementa meccanismi di rilevamento dei bot che possono risultare in un blocco. Per affrontare tali scenari, è necessario riprovare la richiesta più volte, poiché i blocchi potrebbero non essere solo dovuti al rilevamento dei bot, ma anche a problemi di rete o di server.
Il parametro del ritardo è importante perché evita di bombardare il server con più richieste a distanza ravvicinata. Al contrario, attende che il server abbia il tempo sufficiente per elaborare la richiesta, facendo credere al server che sia un umano e non un bot a effettuare le richieste. Pertanto, il meccanismo di riprova dovrebbe essere ritardato per evitare il sovraccarico del server o una risposta lenta del server che potrebbe innescare meccanismi anti-bot.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1):
"""
Invia una richiesta HTTP GET all'URL specificato con un meccanismo di riprova avanzato.
Parameters:
url (str): L'URL a cui inviare la richiesta.
max_retries (int): Il numero massimo di volte in cui riprovare la richiesta. L'impostazione predefinita è 3.
delay (int): Il ritardo (in secondi) tra i tentativi. L'impostazione predefinita è 1.
Raises:
requests.RequestException: Solleva l'ultima eccezione se tutti i tentativi falliscono.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Raise an exception for 4xx or 5xx status codes
response.raise_for_status()
print('Response Status Code:', response.status_code)
except requests.RequestException as e:
# Stampa il messaggio di errore e il numero di tentativo se la richiesta fallisce
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
# Stampa il messaggio di ripetizione e aspetta prima di riprovare
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
# Se il numero massimo di tentativi viene superato, stampare il messaggio e rilanciare l'eccezione
print("Max retries exceeded.")
raise
# Esempio di utilizzo
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Ecco il codice corretto e i commenti che affrontano gli inconvenienti:
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Invia una richiesta HTTP GET all'URL specificato con un meccanismo di riprova avanzato.
Parameters:
url (str): L'URL a cui inviare la richiesta.
max_retries (int): Il numero massimo di tentativi della richiesta. L'impostazione predefinita è 3.
delay (int): Il ritardo (in secondi) tra i tentativi. L'impostazione predefinita è 1.
min_content_length (int): La lunghezza minima del contenuto della risposta da considerare valida. L'impostazione predefinita è 10.
Raises:
requests.RequestException: Solleva l'ultima eccezione se tutti i tentativi falliscono.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Sollevare un'eccezione per i codici di stato 4xx o 5xx
response.raise_for_status()
# Controlla se il codice di stato della risposta è 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Esce dal ciclo per gli errori 404
# Controlla se la lunghezza del testo della risposta è inferiore alla lunghezza minima del contenuto specificata
if len(response.text) < min_content_length:
print("Response text length is less than specified minimum. Retrying...")
time.sleep(delay)
continue # Riprova la richiesta
print('Response Status Code:', response.status_code)
# Se le condizioni sono soddisfatte, uscire dal ciclo
break
except requests.RequestException as e:
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
print("Max retries exceeded.")
# Rilanciare l'ultima eccezione se il massimo dei tentativi è stato raggiunto
raise
# Esempio di utilizzo
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Per alcuni errori, come 429 Troppe richieste, l'uso di proxy a rotazione può aiutare a distribuire le richieste ed evitare la limitazione della velocità.
Il codice seguente implementa una strategia di retry avanzata insieme all'uso dei proxy. In questo modo, possiamo implementare un meccanismo di retry per le richieste di Python. Anche l'uso di proxy di alta qualità per il web scraping è importante. Questi proxy devono avere un buon algoritmo di rotazione dei proxy e un pool affidabile.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Invia una richiesta HTTP GET all'URL specificato con un meccanismo di riprova avanzato.
Parameters:
url (str): L'URL a cui inviare la richiesta.
max_retries (int): Il numero massimo di volte in cui riprovare la richiesta. L'impostazione predefinita è 3.
delay (int): Il ritardo (in secondi) tra i tentativi. L'impostazione predefinita è 1.
Raises:
requests.RequestException: Solleva l'ultima eccezione se tutti i tentativi falliscono.
"""
proxies = {
"http": "http://USER:PASS@HOST:PORT",
"https": "https://USER:PASS@HOST:PORT"
}
for attempt in range(max_retries):
try:
response = requests.get(url, proxies=proxies, verify=False)
# Sollevare un'eccezione per i codici di stato 4xx o 5xx
response.raise_for_status()
# Controllare se il codice di stato della risposta è 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Esce dal ciclo per gli errori 404
# Verifica se la lunghezza del testo di risposta è inferiore a 10 caratteri
if len(response.text) < min_content_length:
print("Response text length is less than 10 characters. Retrying...")
time.sleep(delay)
continue # Riprova la richiesta
print('Response Status Code:', response.status_code)
# Se le condizioni sono soddisfatte, uscire dal ciclo
break
except requests.RequestException as e:
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
print("Max retries exceeded.")
# Rilanciare l'ultima eccezione se il massimo dei tentativi è stato raggiunto
raise
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
I tentativi di risposta alle richieste in Python sono fondamentali per un web scraping efficace. I metodi che abbiamo discusso per gestire i ritentativi possono aiutare a prevenire il blocco e a migliorare l'efficienza e l'affidabilità della raccolta dei dati. L'implementazione di queste tecniche renderà i vostri script di web scraping più robusti e meno suscettibili di essere rilevati dai sistemi di protezione dei bot.
Мы получили вашу заявку!
Ответ будет отправлен на почту в ближайшее время.
С уважением proxy-seller.ru!
Commenti: 0