Belle soupe - Recherche de l'arbre

Il existe de nombreuses méthodes Beautifulsoup, ce qui nous permet de rechercher un arbre d'analyse. Les deux méthodes les plus courantes et les plus utilisées sont find () et find_all ().

Avant de parler de find () et find_all (), voyons quelques exemples de différents filtres que vous pouvez passer dans ces méthodes.

Types de filtres

Nous avons différents filtres que nous pouvons transmettre à ces méthodes et la compréhension de ces filtres est cruciale car ces filtres sont utilisés encore et encore, tout au long de l'API de recherche. Nous pouvons utiliser ces filtres en fonction du nom de la balise, de ses attributs, du texte d'une chaîne ou d'un mélange de ceux-ci.

Un string

L'un des types de filtre les plus simples est une chaîne. En passant une chaîne à la méthode de recherche, Beautifulsoup effectuera une correspondance avec cette chaîne exacte.

Le code ci-dessous trouvera toutes les balises <p> dans le document -

>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>> markup.find_all('p')
[<p>Top Three</p>, <p></p>, <p><b>Java, Python, Cplusplus</b></p>]

Expression régulière

Vous pouvez trouver toutes les balises commençant par une chaîne / balise donnée. Avant cela, nous devons importer le module re pour utiliser une expression régulière.

>>> import re
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>>
>>> markup.find_all(re.compile('^p'))
[<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>]

liste

Vous pouvez transmettre plusieurs balises à rechercher en fournissant une liste. Le code ci-dessous trouve toutes les balises <b> et <pre> -

>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]

Vrai

True renverra toutes les balises qu'il peut trouver, mais aucune chaîne seule -

>>> markup.find_all(True)
[<html><body><p>Top Three</p><p></p><pre>Programming Languages are:</pre>
<p><b>Java, Python, Cplusplus</b> </p> </body></html>, 
<body><p>Top Three</p><p></p><pre> Programming Languages are:</pre><p><b>Java, Python, Cplusplus</b></p>
</body>, 
<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>, <b>Java, Python, Cplusplus</b>]

Pour ne renvoyer que les balises de la soupe ci-dessus -

>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'

Trouver tout()

Vous pouvez utiliser find_all pour extraire toutes les occurrences d'une balise particulière de la réponse de la page comme -

Syntaxe

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

Extrayons quelques données intéressantes d'IMDB - «Films les mieux notés» de tous les temps.

>>> url="https://www.imdb.com/chart/top/?ref_=nv_mv_250"
>>> content = requests.get(url)
>>> soup = BeautifulSoup(content.text, 'html.parser')
#Extract title Page
>>> print(soup.find('title'))
<title>IMDb Top 250 - IMDb</title>

#Extracting main heading
>>> for heading in soup.find_all('h1'):
   print(heading.text)
Top Rated Movies

#Extracting sub-heading
>>> for heading in soup.find_all('h3'):
   print(heading.text)
   
IMDb Charts
You Have Seen
   IMDb Charts
   Top India Charts
Top Rated Movies by Genre
Recently Viewed

D'en haut, nous pouvons voir que find_all nous donnera tous les éléments correspondant aux critères de recherche que nous définissons. Tous les filtres que nous pouvons utiliser avec find_all () peuvent être utilisés avec find () et d'autres méthodes de recherche comme find_parents () ou find_siblings ().

trouver()

Nous l'avons vu plus haut, find_all () est utilisé pour scanner tout le document pour trouver tout le contenu mais quelque chose, la condition est de ne trouver qu'un seul résultat. Si vous savez que le document ne contient qu'une seule balise <body>, il est inutile de rechercher l'ensemble du document. Une façon est d'appeler find_all () avec limit = 1 à chaque fois ou bien nous pouvons utiliser la méthode find () pour faire de même -

Syntaxe

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

Donc, en dessous de deux méthodes différentes donne le même résultat -

>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>

Dans les sorties ci-dessus, nous pouvons voir que la méthode find_all () renvoie une liste contenant un seul élément tandis que la méthode find () renvoie un seul résultat.

Une autre différence entre les méthodes find () et find_all () est -

>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')

Si la méthode soup.find_all () ne trouve rien, elle renvoie une liste vide alors que find () renvoie None.

