Comment travailler avec des données web en utilisant Requests et Beautiful Soup avec Python 3
Introduction
Le web nous fournit plus de données que quiconque ne peut lire et comprendre, nous voulons donc souvent travailler avec ces informations de manière programmatique afin de leur donner un sens. Parfois, ces données nous sont fournies par les créateurs de sites Web via des fichiers .csv ou des fichiers de valeurs séparées par des virgules, ou par le biais d'une API (Interface de Programmation d'Applications). D'autres fois, nous devons collecter nous-mêmes du texte sur le web.
Ce tutoriel expliquera comment travailler avec les modules Requests et Beautiful Soup en Python afin d'utiliser des données provenant des pages web. Le module Requests vous permet d'intégrer vos programmes Python avec des services web, tandis que le module Beautiful Soup est conçu pour que le scraping d'écran se fasse rapidement. En utilisant la console interactive de Python et ces deux bibliothèques, nous passerons en revue comment collecter une page web et travailler avec les informations textuelles disponibles.
Conditions préalables
Pour compléter ce tutoriel, vous aurez besoin d'un environnement de développement pour Python 3. Vous pouvez suivre le guide approprié pour votre système d'exploitation disponible dans la série Comment installer et configurer un environnement de programmation local pour Python 3 ou Comment installer Python 3 et configurer un environnement de programmation sur un serveur Ubuntu 20.04 pour configurer tout ce dont vous avez besoin.
De plus, vous devriez être familiarisé avec :
- La console interactive Python
- Importer des modules en Python 3
- Structure et balisage HTML
Avec votre environnement de développement configuré et ces concepts de programmation Python en tête, commençons à travailler avec Requests et Beautiful Soup.
Installation de Requests
Commençons par activer notre environnement de programmation Python 3. Assurez-vous d'être dans le répertoire où se trouve votre environnement et exécutez la commande suivante :
- . my_env/bin/activate
Pour travailler avec des pages web, nous allons devoir demander la page. La bibliothèque Requests vous permet d'utiliser HTTP dans vos programmes Python de manière lisible par l'homme.
Avec notre environnement de programmation activé, nous allons installer Requests avec pip :
- pip install requests
Pendant l'installation de la bibliothèque Requests, vous recevrez la sortie suivante :
Collecting requests
Downloading requests-2.26.0-py2.py3-none-any.whl (88kB)
100% |████████████████████████████████| 92kB 3.1MB/s
...
Installing collected packages: chardet, urllib3, certifi, idna, requests
Successfully installed certifi-2017.4.17 chardet-3.0.4 idna-2.5 requests-2.26.0 urllib3-1.21.1
Si Requests avait été précédemment installé, vous auriez reçu un retour similaire à ce qui suit dans votre fenêtre de terminal :
Requirement already satisfied
...
Avec Requests installé dans notre environnement de programmation, nous pouvons passer à l'installation du module suivant.
Installer Beautiful Soup
Tout comme nous l'avons fait avec Requests, nous allons installer Beautiful Soup avec pip. La version actuelle de Beautiful Soup 4 peut être installée avec la commande suivante :
- pip install beautifulsoup4
Une fois que vous exécutez cette commande, vous devriez voir une sortie qui ressemble à ceci :
Collecting beautifulsoup4
Downloading beautifulsoup4-4.10.0-py3-none-any.whl (97 kB)
|████████████████████████████████| 97 kB 6.8 MB/s
Collecting soupsieve>1.2
Downloading soupsieve-2.3.1-py3-none-any.whl (37 kB)
Installing collected packages: soupsieve, beautifulsoup4
Successfully installed beautifulsoup4-4.10.0 soupsieve-2.3.1
Maintenant que Beautiful Soup et Requests sont tous deux installés, nous pouvons passer à la compréhension de la manière de travailler avec les bibliothèques pour extraire des données de sites web.
Collecter une page Web avec Requests
Avec les deux bibliothèques Python que nous allons utiliser maintenant installées, nous pouvons nous familiariser avec la navigation sur une page web de base.
Passons d'abord dans la console interactive Python :
- python
À partir d'ici, nous allons importer le module Requests afin que nous puissions collecter un exemple de page web :
- import requests
-
Nous allons assigner l'URL (ci-dessous) de la page web d'exemple, mockturtle.html, à la variable url :
- url = 'https://assets.linux-console.net/articles/eng_python/beautiful-soup/mockturtle.html'
-
Ensuite, nous pouvons attribuer le résultat d'une requête de cette page à la variable page avec la méthode request.get(). Nous passons l'URL de la page (qui a été assignée à la variable url) à cette méthode.
- page = requests.get(url)
-
La variable page est assignée à un objet Response:
>>> page
<Response [200]>
>>>
L'objet Response ci-dessus nous indique la propriété status_code entre crochets (dans ce cas 200). Cet attribut peut être appelé explicitement :
>>> page.status_code
200
>>>
Le code renvoyé 200 nous indique que la page a été téléchargée avec succès. Les codes qui commencent par le chiffre 2 indiquent généralement un succès, tandis que les codes qui commencent par un 4 ou 5 indiquent qu'une erreur s'est produite. Vous pouvez en savoir plus sur les codes d'état HTTP dans les Définitions des Codes d'État du W3C.
Afin de travailler avec des données web, nous souhaitons accéder au contenu textuel des fichiers web. Nous pouvons lire le contenu de la réponse du serveur avec page.text (ou page.content si nous souhaitons accéder à la réponse en octets).
- page.text
Une fois que nous appuyons sur ENTER, nous recevrons la sortie suivante :
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n\n<html lang="en-US"
xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n<head>\n <meta
http-equiv="content-type" content="text/html; charset=us-ascii" />\n\n <title>Turtle
Soup</title>\n</head>\n\n<body>\n <h1>Turtle Soup</h1>\n\n <p class="verse"
id="first">Beautiful Soup, so rich and green,<br />\n Waiting in a hot tureen!<br />\n Who for
such dainties would not stoop?<br />\n Soup of the evening, beautiful Soup!<br />\n Soup of
the evening, beautiful Soup!<br /></p>\n\n <p class="chorus" id="second">Beau--ootiful
Soo--oop!<br />\n Beau--ootiful Soo--oop!<br />\n Soo--oop of the e--e--evening,<br />\n
Beautiful, beautiful Soup!<br /></p>\n\n <p class="verse" id="third">Beautiful Soup! Who cares
for fish,<br />\n Game or any other dish?<br />\n Who would not give all else for two<br />\n
Pennyworth only of Beautiful Soup?<br />\n Pennyworth only of beautiful Soup?<br /></p>\n\n
<p class="chorus" id="fourth">Beau--ootiful Soo--oop!<br />\n Beau--ootiful Soo--oop!<br />\n
Soo--oop of the e--e--evening,<br />\n Beautiful, beauti--FUL SOUP!<br
/></p>\n</body>\n</html>\n'
>>>
Ici, nous voyons que le texte complet de la page a été imprimé, avec tous ses balises HTML. Cependant, il est difficile à lire car il n'y a pas beaucoup d'espacement.
Dans la section suivante, nous pouvons tirer parti du module Beautiful Soup pour travailler avec ces données textuelles de manière plus conviviale.
Parcourir une page avec Beautiful Soup
La bibliothèque Beautiful Soup crée un arbre d'analyse à partir de documents HTML et XML analysés (y compris des documents avec des balises non fermées ou du "tag soup" et d'autres balisages mal formés). Cette fonctionnalité rendra le texte de la page Web plus lisible que ce que nous avons vu provenant du module Requests.
Pour commencer, nous allons importer Beautiful Soup dans la console Python :
- from bs4 import BeautifulSoup
-
Ensuite, nous allons passer le document page.text dans le module pour nous donner un objet BeautifulSoup — c'est-à-dire un arbre d'analyse de cette page analysée que nous obtiendrons en exécutant le html.parser intégré de Python sur le HTML. L'objet construit représente le document mockturtle.html en tant que structure de données imbriquée. Cela est assigné à la variable soup.
- soup = BeautifulSoup(page.text, 'html.parser')
-
Pour afficher le contenu de la page dans le terminal, nous pouvons l'imprimer avec la méthode prettify() afin de transformer l'arbre de parsing de Beautiful Soup en une chaîne Unicode joliment formatée.
- print(soup.prettify())
Cela rendra chaque balise HTML sur sa propre ligne :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
<title>
Turtle Soup
</title>
</head>
<body>
<h1>
Turtle Soup
</h1>
<p class="verse" id="first">
Beautiful Soup, so rich and green,
<br/>
Waiting in a hot tureen!
<br/>
Who for such dainties would not stoop?
<br/>
Soup of the evening, beautiful Soup!
...
</html>
Dans la sortie ci-dessus, nous pouvons voir qu'il y a une étiquette par ligne et aussi que les étiquettes sont imbriquées en raison du schéma en arbre utilisé par Beautiful Soup.
Trouver des instances d'une balise
Nous pouvons extraire une seule balise d'une page en utilisant la méthode find_all de Beautiful Soup. Cela renverra toutes les instances d'une balise donnée dans un document.
- soup.find_all('p')
L'exécution de cette méthode sur notre objet renvoie le texte complet de la chanson ainsi que les balises <p> pertinentes et toutes les balises contenues dans cette balise demandée, qui inclut ici les balises de saut de ligne <br/> :
[<p class="verse" id="first">Beautiful Soup, so rich and green,<br/>
Waiting in a hot tureen!<br/>
Who for such dainties would not stoop?<br/>
Soup of the evening, beautiful Soup!<br/>
Soup of the evening, beautiful Soup!<br/></p>, <p class="chorus" id="second">Beau--ootiful Soo--oop!<br/>
...
Beau--ootiful Soo--oop!<br/>
Soo--oop of the e--e--evening,<br/>
Beautiful, beauti--FUL SOUP!<br/></p>]
Vous remarquerez dans la sortie ci-dessus que les données sont contenues dans des crochets [ ]. Cela signifie qu'il s'agit d'un type de données liste en Python.
Parce que c'est une liste, nous pouvons appeler un élément particulier à l'intérieur (par exemple, le troisième élément <p>), et utiliser la méthode get_text() pour extraire tout le texte à l'intérieur de cette balise:
- soup.find_all('p')[2].get_text()
La sortie que nous recevons sera ce qui se trouve dans le troisième élément <p> dans ce cas :
'Beautiful Soup! Who cares for fish,\n Game or any other dish?\n Who would not give all else for two\n Pennyworth only of Beautiful Soup?\n Pennyworth only of beautiful Soup?'
Notez que les retours à la ligne \n sont également affichés dans la chaîne retournée ci-dessus.
Trouver des balises par classe et identifiant
Les éléments HTML qui se réfèrent aux sélecteurs CSS comme les classes et les ID peuvent être utiles à examiner lors du travail avec des données web en utilisant Beautiful Soup. Nous pouvons cibler des classes et des ID spécifiques en utilisant la méthode find_all() et en passant les chaînes de classe et d'ID en tant qu'arguments.
Tout d'abord, cherchons toutes les instances de la classe chorus. Dans Beautiful Soup, nous assignerons la chaîne pour la classe au paramètre clé class_ :
- soup.find_all(class_='chorus')
Lorsque nous exécutons la ligne ci-dessus, nous recevrons la liste suivante en sortie :
[<p class="chorus" id="second">Beau--ootiful Soo--oop!<br/>
Beau--ootiful Soo--oop!<br/>
Soo--oop of the e--e--evening,<br/>
Beautiful, beautiful Soup!<br/></p>, <p class="chorus" id="fourth">Beau--ootiful Soo--oop!<br/>
Beau--ootiful Soo--oop!<br/>
Soo--oop of the e--e--evening,<br/>
Beautiful, beauti--FUL SOUP!<br/></p>]
Les deux sections taguées <p> avec la classe chorus ont été imprimées dans le terminal.
Nous pouvons également préciser que nous voulons rechercher la classe chorus uniquement dans les balises <p>, au cas où elle serait utilisée pour plus d'une balise :
- soup.find_all('p', class_='chorus')
Exécuter la ligne ci-dessus produira le même résultat qu'auparavant.
Nous pouvons également utiliser Beautiful Soup pour cibler les identifiants associés aux balises HTML. Dans ce cas, nous allons assigner la chaîne 'third' à l'argument clé id :
- soup.find_all(id='third')
Une fois que nous exécutons la ligne ci-dessus, nous recevrons la sortie suivante :
[<p class="verse" id="third">Beautiful Soup! Who cares for fish,<br/>
Game or any other dish?<br/>
Who would not give all else for two<br/>
Pennyworth only of Beautiful Soup?<br/>
Pennyworth only of beautiful Soup?<br/></p>]
Le texte associé à la balise <p> avec l'identifiant third est affiché dans le terminal avec les balises pertinentes.
Conclusion
Ce tutoriel vous a montré comment récupérer une page web avec le module Requests en Python et effectuer un premier parsing des données textuelles de cette page web afin de comprendre Beautiful Soup.
À partir de là, vous pouvez passer à la création d'un programme de web scraping qui générera un fichier CSV à partir des données collectées sur le web en suivant le tutoriel Comment extraire des pages Web avec Beautiful Soup et Python 3.