Comment utiliser cURL avec Python

Dans cet article, vous apprendrez comment Python et cURL peuvent être utilisés ensemble pour automatiser les requêtes GET, POST et PUT, et pour télécharger des fichiers et des pages web.
15 min read
Guide to using cURL with Python

cURL est un outil de ligne de commande open source polyvalent pour le transfert de données sur un réseau. Il peut être utilisé avec un grand nombre de paramètres, qui lui permettent de traiter presque n’importe quelle requête. De plus, cURL possède une interface dans pratiquement tous les langages de programmation modernes.

L’utilisation de cURL avec un langage de programmation offre de nombreux avantages. Par exemple, la réalisation de requêtes peut être automatisée pour des besoin de débogage ou de web scraping.

Dans cet article, vous apprendrez comment Python et cURL peuvent être utilisés ensemble pour automatiser des requêtes GET, POST et PUT, et pour télécharger des fichiers et des pages web.

Qu’est-ce que cURL ?  

cURL est un projet logiciel, mais son nom est également utilisé dans deux produits : une bibliothèque appelée libcurl et un outil de ligne de commande appelé curl (qui utilise libcurl). Lorsque nous parlons de curl dans cet article, il s’agit de l’outil de ligne de commande.

curl est considéré comme un outil polyvalent ; cependant, sa tâche principale est simple : transférer des données via divers protocoles réseau. Compte tenu de la complexité du web actuel, curl est accompagné d’une énorme liste d’options qui lui permettent de traiter les requêtes les plus complexes.

curl a été publié pour la première fois en 1996 en tant que HttpGet avant d’être renommé urlget puis curl. Sa première utilisation consistait à récupérer des taux de change pour les utiliser dans un canal IRC. Aujourd’hui, curl prend en charge le transfert de données par différentes méthodes, y compris FTP(S), HTTP(S) (POST, GET, PUT), IMAP, POP3, MQTT et SMB. De plus, curl peut gérer les cookies et les certificats SSL.

Lorsque curl établit une connexion via HTTPS, il obtient le certificat du serveur distant et le compare à son magasin de certificats CA pour s’assurer que le serveur distant est celui qu’il prétend être. Par exemple, la requête suivante envoie une requête HTTPS au site de Bright Data et définit un cookie appelé greeting avec la valeur hello :

curl --cookie "greeting=hello" https://www.brightdata.com

Pourquoi utiliser curl avec Python ?

Même si curl est un outil polyvalent, il y a une raison importante pour laquelle vous pouvez avoir intérêt à l’utiliser avec Python : Python peut automatiser vos requêtes. Voici trois cas où il s’agit cette association fait merveille :  

Web Scraping

Le web scraping consiste à recueillir des données (généralement en grande quantité) sur une ou plusieurs pages web. Pour collecter des données avec Python, les gens font souvent appel à la bibliothèque de requêtes. Pour faire du scraping récursif, vous pouvez utiliser wget. Cependant, pour les cas d’utilisation plus complexes avec des appels HTTP(S) complexes, curl avec Python est la solution idéale pour le web scraping.

Bien que les données d’une page web puissent être collectées à l’aide d’une seule commande curl qui génère et traite une requête HTTP(S), cette commande ne peut pas agir de manière récursive. En intégrant curl dans du code Python, vous pouvez simuler un chemin de navigation sur un site web en manipulant des éléments tels que les paramètres de requête, les cookies et les agents utilisateurs.

La navigation n’a même pas besoin d’être fixe. Chaque nouvelle requête peut être entièrement dynamique si vous la subordonnez au contenu extrait.

Par exemple, si vous collectez des données dans la section des commentaires d’un site web d’actualités populaire, et que vous voulez seulement collecter des données sur la page du profil de l’auteur, si les commentaires contiennent des mots clés haineux, vous pouvez créer une instruction conditionnelle relative aux commentaires collectés et appliquer facilement ce filtre dynamique.

