Retour au blog
Guides
Mihnea-Octavian Manolache2 décembre 202213 minutes de lecture

Les 3 meilleurs clients HTTP Python pour le web scraping

Les 3 meilleurs clients HTTP Python pour le web scraping

Que sont les clients HTTP Python et comment les utiliser

Pour mieux comprendre comment fonctionne Internet, il est nécessaire de se familiariser avec le protocole HTTP (Hypertext Transfer Protocol). Cependant, nous allons aujourd’hui nous concentrer principalement sur les clients HTTP Python. Je pars donc du principe que vous connaissez déjà le protocole HTTP.

D'une manière générale, un client HTTP désigne une instance ou un programme qui facilite la communication avec un serveur. Par exemple, un navigateur web peut être considéré comme un client HTTP. Cependant, en tant que programmeurs, nous utilisons rarement un navigateur réel lors du développement d'une application, sauf lorsque nous travaillons sur un web scraper ou lorsque nous effectuons des recherches.

Cela étant dit, lorsque nous parlons de clients HTTP d’un point de vue plus technique, nous faisons généralement référence à une méthode ou à une instance d’une classe utilisée pour exécuter des requêtes HTTP. Python étant sans conteste l’un des langages de programmation les plus populaires (et aussi mon préféré), nous allons aujourd’hui aborder les meilleurs clients HTTP Python ainsi que la manière de les implémenter dans un projet concret.

Comprendre le protocole HTTP

Avant d’aller plus loin, même si je vous recommande de consulter la documentation HTTP, permettez-moi de passer rapidement en revue certains concepts HTTP de base. Tout d’abord, HTTP est sans doute l’un des protocoles Internet les plus utilisés. Nous l’utilisons tous les jours pour échanger des informations entre clients et serveurs. 

Pour ce faire, HTTP utilise des méthodes de requête. Ces méthodes indiquent l'action qu'un client souhaite effectuer sur un serveur. Par exemple, si vous souhaitez obtenir des informations d'un serveur, vous utiliserez GET. Si vous souhaitez envoyer quelque chose au serveur, vous utiliserez POST. Voici une liste des méthodes de requêtes HTTP les plus courantes :

  • GET - récupérer des données depuis le serveur
  • HEAD - récupérer uniquement l'en-tête, sans le corps (les données proprement dites)
  • POST - Envoyer des informations au serveur
  • PUT - Envoyer des informations au serveur et remplacer toutes les représentations actuelles de la ressource
  • PATCH - Envoyer des informations au serveur et modifier partiellement la ressource
  • DELETE - Supprimer la ressource du serveur

Pourquoi choisir Python pour les requêtes HTTP

Tout d'abord, Python dispose d'une excellente syntaxe et d'une communauté encore plus formidable. Il est donc parfait pour l'apprentissage. Pour ma part, lorsque j'ai commencé à programmer, j'ai choisi Python. En fait, les clients HTTP Python ont été parmi les premières technologies que j'ai découvertes. Mais c'est un autre sujet. 

Mon objectif pour l'article d'aujourd'hui est de m'assurer que vous repartiez non seulement avec une compréhension théorique de base, mais aussi avec un aperçu de la mise en œuvre pratique. 

Et Python est idéal pour les deux, pour plusieurs raisons. Pour n'en citer que quelques-unes :

  • Syntaxe - Écrire en Python, c'est un peu comme écrire en anglais. Ainsi, lire un script Python vous aidera à faire le lien entre les concepts théoriques et leur mise en œuvre concrète. 
  • Assistance - Python dispose d'une très grande communauté. La plupart du temps, si vous êtes bloqué, une simple question sur StackOverflow vous permettra de trouver la réponse à votre problème. 
  • Disponibilité - La bibliothèque de paquets de Python est parmi les plus complètes. Par exemple, rien que pour les clients HTTP Python, il existe plus d'une douzaine de paquets. Mais nous nous concentrerons aujourd'hui sur les plus populaires. 

Les 3 (+1) meilleurs clients HTTP Python

Lorsqu'il s'agit de classer les bibliothèques pour établir un top 3 des meilleurs clients HTTP Python, je pense que c'est à la fois une question de fonctionnalités et de préférences personnelles. Il est donc plus juste de dire que ce qui suit représente mon top 3 des bibliothèques de clients HTTP pour Python, plutôt qu'un classement général.

1. Requests - Une simplicité puissante

Requests est probablement l'un des clients HTTP les plus appréciés de la communauté Python. Je ne fais pas exception. Chaque fois que je teste un nouveau scraper web, j'utilise Python avec Requests. C'est aussi simple que de dire .get et aussi puissant qu'un véritable navigateur web. 