find_parents () et find_parent ()

Contrairement aux méthodes find_all () et find () qui traversent l'arbre, en regardant les descendants de la balise, les méthodes find_parents () et find_parents () font le contraire, elles traversent l'arbre vers le haut et regardent les parents d'une balise (ou d'une chaîne).

Syntaxe

find_parents(name, attrs, string, limit, **kwargs)
find_parent(name, attrs, string, **kwargs)

>>> a_string = soup.find(string="The Godfather")
>>> a_string
'The Godfather'
>>> a_string.find_parents('a')
[<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>]
>>> a_string.find_parent('a')
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
>>> a_string.find_parent('tr')
<tr>

<td class="posterColumn">
<span data-value="2" name="rk"></span>
<span data-value="9.149038526210072" name="ir"></span>
<span data-value="6.93792E10" name="us"></span>
<span data-value="1485540" name="nv"></span>
<span data-value="-1.850961473789928" name="ur"></span>
<a href="/title/tt0068646/"> <img alt="The Godfather" height="67" src="https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUt[email protected]._V1_UY67_CR1,0,45,67_AL_.jpg" width="45"/>
</a> </td>
<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>
<td class="ratingColumn imdbRating">
<strong title="9.1 based on 1,485,540 user ratings">9.1</strong>
</td>
<td class="ratingColumn">
<div class="seen-widget seen-widget-tt0068646 pending" data-titleid="tt0068646">
<div class="boundary">
<div class="popover">
<span class="delete"> </span><ol><li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9<li>10</li>0</li></li></li></li&td;</li></li></li></li></li></ol> </div>
</div>
<div class="inline">
<div class="pending"></div>
<div class="unseeable">NOT YET RELEASED</div>
<div class="unseen"> </div>
<div class="rating"></div>
<div class="seen">Seen</div>
</div>
</div>
</td>
<td class="watchlistColumn">

<div class="wlb_ribbon" data-recordmetrics="true" data-tconst="tt0068646"></div>
</td>
</tr>
>>>
>>> a_string.find_parents('td')
[<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>]

Il existe huit autres méthodes similaires -

find_next_siblings(name, attrs, string, limit, **kwargs)
find_next_sibling(name, attrs, string, **kwargs)

find_previous_siblings(name, attrs, string, limit, **kwargs)
find_previous_sibling(name, attrs, string, **kwargs)

find_all_next(name, attrs, string, limit, **kwargs)
find_next(name, attrs, string, **kwargs)

find_all_previous(name, attrs, string, limit, **kwargs)
find_previous(name, attrs, string, **kwargs)

Où,

find_next_siblings() et find_next_sibling() Les méthodes itéreront sur tous les frères de l'élément qui viennent après celui en cours.

find_previous_siblings() et find_previous_sibling() Les méthodes itéreront sur tous les frères qui précèdent l'élément actuel.

find_all_next() et find_next() Les méthodes itéreront sur toutes les balises et chaînes qui suivent l'élément courant.

find_all_previous et find_previous() Les méthodes itéreront sur toutes les balises et chaînes qui précèdent l'élément actuel.

Sélecteurs CSS

La bibliothèque BeautifulSoup pour prendre en charge les sélecteurs CSS les plus couramment utilisés. Vous pouvez rechercher des éléments à l'aide des sélecteurs CSS à l'aide de la méthode select ().

Voici quelques exemples -

>>> soup.select('title')
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>>
>>> soup.select("p:nth-of-type(1)")
[<p>The Top Rated Movie list only includes theatrical features.</p>, <p> class="imdb-footer__copyright _2-iNNCFskmr4l2OFN2DRsf">© 1990-2019 by IMDb.com, Inc.</p>]
>>> len(soup.select("p:nth-of-type(1)"))
2
>>> len(soup.select("a"))
609
>>> len(soup.select("p"))
2

>>> soup.select("html head title")
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>> soup.select("head > title")
[<title>IMDb Top 250 - IMDb</title>]

#print HTML code of the tenth li elemnet
>>> soup.select("li:nth-of-type(10)")
[<li class="subnav_item_main">
<a href="/search/title?genres=film_noir&sort=user_rating,desc&title_type=feature&num_votes=25000,">Film-Noir
</a> </li>]