En outre, de nombreux sites web ont des mécanismes de sécurité qui rendent le scraping d’un grand nombre de pages plus difficile : pensez par exemple à la protection contre les attaques par déni de service distribuées (DDoS) ou aux invites reCAPTCHA. En appliquant certaines règles et en effectuant des pauses entre les requêtes, il est possible de simuler un comportement humain, ce qui est plus difficile à détecter.

Tests et débogage

Utiliser curl sur votre propre site web peut sembler bizarre, mais cela peut s’avérer utile dans un contexte de tests et de débogage. Les tests et le débogage d’une ou de plusieurs fonctionnalités d’une application sont souvent des tâches lourdes. Cela doit être effectué de façon récursive et avec une foule de paramètres. Bien qu’il existe de nombreux outils de test prêts à l’emploi, Python et curl rendent assez rapide la configuration de certains tests.

Par exemple, si vous créez un nouveau flux de paiement pour votre service en ligne (complexe) qui utilise des cookies, s’appuie sur le référent, présente des différences mineures selon le navigateur (agent utilisateur) et intègre toutes les étapes du processus de paiement dans le corps d’une requête POST, tester manuellement tous les cas possibles peut être particulièrement chronophage. En Python, vous pouvez créer un dictionnaire contenant l’ensemble des paramètres et envoyer une requête en utilisant curl pour chaque combinaison possible.

Automatisation des workflows

Outre les tests, le débogage et le web scraping, curl peut être utilisé pour l’automatisation des workflows. Par exemple, de nombreux pipelines d’intégration de données commencent par le vidage récurrent d’une exportation de données, sous la forme d’un fichier CSV ou Apache parquet. Avec une application Python qui vérifie la présence de nouveaux fichiers sur un serveur (S)FTP, la copie des vidages de données peut être entièrement automatisée.

Vous pouvez également envisager de configurer des mailhooks. Imaginez combien de tâches quotidiennes pourraient être automatisées si une application pouvait vérifier la présence d’e-mails contenant une requête. En vérifiant la présence de nouveaux messages via le protocole POP3 ou IMAP, les applications Python peuvent être déclenchées lorsqu’une boîte aux lettres reçoit un e-mail spécifique.

Comment utiliser cURL avec Python

Il existe différentes façons de faire des requêtes en utilisant curl en Python. Cet article couvre deux options. La première consiste à simuler les requêtes curl dans la ligne de commande via les packages Python os et subprocess. Cette approche directe envoie par programmation des commandes à l’interface de la ligne de commande de votre système d’exploitation.

La deuxième option consiste à utiliser le package PycURL. Si vous voulez en savoir plus sur d’autres façons de collecter des données sur des sites web avec Python (sans utiliser curl), vous pouvez consulter ce guide Bright Data de scraping avec Python.  

Prérequis

Avant de commencer ce tutoriel, assurez-vous que vous avez téléchargé et installé curl. Si vous utilisez Windows, assurez-vous d’ajouter curl à votre variable d’environnement PATH, de manière à pouvoir simplement exécuter la commande curl.

Pour créer une interface Python avec votre système d’exploitation, vous pouvez utiliser différents packages. Cela dit, les deux packages les plus couramment utilisés sont os et subprocess. Pour les installer, exécutez la commande pip suivante :

pip install os subprocess

Génération d’une requête avec curl et os

Le package os est un package extrêmement simple. L’exécution d’une requête curl sans traitement de la réponse ne prend que deux lignes de code. Il vous suffit de passer le cookie décrit dans l’exemple précédent, et la sortie s’écrit dans le fichier output.txt :

import os
os.system('curl -o output.txt --cookie "greeting=hello" -k https://curl.se')

Si vous voulez traiter la réponse en Python au lieu de l’écrire dans un fichier, vous devez utiliser le package subprocess décrit dans la section suivante.

Le code suivant exécute la même instruction, mais au lieu d’écrire la réponse dans un fichier, il génère le stdout et le stderr en tant que tuple. Cette sortie peut alors être traitée avec d’autres packages Python, tels que Beautiful Soup :