Entre autres, la bibliothèque Requests offre :

  • la vérification SSL 
  • Prise en charge des proxys pour HTTPS
  • Persistance des cookies et sessions
  • Fonctionnalité Keep-Alive
  • Authentification personnalisée

Et ce ne sont là que quelques exemples. Vous pouvez consulter la liste complète des fonctionnalités ici. Je vais maintenant vous montrer comment utiliser requests :

import requests
r = requests.get("http://google.com")      
print(r.test)

Comme vous pouvez le voir, en seulement 3 lignes de code, la bibliothèque requests nous aide à récupérer le code HTML d'une ligne depuis un serveur. Dans l'exemple ci-dessus, nous effectuons une requête GET vers le serveur et nous affichons le résultat. Mais comme je l'ai dit, cette bibliothèque offre bien plus de possibilités. Créons un exemple plus complexe, qui utilise des fonctionnalités telles que les proxys et les requêtes POST :

import requests

def get_params(object):
    params = ''
    for key,value in object.items():
        if list(object).index(key) < len(object) - 1:
            params += f"{key}={value}."
        else:
            params += f"{key}={value}"
    return params

API_KEY = '<YOUR_API_KEY>'

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

PARAMETERS = {
    "proxy_type":"datacenter",
    "device":"desktop"
}

PROXY = {
    "http": f"http://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:80",
    "https": f"https://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:8000"
}

response = requests.post(
    url=TARGET_URL,
    data=DATA,
    proxies=PROXY,
    verify=False
)

print(response.text)

Voyons ce que nous faisons ici :

  • Nous définissons la fonction `get_params`, qui prend un objet et le renvoie sous forme de chaîne de paramètres URL.
  • Nous définissons nos variables : undefinedundefinedundefinedundefinedundefined
  • Nous utilisons la méthode `post` de Requests pour envoyer une requête HTTP POST.
  • Nous affichons le corps de la réponse

2. HTTPX - Requests réinventé

HTTPX est relativement nouveau sur la scène. Cependant, en très peu de temps, il est devenu l'un des clients HTTP Python les plus recommandés. Par exemple, Flask (l'un des plus grands frameworks web pour Python) recommande l'utilisation de HTTPX dans sa documentation officielle. 

Quand j'ai dit qu'HTTPX était une réinvention de Requests, c'était parce que les deux bibliothèques sont très similaires en termes de syntaxe. En fait, HTTPX vise une compatibilité totale avec Requests. Il n'y a que quelques différences mineures de conception entre les deux, qui sont mises en évidence ici

Voici à quoi ressemble une requête POST de base dans HTTPX :

import httpx

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

r = httpx.post(
   url=TARGET_URL,
   data=DATA,
)

print(r.text)

Comme vous pouvez le constater, c’est principalement le nom du package que nous modifions par rapport à l’exemple Requests. Et comme ils sont si similaires, la question demeure : pourquoi choisir HTTPX plutôt que Requests ? Eh bien, pour commencer, HTTPX est l’un des rares clients HTTP Python à offrir une prise en charge asynchrone. En résumé, HTTPX est un excellent choix si vous souhaitez refactoriser votre code basé sur Requests. 

3. urllib3 - Connexions thread-safe

Python dispose de plusieurs « urllib », ce qui sème souvent la confusion chez les nouveaux programmeurs. La principale différence entre urllib, urllib2 et urllib3 réside dans les fonctionnalités de chaque bibliothèque. urllib était le client HTTP d’origine de Python, inclus dans la bibliothèque standard de Python 1.2. urllib2 était la version améliorée, introduite dans Python 1.6 et destinée à remplacer l’urllib d’origine.

En ce qui concerne urllib3, il s'agit en réalité d'un client HTTP Python tiers. Malgré son nom, cette bibliothèque n'a aucun lien avec ses deux « prédécesseurs ». De plus, selon les rumeurs au sein de la communauté Python, il n'est pas prévu d'inclure urllib3 dans la bibliothèque standard. Du moins dans un avenir proche. 

Même si ce paquet n'est pas officiellement lié à la bibliothèque standard de Python, de nombreux développeurs l'utilisent car il offre :

  • La sécurité des threads
  • Vérification SSL/TLS côté client
  • Prise en charge des proxys pour HTTP et SOCKS
  • Une couverture de test complète

Maintenant que nous avons abordé la partie théorique, examinons l'exemple d'implémentation :

import urllib3,json

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

http = urllib3.PoolManager()

