Python >> Tutoriel Python >  >> Python

Recherche dans l'arbre d'analyse à l'aide de BeautifulSoup

Présentation

HTML (Hypertext Markup Language) se compose de nombreuses balises et les données que nous devons extraire se trouvent à l'intérieur de ces balises. Nous devons donc trouver les bonnes balises pour extraire ce dont nous avons besoin. Maintenant, comment trouver les bonnes balises ? Nous pouvons le faire avec l'aide de BeautifulSoup's méthodes de recherche.

Beautiful Soup a de nombreuses méthodes pour rechercher un arbre d'analyse. Les deux méthodes les plus populaires et les plus courantes sont :

  1. find()
  2. find_all()

Les autres méthodes sont assez similaires en termes d'utilisation. Par conséquent, nous nous concentrerons sur le find() et find_all() méthodes dans cet article.

? L'exemple suivant seront utilisés tout au long de ce document lors de la démonstration des concepts :

html_doc = """

<html><head><title>Searching Tree</title></head>
<body>
<h1>Searching Parse Tree In BeautifulSoup</h1></p>

<p class="Main">Learning 
<a href="https://docs.python.org/3/" class="language" id="python">Python</a>,
<a href="https://docs.oracle.com/en/java/" class="language" id="java">Java</a> and
<a href="https://golang.org/doc/" class="language" id="golang">Golang</a>;
is fun!</p>

<p class="Secondary"><b>Please subscribe!</b></p>
<p class="Secondary" id= "finxter"><b>copyright - FINXTER</b></p>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, "html.parser")

Types de filtres

Il existe différents filtres qui peuvent être passés dans le find() et find_all() et il est crucial d'avoir une compréhension claire de ces filtres car ils sont utilisés encore et encore, tout au long du mécanisme de recherche. Ces filtres peuvent être utilisés en fonction des balises :

  • nom,
  • attributs,
  • sur le texte d'une chaîne,
  • ou un mélange de ceux-ci.

❖ Une chaîne

Lorsque nous passons une chaîne à une méthode de recherche puis Belle Soupe effectue une correspondance avec cette chaîne transmise. Regardons un exemple et trouvons les balises

dans le document HTML :

print(soup.find_all('h1'))

Sortie :

[<h1>Searching Parse Tree In BeautifulSoup</h1>]

❖ Une expression régulière

Passer un objet d'expression régulière permet à Beautiful Soup de filtrer les résultats en fonction de cette expression régulière. Si vous souhaitez maîtriser les concepts du module regex en Python, veuillez vous référer à notre tutoriel ici .

Remarque :

  • Nous devons importer le re module pour utiliser une expression régulière.
  • Pour obtenir uniquement le nom de la balise au lieu de tout le contenu (balise + contenu dans la balise), utilisez le .name attribut.

Exemple : Le code suivant trouve toutes les instances des balises commençant par la lettre "b".

# finding regular expressions
for regular in soup.find_all(re.compile("^b")):
    print(regular.name)

Sortie :

body
b

❖ Une liste

Plusieurs balises peuvent être transmises aux fonctions de recherche à l'aide d'une liste illustrée dans l'exemple ci-dessous :

Exemple : Le code suivant trouve toutes les balises et dans le document HTML.

for tag in soup.find_all(['a','b']):
    print(tag)

Sortie :

<a class="language" href="https://docs.python.org/3/" id="python">Python</a>
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a>
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>
<b>Please subscribe!</b>

❖ Une fonction

Nous pouvons définir une fonction et passer un élément comme argument. La fonction renvoie True en cas de correspondance, sinon il renvoie False .

Exemple : Le code suivant définit une fonction qui renvoie True pour tous les classes qui ont aussi un id dans le document HTML. On passe ensuite cette fonction au find_all() méthode pour obtenir la sortie souhaitée.

def func(tag):
    return tag.has_attr('class') and tag.has_attr('id')


for tag in soup.find_all(func):
    print(tag)

Sortie :

<a class="language" href="https://docs.python.org/3/" id="python">Python</a>
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a>
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>

➠ Maintenant que nous avons parcouru les différents types de filtres que nous utilisons avec les méthodes de recherche, nous sommes bien équipés pour plonger profondément dans le find() et find_all() méthodes.

✨ La méthode find()

Le find() est utilisée pour rechercher l'occurrence de la première instance d'une balise avec le nom nécessaire.

Syntaxe :

find(name, attrs, recursive, string, **kwargs)

find() renvoie un objet de type bs4.element.Tag .

Exemple :

print(soup.find('h1'), "\n")
print("RETURN TYPE OF find(): ",type(soup.find('h1')), "\n")
# note that only the first instance of the tag is returned
print(soup.find('a'))

Sortie :

<h1>Searching Parse Tree In BeautifulSoup</h1> 

RETURN TYPE OF find():  <class 'bs4.element.Tag'> 

<a class="language" href="https://docs.python.org/3/" id="python">Python</a>

➠ L'opération ci-dessus est la même que celle effectuée par le soup.h1 ou soupe soup.a qui renvoie également la première instance de la balise donnée. Alors, quelle est la différence ? Le find() nous aide à trouver une instance particulière d'une balise donnée à l'aide de paires clé-valeur, comme indiqué dans l'exemple ci-dessous :

print(soup.find('a',id='golang'))

Sortie :

<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>

✨ La méthode find_all()

Nous avons vu que le find() La méthode est utilisée pour rechercher la première balise. Que se passe-t-il si nous voulons trouver toutes les instances d'une balise ou de nombreuses instances d'une balise donnée dans le document HTML ? Le find_all() méthode, nous aide à rechercher toutes les balises avec le nom de balise donné et renvoie une liste de type bs4.element.ResultSet . Les éléments étant renvoyés dans une liste, ils sont accessibles à l'aide de leur index.

Syntaxe :

find_all(name, attrs, recursive, string, limit, **kwargs)

Exemple : Recherche de toutes les instances de la balise "a" dans le document HTML.

for tag in soup.find_all('a'):
    print(tag)

Sortie :

<a class="language" href="https://docs.python.org/3/" id="python">Python</a>
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a>
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>

Maintenant, il existe de nombreux autres arguments mis à part les filtres dont nous avons déjà parlé plus tôt. Examinons-les un par un.

❖ Le nom Argument

Comme indiqué précédemment, l'argument name peut être une chaîne, une expression régulière, une liste, une fonction ou la valeur True.

Exemple :

for tag in soup.find_all('p'):
    print(tag)

Sortie :

<p class="Main">Learning 
<a class="language" href="https://docs.python.org/3/" id="python">Python</a>,
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a> and
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>;
is fun!</p>
<p class="Secondary"><b>Please subscribe!</b></p>

❖ Le mot-clé Arguments

Tout comme le find() méthode, find_all() nous permet également de trouver des instances particulières d'une balise. Par exemple, si le id est passé, Beautiful Soup filtre l'attribut "id" de chaque balise et renvoie le résultat en conséquence.

Exemple :

print(soup.find_all('a',id='java'))

Sortie :

[<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a>]

Vous pouvez également transmettre les attributs sous forme de paires clé-valeur de dictionnaire à l'aide du attrs arguments.

Exemple :

print(soup.find_all('a', attrs={'id': 'java'}))

Sortie :

[<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a>]

❖ Recherche à l'aide de la classe CSS

Souvent, nous devons trouver une balise qui a une certaine classe CSS, mais l'attribut, class , est un mot clé réservé en Python. Ainsi, en utilisant class comme argument de mot-clé donnera une erreur de syntaxe . Beautiful Soup 4.1.2 nous permet de rechercher une classe CSS en utilisant le mot-clé class_

Exemple :

print(soup.find_all('p', class_='Secondary'))

Sortie :

[<p class="Secondary"><b>Please subscribe!</b></p>]

❖ Remarque :La recherche ci-dessus vous permettra de rechercher toutes les instances de la balise p avec la classe "Secondaire". Mais vous pouvez également filtrer les recherches en fonction de plusieurs attributs, à l'aide d'un dictionnaire.

Exemple :

print(soup.find_all('p', attrs={'class': 'Secondary', 'id': 'finxter'}))

Sortie :

[<p class="Secondary" id="finxter"><b>copyright - FINXTER</b></p>]

❖ L'argument de chaîne

La chaîne nous permet de rechercher des chaînes au lieu de balises.

Exemple :

print(soup.find_all(string=["Python", "Java", "Golang"]))

Sortie :

['Python', 'Java', 'Golang']

❖ L'argument limite

Le find_all() La méthode parcourt l'intégralité du document HTML et renvoie toutes les balises et chaînes correspondantes. Cela peut être extrêmement fastidieux et prendre beaucoup de temps si le document est volumineux. Ainsi, vous pouvez limiter le nombre de résultats en passant le limit dispute.

Exemple : Il y a trois liens dans l'exemple de document HTML, mais ce code ne trouve que les deux premiers :

print(soup.find_all("a", limit=2))

Sortie :

[<a class="language" href="https://docs.python.org/3/" id="python">Python</a>, <a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a>]

✨ Autres méthodes de recherche

Nous avons exploré avec succès les méthodes de recherche les plus couramment utilisées, c'est-à-dire find et find_all() . Beautiful Soup a également d'autres méthodes pour rechercher l'arbre d'analyse, mais elles sont assez similaires à ce que nous avons déjà discuté ci-dessus. Les seules différences sont où ils sont utilisés. Jetons un coup d'œil à ces méthodes.

  • find_parents() et find_parent()  :ces méthodes sont utilisées pour parcourir l'arbre d'analyse vers le haut et rechercher le(s) parent(s) d'une balise/chaîne.
  • find_next_siblings() et find_next_sibling() :ces méthodes sont utilisées pour trouver le(s) frère(s) suivant(s) d'un élément dans le document HTML.
  • find_previous_siblings() et find_previous_sibling()  :ces méthodes sont utilisées pour rechercher et itérer sur le ou les frères qui apparaissent avant l'élément actuel.
  • find_all_next() et find_next()  :ces méthodes sont utilisées pour rechercher et itérer sur le ou les frères qui apparaissent après l'élément actuel.
  • find_all_previous et find_previous()  :ces méthodes sont utilisées pour rechercher et itérer sur les balises et les chaînes qui apparaissent avant l'élément actuel dans le document HTML.

Exemple :

current = soup.find('a', id='java')
print(current.find_parent())
print()
print(current.find_parents())
print()
print(current.find_previous_sibling())
print()
print(current.find_previous_siblings())
print()
print(current.find_next())
print()
print(current.find_all_next())
print()

Sortie :

<p class="Main">Learning 
<a class="language" href="https://docs.python.org/3/" id="python">Python</a>,
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a> and
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>;
is fun!</p>

[<p class="Main">Learning 
<a class="language" href="https://docs.python.org/3/" id="python">Python</a>,
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a> and
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>;
is fun!</p>, <body>
<h1>Searching Parse Tree In BeautifulSoup</h1>
<p class="Main">Learning 
<a class="language" href="https://docs.python.org/3/" id="python">Python</a>,
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a> and
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>;
is fun!</p>
<p class="Secondary"><b>Please subscribe!</b></p>
<p class="Secondary" id="finxter"><b>copyright - FINXTER</b></p>
<p class="Secondary"><b>Please subscribe!</b></p>
</body>, <html><head><title>Searching Tree</title></head>
<body>
<h1>Searching Parse Tree In BeautifulSoup</h1>
<p class="Main">Learning 
<a class="language" href="https://docs.python.org/3/" id="python">Python</a>,
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a> and
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>;
is fun!</p>
<p class="Secondary"><b>Please subscribe!</b></p>
<p class="Secondary" id="finxter"><b>copyright - FINXTER</b></p>
<p class="Secondary"><b>Please subscribe!</b></p>
</body></html>, 
<html><head><title>Searching Tree</title></head>
<body>
<h1>Searching Parse Tree In BeautifulSoup</h1>
<p class="Main">Learning 
<a class="language" href="https://docs.python.org/3/" id="python">Python</a>,
<a class="language" href="https://docs.oracle.com/en/java/" id="java">Java</a> and
<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>;
is fun!</p>
<p class="Secondary"><b>Please subscribe!</b></p>
<p class="Secondary" id="finxter"><b>copyright - FINXTER</b></p>
<p class="Secondary"><b>Please subscribe!</b></p>
</body></html>]

<a class="language" href="https://docs.python.org/3/" id="python">Python</a>

[<a class="language" href="https://docs.python.org/3/" id="python">Python</a>]

<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>

[<a class="language" href="https://golang.org/doc/" id="golang">Golang</a>, <p class="Secondary"><b>Please subscribe!</b></p>, <b>Please subscribe!</b>, <p class="Secondary" id="finxter"><b>copyright - FINXTER</b></p>, <b>copyright - FINXTER</b>, <p class="Secondary"><b>Please subscribe!</b></p>, <b>Please subscribe!</b>]

Conclusion

Avec cela, nous arrivons à la fin de cet article; J'espère qu'après avoir lu cet article, vous pourrez facilement rechercher des éléments dans un arbre d'analyse ! Veuillez vous abonner et restez à l'écoute pour des articles plus intéressants.


Prochain article