import shlex
import subprocess
shell_cmd = shlex.split('curl --cookie "greeting=hello" -k https://curl.se')
process = subprocess.Popen(shell_cmd,
                    stdout = subprocess.PIPE,
                    stderr = subprocess.PIPE,
                    text = True,
                    shell = True
                    )
std_out, std_err = process.communicate()
std_out.strip(), std_err

Utilisation de PycURL

Au lieu de vous interfacer avec votre terminal en Python, vous pouvez utiliser le package PycURL. Si vous utilisez Linux, vous avez de la chance car vous pouvez installer PycURL à l’aide de pip :

pip install pycurl
pip install certifi

Vous devez également installer certifi pour assurer l’interface sur le protocole HTTPS. Si vous rencontrez des problèmes, suivez les instructions suivantes, proposées dans Stack Overflow.

Bien que PycURL soit également installable sous Windows, il s’agit d’une tâche très frustrante. Si vous essayez de l’installer avec pip, l’erreur suivante s’affiche :

Please specify --curl-dir=/path/to/built/libcurl

C’est pourquoi vous devez l’installer à partir de la source, ce qui n’est « pas pour les âmes sensibles en raison de la multitude de dépendances possibles, chacune de ces dépendances ayant sa propre structure de répertoire, son propre style de configuration, ses propres paramètres et ses pièges spécifiques ». Pour cette raison, il est recommandé de vous en tenir au package requests pour les requêtes réseau de base si vous travaillez sur un ordinateur Windows.

Comment générer des requêtes avec PycURL

Le reste de cet article traite de la création de différents types de requêtes à l’aide du package PycURL.

Génération d’une requête GET avec PycURL

La requête la plus simple que vous puissiez faire avec PycURL est une requête GET. Il s’agit essentiellement d’un modèle pour tous les autres modèles de cette section.

Vous pouvez identifier cinq étapes dans le code suivant :

  1. Tous les packages requis sont importés.
  2. Deux objets sont créés : le tampon dans lequel la requête curl stocke sa réponse et l’objet curl, qui est utilisé pour générer la requête.
  3. Les options de la requête sont spécifiées : l’URL, la destination et la validation SSL.
  4. L’exécution de la requête.
  5. La sortie de la requête.
# Preparation
import pycurl
import certifi
from io import BytesIO

# Set buffer and Curl object.
buffer = BytesIO()
c = pycurl.Curl()

# Set request options.
## Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/')

## Set the buffer as the destination of the request's response.
c.setopt(c.WRITEDATA, buffer)

## Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
c.perform()
c.close()

# Print the buffer's content with a Latin1 (iso-8859-1) encoding.
body = buffer.getvalue()
data = body.decode('iso-8859-1')
print(data)

Génération d’une requête POST avec PycURL

La génération d’une requête POST avec PycURL est très similaire à la génération d’une requête GET. Toutefois, une option supplémentaire est ajoutée à la requête : le corps POST. Dans l’extrait de code suivant, une valeur de clé est définie et codée par URL pour garantir un traitement adéquat :

# Preparation
import pycurl
import certifi
from io import BytesIO

# Set buffer and Curl object.
buffer = BytesIO()
c = pycurl.Curl()

# Set request options.
## Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/')

## Set the request's body.
post_body = {'greeting': 'hello'}
postfields = urlencode(post_body)
c.setopt(c.POSTFIELDS, postfields)

## Set the buffer as the destination of the request's response.
c.setopt(c.WRITEDATA, buffer)

## Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
c.perform()
c.close()

# Print the buffer's content with a Latin1 (iso-8859-1) encoding.
body = buffer.getvalue()
print(body.decode('iso-8859-1'))

Génération d’une requête PUT avec PycURL

La requête POST que vous avez créée dans la section précédente peut également être envoyée en tant que requête PUT. Au lieu d’envoyer la valeur clé dans le corps de la requête, vous l’enverrez sous forme de représentation de fichier encodée en UTF-8. Cette méthode peut également être utilisée pour charger des fichiers :

import pycurl
import certifi
from io import BytesIO

c = pycurl.Curl()

# Set request options.
## Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/')