encoded_data = json.dumps(DATA)

r = http.request('POST', TARGET_URL, body=encoded_data)   

print(r.data.decode('utf-8'))

Examinons les différences identifiées dans urllib3, par rapport à Requests :

  • `http` - une instance de la méthode `PoolManager`, qui gère les détails liés à la sécurité des threads et au pool de connexions
  • `encoded_data` - une chaîne JSON convertie, contenant la charge utile que nous envoyons
  • `r` - la requête POST que nous effectuons à l'aide d'urllib3. Ici, nous utilisons la méthode `request` de l'instance `PoolManager`.

Enfin, nous devons décoder les données que nous recevons en retour de notre requête. Comme vous pouvez le constater, nous procédons différemment de Requests sur plusieurs points.

Mention honorable : http.client - Client HTTP Python traditionnel

http.client fait également partie de la bibliothèque standard de Python. Traditionnellement, il n’est pas utilisé directement par les programmeurs. Par exemple, urllib l’utilise en réalité comme dépendance, afin de gérer les requêtes HTTP et HTTPS. Je l’ai inclus dans notre classement car je pense qu’en tant que programmeurs, il est bon de connaître les « fondements » des paquets que nous utilisons.

Ainsi, même si vous ne créez peut-être pas de projet concret avec http.client, voici un exemple d’implémentation qui, j’en suis sûr, vous aidera à mieux comprendre le fonctionnement des clients HTTP Python :

import http.client

TARGET_URL = 'www.httpbin.org'

http = http.client.HTTPSConnection(TARGET_URL)
http.request("GET", "/get")

r = http.getresponse()

print(r.read().decode('utf-8'))

L'instance `HTTPSConnection` prend quelques paramètres, que vous pouvez consulter ici. Dans notre exemple, nous ne définissons que la `méthode` et l'`URL` (ou plus précisément, le point de terminaison). De plus, tout comme urllib3, http.client renvoie une réponse encodée. Nous devons donc la décoder avant de l'afficher.

Cas d&#x27;utilisation : créer un scraper avec Requests

Maintenant que nous savons comment utiliser les clients HTTP, lançons-nous dans un petit projet. Cela vous permettra non seulement de mettre en pratique ce que vous avez appris, mais aussi d’enrichir votre portfolio de programmation. 

Comme les clients HTTP Python sont couramment utilisés pour collecter des informations sur des serveurs, l’utilisation la plus courante de ces technologies consiste à créer un scraper web. Nous allons donc nous concentrer sur la création d'un scraper web à l'aide de clients HTTP en Python. Comme j'ai un favori personnel – requests – je l'utiliserai pour ce projet. Cependant, vous pouvez vous en servir comme point de départ et même le modifier pour utiliser certaines des autres technologies dont nous avons parlé. Sans plus attendre, commençons à coder :

1. Configuration du projet

Commençons par créer un nouveau répertoire dans lequel nous allons stocker les fichiers de notre web scraper. Ouvrez maintenant une nouvelle fenêtre de terminal et accédez à ce répertoire avec la commande `cd`. Ici, nous voulons initialiser un nouvel environnement virtuel. Si vous utilisez un système d'exploitation de type UNIX, vous pouvez utiliser :

~ » python3 -m venv env && source env/bin/activate              

Créez maintenant simplement un nouveau fichier Python qui contiendra notre logique et ouvrez-le dans l'IDE de votre choix. Si vous souhaitez utiliser le terminal, collez simplement la commande suivante :

~ » touch scraper.py && code .                                         

2. Installation des dépendances

Nous utiliserons pip pour installer les paquets dont nous avons besoin pour ce projet. Pour l'instant, nous avons décidé d'utiliser Requests, mais cela ne suffit pas pour un scraper web. Un scraper web implique également la gestion des données. Cela signifie que nous devons analyser le code HTML collecté sur les serveurs. Heureusement, la bibliothèque Python offre une grande variété de paquets. Pour ce projet, nous utiliserons toutefois BeautifulSoup. Pour installer les paquets, il suffit de coller la commande suivante :

~ » python3 -m pip install requests bs4                                    

3. Écriture de la logique

Nous allons diviser notre code en deux sections : une pour l'extraction des données et une pour la manipulation des données. La première partie est gérée par le module Requests, tandis que la seconde est gérée par BeautifulSoup. Sans plus attendre, passons au codage, en commençant par la partie extraction :

import requests

def scrape( url = None ):
   # if there is no URL, there is no need to use Python HTTP clients
   # We will print a message and stop execution
   if url == None:
       print('[!] Please add a target!')
       return

   response = requests.get( url ) 
   return response

