Retour au blog
Guides
Sorin-Gabriel Marica13 juillet 20219 minutes de lecture

Extraction et analyse de données Web avec Python et BeautifulSoup

Extraction et analyse de données Web avec Python et BeautifulSoup

Présentation de BeautifulSoup

BeautifulSoup, comme indiqué dans sa documentation, est une bibliothèque Python permettant d'extraire des données de fichiers HTML et XML. Vous pouvez donc utiliser Python pour extraire le contenu HTML d'un site web, puis utiliser BeautifulSoup pour analyser ce code HTML afin d'obtenir uniquement les informations pertinentes.

Le principal avantage de BeautifulSoup réside dans la simplicité de sa syntaxe. Grâce à cette bibliothèque, vous pouvez parcourir l'arborescence DOM, rechercher des éléments spécifiques ou modifier le contenu HTML. Tous ces avantages en ont fait la bibliothèque Python la plus populaire pour l'analyse de documents HTML et XML.

Installation

Pour installer BeautifulSoup, consultez le guide disponible ici, car l'installation varie en fonction de la machine que vous utilisez. Dans cet article, j'utilise un système Linux et il me suffit d'exécuter la commande suivante :

pip install beautifulsoup4

Si vous utilisez Python 3, vous devrez peut-être installer la bibliothèque à l'aide de la commande suivante à la place :

pip3 install beautifulsoup4

Gardez à l'esprit que Python 3 est déjà installé sur ma machine. Si vous débutez avec Python, vous trouverez un guide d'installation ici. Nous vous invitons également à consulter notre guide complet sur la création d'un scraper web avec Python pour plus d'informations sur le sujet.

Créer un scraper avec BeautifulSoup

Maintenant, si tout s'est bien passé, nous sommes prêts à commencer à créer notre propre scraper. Pour cet article, j'ai choisi de récupérer les 100 meilleurs films de tous les temps sur RottenTomatoes et d'enregistrer le tout aux formats JSON et CSV.

Récupération du code source de la page

Pour nous mettre en condition et nous familiariser avec BeautifulSoup, nous allons d'abord récupérer l'intégralité du code HTML de la page et l'enregistrer dans un nouveau fichier nommé « page.txt ».

Si vous souhaitez voir le code source HTML d’une page, vous pouvez le faire dans Google Chrome en appuyant sur CTRL+U. Cela ouvrira un nouvel onglet, et vous verrez quelque chose comme ceci :

View-source page showing HTML and script tags from a movie listing page

Pour obtenir la même source avec BeautifulSoup et Python, nous pouvons utiliser le code suivant :

import requests
from bs4 import BeautifulSoup
 
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)
 
soup = BeautifulSoup(page.content, 'html.parser')
 
file = open('page.txt', mode='w', encoding='utf-8')
file.write(soup.prettify())

Dans ce code, nous envoyons une requête à la page RottenTomatoes, puis ajoutons tout le contenu de la page dans un objet BeautifulSoup. La seule utilisation de BeautifulSoup dans cet exemple est la fonction finale appelée « prettify() », qui formate le code HTML pour le rendre plus lisible.

Pour mieux comprendre cette fonction, prenons le code HTML « <div><span>Test&lt;/span></div> » : prettify ajoutera des tabulations et le transformera en ce code formaté :

<div>

   <span>

       Test

   </span>

</div>

Le résultat final du code est la création d'un fichier nommé page.txt qui contient l'intégralité du code source de notre lien :

Notepad showing page source with JSON-LD list items for a top movies table

Notez qu'il s'agit du code source de la page avant l'exécution de tout code JavaScript. Certains sites web peuvent choisir de modifier le contenu de leurs pages de manière dynamique. Dans ce cas, le code source de la page sera différent du contenu réel affiché à l'utilisateur. Si vous avez besoin que votre scraper exécute du code JavaScript, vous pouvez consulter notre guide sur la création d'un scraper web avec Selenium, ou utiliser WebScrapingAPI, notre produit qui se charge de cette tâche pour vous.

Récupération des données Web

