Le web scraping est une méthode efficace pour extraire des données du web. De nombreux développeurs préfèrent utiliser la bibliothèque de requêtes Python pour réaliser des projets de web scraping, car elle est simple et efficace. Cependant, même si elle est excellente, la bibliothèque de requêtes a ses limites. Un problème typique que l'on peut rencontrer dans le web scraping est l'échec des requêtes, qui conduit souvent à une extraction de données instable. Dans cet article, nous allons voir comment implémenter les tentatives de requêtes en Python, afin que vous puissiez gérer les erreurs HTTP et garder vos scripts de web scraping stables et fiables.
Commençons par mettre en place notre environnement. Assurez-vous que Python est installé et que vous avez l'IDE de votre choix. Ensuite, installez la bibliothèque requests si vous ne l'avez pas déjà.
pip install requests
Une fois installé, envoyons une requête à example.com en utilisant le module requests de Python. Voici une fonction simple qui fait exactement cela :
import requests
def send_request(url):
"""
Envoie une requête HTTP GET à l'URL spécifiée et affiche le code d'état de la réponse.
Parameters:
url (str): L'URL à laquelle envoyer la demande.
"""
response = requests.get(url)
print('Response Status Code: ', response.status_code)
send_request('https://example.com')
La sortie du code est indiquée ci-dessous :
Examinons de plus près les codes d'état HTTP pour mieux les comprendre.
Le serveur répond à une requête HTTP par un code d'état indiquant le résultat de la requête. En voici un bref aperçu :
Dans notre exemple, le code de statut 200 signifie que la requête vers https://example.com a été complétée. C'est la façon dont le serveur dit : "Tout va bien, votre demande a été acceptée".
Ces codes d'état peuvent également jouer un rôle dans la détection des robots et indiquer si l'accès est restreint en raison d'un comportement similaire à celui d'un robot.
Voici un bref aperçu des codes d'erreur HTTP qui se produisent principalement en raison de problèmes de détection et d'authentification des robots.
Nous allons maintenant écrire un simple mécanisme de relance en Python pour effectuer une requête HTTP GET à l'aide de la bibliothèque requests. Il arrive que des requêtes réseau échouent en raison d'un problème réseau ou d'une surcharge du serveur. Si notre requête échoue, nous devons donc la relancer.
La fonction send_request_with_basic_retry_mechanism émet des requêtes HTTP GET vers une URL donnée avec un mécanisme de réessai basique en place qui ne réessaie que si une exception de réseau ou de requête telle qu'une erreur de connexion est rencontrée. La requête sera relancée un maximum de fois. Si toutes les tentatives échouent avec une telle exception, il lève la dernière exception rencontrée.
import requests
import time
def send_request_with_basic_retry_mechanism(url, max_retries=2):
"""
Envoie une requête HTTP GET à une URL avec un mécanisme de relance de base.
Parameters:
url (str): L'URL à laquelle envoyer la demande.
max_retries (int): Nombre maximal de tentatives de réitération de la demande.
Raises:
requests.RequestException: Lève la dernière exception si toutes les tentatives échouent.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
print('Response status: ', response.status_code)
break # Sortir de la boucle si la demande est acceptée
except requests.RequestException as error:
print(f"Attempt {attempt+1} failed:", error)
if attempt < max_retries - 1:
print(f"Retrying...")
time.sleep(delay) # Attendre avant de réessayer
else:
print("Max retries exceeded.")
# Relance la dernière exception si le nombre maximum de tentatives est atteint
raise
send_request_with_basic_retry_mechanism('https://example.com')
Adaptons maintenant le mécanisme de relance de base pour gérer les scénarios dans lesquels le site web que nous essayons de récupérer met en œuvre des mécanismes de détection des robots qui peuvent entraîner un blocage. Dans ce cas, nous devons réessayer la requête plusieurs fois, car il peut s'agir non seulement de blocages dus à la détection de robots, mais aussi de problèmes de réseau ou de serveur.
La fonction ci-dessous send_request_with_advance_retry_mechanism envoie une requête HTTP GET à l'URL fournie avec des tentatives de réessai et un délai de réessai optionnels. Elle tente d'envoyer la requête plusieurs fois pour le nombre de tentatives spécifié et affiche le code d'état de la réponse si la requête obtient une réponse. S'il rencontre une erreur au cours de l'opération de requête, il affiche le message d'erreur et recommence. Il attend le délai de réessai spécifié entre chaque tentative. Si la demande échoue même après le nombre de tentatives spécifié, il lève la dernière exception rencontrée.
Le paramètre de délai est important car il permet d'éviter de bombarder le serveur de multiples demandes à intervalles rapprochés. Au contraire, il attend que le serveur ait suffisamment de temps pour traiter la demande, ce qui lui fait penser que c'est un humain et non un robot qui fait les demandes. Le mécanisme de relance doit donc être retardé afin d'éviter une surcharge du serveur ou une réponse lente du serveur, ce qui pourrait déclencher des mécanismes anti-bots.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1):
"""
Envoie une requête HTTP GET à l'URL spécifiée avec un mécanisme de relance avancé.
Parameters:
url (str): L'URL à laquelle envoyer la demande.
max_retries (int): Nombre maximal de tentatives de réitération de la demande. La valeur par défaut est 3.
delay (int): Délai (en secondes) entre les tentatives. La valeur par défaut est 1.
Raises:
requests.RequestException: Lève la dernière exception si toutes les tentatives échouent.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Lever une exception pour les codes d'état 4xx ou 5xx
response.raise_for_status()
print('Response Status Code:', response.status_code)
except requests.RequestException as e:
# Imprimer le message d'erreur et le numéro de la tentative si la demande échoue
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
# Imprimer le message de réessai et attendre avant de réessayer
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
# Si le nombre maximum de tentatives est dépassé, imprimer le message et relancer l'exception
print("Max retries exceeded.")
raise
# Exemple d'utilisation
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Voici le code corrigé ainsi que les commentaires concernant les inconvénients :
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Envoie une requête HTTP GET à l'URL spécifiée avec un mécanisme de relance avancé.
Parameters:
url (str): L'URL à laquelle envoyer la demande.
max_retries (int): Nombre maximal de tentatives de réitération de la demande. La valeur par défaut est 3.
delay (int): Délai (en secondes) entre les tentatives. La valeur par défaut est 1.
min_content_length (int): Longueur minimale du contenu de la réponse à considérer comme valide. La valeur par défaut est 10.
Raises:
requests.RequestException: Lève la dernière exception si toutes les tentatives échouent.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Lever une exception pour les codes d'état 4xx ou 5xx
response.raise_for_status()
# Vérifier si le code d'état de la réponse est 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Sortir de la boucle pour les erreurs 404
# Vérifier si la longueur du texte de la réponse est inférieure à la longueur minimale spécifiée du contenu
if len(response.text) < min_content_length:
print("Response text length is less than specified minimum. Retrying...")
time.sleep(delay)
continue # Réessayer la demande
print('Response Status Code:', response.status_code)
# Si les conditions sont remplies, sortir de la boucle
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.")
# Relance la dernière exception si le nombre maximum de tentatives est atteint
raise
# Exemple d'utilisation
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Pour certaines erreurs telles que 429 Too Many Requests, l'utilisation de proxies rotatifs peut aider à répartir les demandes et à éviter la limitation du débit.
Le code ci-dessous implémente une stratégie de relance avancée avec l'utilisation de proxies. De cette manière, nous pouvons mettre en place un mécanisme de relance des requêtes Python. Il est également important d'utiliser des proxys de web scraping de haute qualité. Ces proxys doivent disposer d'un bon algorithme de rotation des proxys et d'un pool fiable.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Envoie une requête HTTP GET à l'URL spécifiée avec un mécanisme de relance avancé.
Parameters:
url (str): L'URL à laquelle envoyer la demande.
max_retries (int): Nombre maximal de tentatives de réitération de la demande. La valeur par défaut est 3.
delay (int): Délai (en secondes) entre les tentatives. La valeur par défaut est 1.
Raises:
requests.RequestException: Lève la dernière exception si toutes les tentatives échouent.
"""
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)
# Lever une exception pour les codes d'état 4xx ou 5xx
response.raise_for_status()
# Vérifier si le code d'état de la réponse est 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Sortir de la boucle pour les erreurs 404
# Vérifier si la longueur du texte de la réponse est inférieure à 10 caractères
if len(response.text) < min_content_length:
print("Response text length is less than 10 characters. Retrying...")
time.sleep(delay)
continue # Réessayer la demande
print('Response Status Code:', response.status_code)
# Si les conditions sont remplies, sortir de la boucle
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.")
# Relance la dernière exception si le nombre maximum de tentatives est atteint
raise
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Les tentatives de requêtes en Python sont cruciales pour un web scraping efficace. Les méthodes que nous avons examinées pour gérer les tentatives peuvent aider à prévenir le blocage et à améliorer l'efficacité et la fiabilité de la collecte de données. La mise en œuvre de ces techniques rendra vos scripts de web scraping plus robustes et moins susceptibles d'être détectés par les systèmes de protection contre les robots.
Мы получили вашу заявку!
Ответ будет отправлен на почту в ближайшее время.
С уважением proxy-seller.com!
Commentaires: 0