Introduction à Beautiful Soup 4
Beautiful Soup est une bibliothèque Python largement utilisée pour extraire des informations à partir de fichiers HTML et XML. Bien que la version 3 ait existé par le passé, la version actuelle et recommandée est Beautiful Soup 4 (BS4).
Pour commencer, installez la bibliothèque via pip :
pip install beautifulsoup4
Beautiful Soup nécessite un analyseur (parser) pour traiter le code source. Bien que Python inclue html.parser par défaut, l'utilisation de lxml est fortement recommandée pour sa rapidité et sa flexibilité :
pip install lxml
Concepts de base et types d'objets
BS4 transforme un document complexe en une structure d'objets Python imbriqués. On distingue principalement quatre types d'objets :
1. L'objet Tag
Un objet Tag correspond à une balise HTML ou XML réelle. Par exemple, dans <b class="titre">Hello</b>, le tag est "b".
- Name : Accessible via
tag.name. Il est possible de le modifier pour refléter un changement dans l'arbre syntaxique. - Attributes : Les attributs d'une balise se manipulent comme un dictionnaire Python.
tag['class']renverra la valeur de l'attribut.
2. NavigableString
Il s'agit du texte contenu à l'intérieur d'une balise. On y accède via tag.string. Contrairement à une chaîne de caractères classique, cet objet supporte certaines fonctionnalités de navigation de Beautiful Soup.
3. BeautifulSoup
C'est l'objet racine qui représente l'intégralité du document analysé. Il se comporte globalement comme un objet Tag.
Exemples pratiques de manipulation
Voici comment initialiser l'analyse d'un document :
from bs4 import BeautifulSoup
html_doc = """
<div id="main">
<p class="description">Bienvenue sur notre site</p>
<a href="http://example.com/1" class="lien" id="link1">Lien 1</a>
<a href="http://example.com/2" class="lien" id="link2">Lien 2</a>
</div>
"""
# Création de l'objet soup
analyseur = BeautifulSoup(html_doc, 'lxml')
Recherche d'éléments avec find_all()
La méthode find_all() parcourt les descendants d'un tag et récupère tous ceux qui correspondent aux filtres appliqués.
# Trouver toutes les balises 'a'
tous_les_liens = analyseur.find_all('a')
# Utilisation d'une liste pour plusieurs types de balises
elements = analyseur.find_all(['p', 'a'])
# Recherche par attribut spécifique
lien_specifique = analyseur.find_all(id="link2")
Le cas particulier de l'attribut "class"
Puisque class est un mot-clé réservé en Python, Beautiful Soup utilise l'argument class_ pour filtrer par classe CSS :
# Trouver les balises avec la classe 'lien'
liens_css = analyseur.find_all("a", class_="lien")
Navigation avancée et filtres
Il est possible de filtrer les résultats en utilisant des dictionnaires pour des attributs personnalisés (comme data-* en HTML5) :
# Recherche avec un dictionnaire d'attributs
bloc = analyseur.find_all("div", attrs={"id": "main"})
Pour limiter la recherche aux enfants directs (sans descendre dans toute l'arborescence), utilisez l'argument recursive :
# Ne cherche que parmi les enfants directs
resultats = analyseur.find_all("p", recursive=False)
Navigation dans l'arborescence
Beautiful Soup permet de se déplacer horizontalement ou verticalement dans le DOM :
- Parent :
find_parent()etfind_parents()permettent de remonter vers les éléments ancêtres. - Frères (Siblings) :
find_next_sibling()etfind_previous_sibling()accèdent aux éléments situés au même niveau hiérarchique. - Directionnel :
find_next()cherche l'élément suivant dans l'ordre de lecture du document, qu'il soit un frère ou non.
Extraction de texte brut
Pour récupérer uniquement le contenu textuel d'un élément ou d'un document, la méthode get_text() est la plus efficace. Elle concatène tout le texte des fils de manière récursive :
contenu_global = analyseur.get_text()
# On peut spécifier un séparateur
texte_propre = analyseur.div.get_text(separator=" | ")
La différence majeure entre .string et get_text() est que .string renvoie None si la balise contient plusieurs sous-balises, alors que get_text() récupère l'intégralité du contenu visible.