Si vous examinez le code source de la page précédente, vous verrez que vous pouvez y trouver les titres des films et leur note. Heureusement pour nous, RottenTomatoes ne charge pas la liste des films de manière dynamique, nous pouvons donc procéder au scraping des informations nécessaires.

Tout d'abord, nous inspectons la page pour voir comment le code HTML est structuré. Pour ce faire, vous pouvez cliquer avec le bouton droit sur le titre d'un film et choisir l'option « Inspecter l'élément ». La fenêtre suivante devrait s'afficher :

Browser DevTools highlighting a table row and movie link in a Rotten Tomatoes page

J'ai utilisé la ligne rouge pour mettre en évidence les informations utiles de cette image. Vous pouvez voir que la page affiche les meilleurs films dans un tableau et qu'il y a quatre cellules sur chaque ligne du tableau (élément <tr>).

La première cellule contient la position du film, la deuxième contient des informations sur les notes (élément avec la classe tMeterScore), la troisième inclut le titre du film et la dernière cellule nous donne le nombre d'avis.

Maintenant que nous connaissons cette structure, nous pouvons commencer à extraire les informations dont nous avons besoin.

import requests
from bs4 import BeautifulSoup
 
links_base = 'https://www.rottentomatoes.com'
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)
 
soup = BeautifulSoup(page.content, 'html.parser')
 
table = soup.find("table", class_="table") # We extract just the table code from the entire page
rows = table.findAll("tr") # This will extract each table row, in an array
 
movies = []
 
for index, row in enumerate(rows):
    if index > 0: # We skip the first row since this row only contains the column names
        link = row.find("a") # We get the link from the table row
        rating = row.find(class_="tMeterScore") # We get the element with the class tMeterScore from the table row
        movies.append({
            "link": links_base + link.get('href'), # The href attribute of the link
            "title": link.string.strip(), # The strip function removes blank spaces at the beginning and the end of a string
            "rating": rating.string.strip().replace("&nbsp;", ""), # We remove &nbsp; from the string and the blank spaces
        })
        
print(movies)

En exécutant ce code, vous devriez obtenir un résultat comme celui-ci :

Terminal output showing scraped movie titles, links, and ratings formatted as JSON

Dans cet exemple, nous extrayons le contenu du tableau et parcourons les lignes du tableau. Comme la première ligne ne contient que les noms des colonnes, nous allons l'ignorer.

Pour les autres lignes, nous poursuivons le processus en extrayant l'élément d'ancrage (<a>) et l'élément span avec la classe « tMeterScore ». Une fois ces éléments en main, nous pouvons récupérer les informations nécessaires.

Le titre du film se trouve à l'intérieur de l'élément d'ancrage, le lien correspond à l'attribut « href » de l'ancrage, et la note se trouve à l'intérieur de l'élément span avec la classe « tMeterScore ». Il suffit de créer un nouveau dictionnaire pour chaque ligne et de l'ajouter à notre liste de films.

Enregistrement des données Web

Jusqu’à présent, le scraper a récupéré et formaté les données, mais nous ne les avons affichées que dans le terminal. Nous pouvons également enregistrer ces informations sur notre ordinateur au format JSON ou CSV. Le code complet du scraper (y compris la création d’un fichier local) est le suivant :

import requests
from bs4 import BeautifulSoup
import csv
import json
 
links_base = 'https://www.rottentomatoes.com'
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)
 
soup = BeautifulSoup(page.content, 'html.parser')
 
table = soup.find("table", class_="table") # We extract just the table code from the entire page
rows = table.findAll("tr") # This will extract each table row from the table, in an array
 
movies = []
 
for index, row in enumerate(rows):
    if index > 0: # We skip the first row since this row only contains the column names
        link = row.find("a") # We get the link from the table row
        rating = row.find(class_="tMeterScore") # We get the element with the class tMeterScore from the table row
        movies.append({
            "link": links_base + link.get('href'), # The href attribute of the link
            "title": link.string.strip(), # The strip function removes blank spaces at the beginning and the end of a string
            "rating": rating.string.strip().replace("&nbsp;", ""), # We remove &nbsp; from the string and the blank spaces
        })
        
file = open('movies.json', mode='w', encoding='utf-8')
file.write(json.dumps(movies))
 