Dans cette section, nous définissons une fonction avec un seul paramètre : l’URL ciblée. Si l’URL n’est pas fournie, nous affichons un message et arrêtons l’exécution. Sinon, nous utilisons la méthode get de Requests pour renvoyer la réponse. Or, nous savons que les clients HTTP Python prennent en charge davantage de méthodes ; ajoutons donc un paramètre conditionnel :

import requests

def scrape( method = 'get', url = None, data = None ):
   # if there is no URL, there is no need to use Python HTTP clients
   # We will print a message and stop execution
   if url == None:
       print('[!] Please add a target!')
       return

   if method.lower() == 'get':
       response = requests.get( url )

   elif method.lower() == 'post':
       if data == None:
           print('[!] Please add a payload to your POST request!')
           return
       response = requests.post( url, data )
      
   return response

Comme vous pouvez le voir, nous avons ajouté quelques paramètres supplémentaires à notre fonction. Le paramètre `method` spécifie la méthode à utiliser pour notre requête. Le paramètre `data` représente la charge utile que nous envoyons avec la requête POST. Par défaut, la méthode est GET, le paramètre `method` n'est donc pas obligatoire. 

Défi : Ajoutez d’autres méthodes à cette fonction et enrichissez les capacités de notre scraper. Non seulement c’est amusant, mais c’est aussi une bonne approche d’apprentissage. De plus, vous pouvez vous approprier le code afin de l’ajouter à votre portfolio.

Jusqu'à présent, nous avons abordé l'extraction de données. Analysons le code HTML et exploitons-le :

from bs4 import BeautifulSoup

def extract_elements(data = None, el = None):
   if data == None:
       print('[!] Please add some data!')
       return

   if el == None:
       print('[!] Please specify which elements you are targeting!')
       return

   soup = BeautifulSoup(data.text, 'html.parser')
   elements = soup.find_all(el)

   return elements

Mais un scraper web devrait être capable d'extraire des données plus spécifiques. Par exemple, il devrait pouvoir localiser et renvoyer des éléments en fonction de leur sélecteur CSS. Ajoutons donc la logique qui gère cette partie :

from bs4 import BeautifulSoup

def extract_elements(data = None, el = None, attr = None, attr_value = None):
   if data == None:
       print('[!] Please add some data!')
       return

   if el == None:
       print('[!] Please specify which elements you are targeting!')
       return

   soup = BeautifulSoup(data.text, 'html.parser')
   elements = soup.find_all(el, { attr : attr_value })

   return elements

BeautifulSoup nous permet d'extraire des données spécifiques en fonction de leurs attributs. Nous avons donc ajouté ici deux nouveaux paramètres qui nous aideront à localiser et à extraire des éléments en fonction de leurs attributs.

Nous avons désormais tout ce dont nous avons besoin. Il ne reste plus qu’à combiner les deux sections pour obtenir notre scraper web. Une fois votre code assemblé, il suffit de :

  • Créez une nouvelle variable qui contiendra les données extraites avec Requests 
  • Affichez les éléments renvoyés par BeautifulSoup

Voici les deux éléments manquants de votre code :

data = scrape('GET', 'https://webscrapingapi.com')
print( extract_elements(data, 'ul') )

Je suis sûr que vous avez déjà compris le fonctionnement de chaque élément et qu'une explication n'est plus nécessaire à ce stade. Tout comme pour notre scraper, je vous mets au défi d'expérimenter avec la fonction `extract_elements` et de lui faire faire plus que simplement renvoyer des éléments. 

Conclusion

Lorsqu'on apprend un nouveau concept de programmation, je pense qu'il est préférable de tester les différentes technologies disponibles. Cependant, lorsqu'il s'agit de construire l'infrastructure d'un projet plus vaste, il vaut mieux se renseigner sur les forces et les faiblesses de chaque technologie avant d'en choisir une. 

J'espère que cet article vous a été utile et que vous comprenez désormais bien le fonctionnement des clients HTTP Python. Je vous encourage également à faire des essais, car je suis sûr que vous trouverez le package qui vous convient.

À propos de l'auteur
Mihnea-Octavian Manolache, Développeur Full Stack @ WebScrapingAPI
Mihnea-Octavian ManolacheDéveloppeur Full Stack

Mihnea-Octavian Manolache est ingénieur Full Stack et DevOps chez WebScrapingAPI, où il développe des fonctionnalités pour les produits et assure la maintenance de l'infrastructure qui garantit le bon fonctionnement de la plateforme.

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.