## Set data for the PUT request.
c.setopt(c.UPLOAD, 1)
data = '{"greeting": "hello"}'
buffer = BytesIO(data.encode('utf-8'))
c.setopt(c.READDATA, buffer)

## Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
c.perform()
c.close()

Téléchargement d’un fichier avec PycURL

L’extrait de code suivant montre comment un fichier peut être téléchargé à l’aide de PycURL. Une image JPEG aléatoire est demandée et un flux d’écriture est ouvert sur some_image.jpg puis transmis à PycURL comme destination pour le fichier :

import pycurl
import certifi

c = pycurl.Curl()

# Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/some_image.jpg')

# Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
with open('some_image.jpg', 'w') as f:
    c.setopt(c.WRITEFUNCTION, f.write)
    c.perform()

c.close()

Téléchargement et traitement d’une page web avec PycURL

Comme de nombreux cas d’utilisation de PycURL font intervenir du web scraping, l’extrait de code suivant décrit comment vous pouvez traiter la réponse à une requête avec Beautiful Soup, qui est un package couramment utilisé pour l’analyse de fichiers HTML.

Tout d’abord, installez Beautiful Soup 4 à l’aide de pip :

pip install beautifulsoup4

Ensuite, introduisez l’extrait de code suivant juste derrière le premier extrait de code PycURL qui a généré une requête GET. Les données de réponse seront ainsi traitées par Beautiful Soup.

Dans cette démonstration, la méthode find_all est utilisée pour rechercher tous les éléments de paragraphe, à la suite de quoi le contenu des différents paragraphes est affiché :

from bs4 import BeautifulSoup

# Parsing data using BeautifulSoup
soup = BeautifulSoup(data, 'html.parser')

# Find all paragraphs
paragraphs = soup.find_all('p')
for p in paragraphs:
   print(p.text)

Utilisation d’un proxy avec PycURL

Le web scraping sur de gros volumes de données fonctionne mieux lorsque vous travaillez avec des proxys. L’avantage est que vous pouvez émuler le comportement de navigation d’un utilisateur réel en parallèle sans que votre web scraper ne soit signalé comme un bot ou comme présentant un comportement anormal.

Dans cette dernière section, vous apprendrez comment créer une requête avec PycURL via un proxy. Pour ce faire, vous devez ajuster les options de votre requête, comme vous l’avez fait précédemment. Nous décrivons par la suite quatre paramètres, mais vous pouvez adapter cela à votre propre situation :

  1. Pour faciliter les choses, les proxys non sécurisés sont activés.
  2. Le serveur proxy est défini.
  3. Le script s’authentifie auprès du serveur.
  4. Le proxy est défini comme HTTPS.
# Enable insecure proxies
c.setopt(c.PROXY_SSL_VERIFYHOST, 0)
c.setopt(c.PROXY_SSL_VERIFYPEER, 0)

# Set proxy server
c.setopt(pycurl.PROXY, <YOUR_HTTPS_PROXY_SERVER>)

# Authenticate with the proxy server
c.setopt(pycurl.PROXYUSERPWD, f"{<YOUR_USERNAME>}:{<YOUR_PASSWORD>}")

# Set proxy type to https
c.setopt(pycurl.PROXYTYPE, 2)

Ces options peuvent être insérées n’importe où dans l’un des extraits de code décrits précédemment pour que la requête soit reroutée via le serveur proxy.

Conclusion

Dans cet article, nous vous avons expliqué en détail l’association de curl et de Python, en soulignant pourquoi vous pouvez avoir intérêt à les utiliser ensemble pour générer des requêtes complexes pour le web scraping et les tests d’applications. Nous vous avons donnés plusieurs exemples pour vous montrer la polyvalence de PycURL pour la génération de diverses requêtes réseau.

Vous pouvez également utiliser le réseau de proxys et le Web Scraper IDE de Bright Data, ce dernier étant spécialement conçu pour gérer toutes les tâches complexes pour les développeurs. Ainsi, vous pouvez vous concentrer sur les données extraites sans avoir besoin de vous préoccuper de contourner des mesures anti-scraping.