writer = csv.writer(open("movies.csv", 'w'))
for movie in movies:
    writer.writerow(movie.values())

Aller encore plus loin dans le scraping

Maintenant que vous disposez de toutes les informations, vous pouvez choisir d’aller plus loin dans le scraping. N’oubliez pas que chaque film dispose d’un lien. Vous pourriez continuer en scrapant les pages des films et en extrayant encore plus d’informations à leur sujet.

Par exemple, si vous consultez la page du film It Happened One Night (1934), vous pouvez voir qu'il est encore possible d'extraire des informations utiles telles que la note du public, la durée du film, le genre, etc.

Cependant, effectuer toutes ces requêtes en peu de temps semble très inhabituel et pourrait entraîner des validations CAPTCHA, voire des blocages d'IP. Pour éviter cela, vous devriez utiliser des proxys rotatifs afin que le trafic envoyé paraisse naturel et provienne de plusieurs adresses IP.

Autres fonctionnalités de BeautifulSoup

Bien que notre scraper RottenTomatoes soit complet, BeautifulSoup a encore beaucoup à offrir. Chaque fois que vous travaillez sur un projet, vous devriez garder le lien vers la documentation ouvert afin de pouvoir rapidement rechercher une solution lorsque vous êtes bloqué.

Par exemple, BeautifulSoup permet de naviguer dans l'arborescence DOM de la page :

from bs4 import BeautifulSoup
 
soup = BeautifulSoup("<head><title>Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>", 'html.parser')
 
print(soup.head.title) # Will print "<title>Title</title>"
print(soup.body.div.p.span) # Will print "<span>Span</span>"

Cette fonctionnalité peut vous aider lorsque vous devez sélectionner un élément qui ne peut pas être identifié par ses attributs. Dans ce cas, la seule façon de le trouver est de passer par la structure du DOM.

Un autre aspect intéressant de BeautifulSoup est qu'il permet de modifier le code source de la page :

from bs4 import BeautifulSoup
 
soup = BeautifulSoup("<head><title>Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>", 'html.parser')
 
soup.head.title.string = "New Title"
print(soup)
# The line above will print "<head><title>New Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>"

Cela peut s'avérer inestimable si vous souhaitez créer un service permettant aux utilisateurs d'optimiser leurs pages. Par exemple, vous pouvez utiliser le script pour extraire le contenu d'un site web, récupérer le CSS, le minifier et le remplacer dans le code source HTML. Les possibilités sont infinies !

Effectuez toujours votre scraping de manière intelligente

Je tiens vraiment à ce que tu retiennes ceci : utiliser Python et BeautifulSoup pour le web scraping est une excellente idée. Cela rend le processus beaucoup plus simple par rapport à d'autres langages de programmation.

Le scraper que nous avons créé pour récupérer les films les mieux notés de tous les temps sur RottenTomatoes peut être codé en quelques minutes seulement, et vous pouvez même l'utiliser en complément du scraper IMDB de notre guide ultime du scraping avec PHP.

Cependant, certains sites web sont plus accessibles aux scrapers que d’autres. Si le projet présenté dans cet article est simple et amusant, certains sont tout sauf cela. Parfois, les sites web font tout ce qui est en leur pouvoir pour empêcher le scraping de leur contenu.

Dans certaines situations, la seule façon de scraper du contenu est de masquer votre activité à l'aide de plusieurs adresses IP et d'un navigateur réel. Pour ce type de situation, nous avons créé WebScrapingAPI, une solution puissante qui offre des proxys rotatifs, le rendu Javascript, et qui vous permet de scraper n'importe quel site web avec un minimum de tracas !

Ne vous contentez pas de me croire sur parole, essayez-le vous-même ! Vous pouvez commencer votre essai gratuit dès maintenant et bénéficier de 5 000 appels API sans avoir à fournir de données sensibles telles que vos informations de carte de crédit.

À propos de l'auteur
Sorin-Gabriel Marica, Développeur full-stack @ WebScrapingAPI
Sorin-Gabriel MaricaDéveloppeur full-stack

Sorin Marica est ingénieur Full Stack et DevOps chez WebScrapingAPI ; 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.