Piękna zupa - Przeszukiwanie drzewa

Istnieje wiele metod Beautifulsoup, które pozwalają nam przeszukiwać drzewo parsowania. Dwie najpopularniejsze i najczęściej używane metody to find () i find_all ().

Zanim porozmawiamy o find () i find_all (), zobaczmy kilka przykładów różnych filtrów, które możesz przekazać do tych metod.

Rodzaje filtrów

Mamy różne filtry, które możemy przekazać do tych metod, a zrozumienie tych filtrów jest kluczowe, ponieważ filtry te są używane wielokrotnie w całym API wyszukiwania. Możemy użyć tych filtrów w oparciu o nazwę tagu, jego atrybuty, tekst ciągu lub mieszankę tych elementów.

Sznurek

Jednym z najprostszych typów filtrów jest łańcuch. Przekazanie ciągu do metody wyszukiwania i Beautifulsoup przeprowadzi dopasowanie do tego dokładnego ciągu.

Poniższy kod zawiera wszystkie tagi <p> ​​w dokumencie -

>>> 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>]

Wyrażenie regularne

Możesz znaleźć wszystkie tagi zaczynające się od danego ciągu / tagu. Wcześniej musimy zaimportować moduł re, aby użyć wyrażenia regularnego.

>>> 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>]

Lista

Możesz przekazać wiele tagów do znalezienia, podając listę. Poniższy kod znajduje wszystkie tagi <b> i <pre> -

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

Prawdziwe

True zwróci wszystkie tagi, które może znaleźć, ale żadnych ciągów samodzielnie -

>>> 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>]

Aby zwrócić tylko tagi z powyższej zupy -

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

Znajdź wszystko()

Możesz użyć find_all, aby wyodrębnić wszystkie wystąpienia określonego tagu z odpowiedzi strony jako -

Składnia

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

Wyciągnijmy kilka interesujących danych z IMDB - „Najwyżej oceniane filmy” wszechczasów.

>>> 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

Z góry widzimy, że find_all poda nam wszystkie elementy pasujące do zdefiniowanych przez nas kryteriów wyszukiwania. Wszystkie filtry, których możemy użyć w funkcji find_all (), mogą być używane z funkcją find () i innymi metodami wyszukiwania, takimi jak find_parents () lub find_siblings ().

odnaleźć()

Widzieliśmy powyżej, find_all () służy do skanowania całego dokumentu w celu znalezienia całej zawartości, ale coś, wymaganiem jest znalezienie tylko jednego wyniku. Jeśli wiesz, że dokument zawiera tylko jeden tag <body>, przeszukiwanie całego dokumentu jest stratą czasu. Jednym ze sposobów jest wywołanie find_all () z limitem = 1 za każdym razem lub możemy użyć metody find (), aby zrobić to samo -

Składnia

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

Więc poniżej dwie różne metody dają ten sam wynik -

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

W powyższych wynikach widzimy, że metoda find_all () zwraca listę zawierającą pojedynczy element, podczas gdy metoda find () zwraca pojedynczy wynik.

Inną różnicą między metodą find () i find_all () jest -

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

Jeśli metoda soup.find_all () nie może niczego znaleźć, zwraca pustą listę, podczas gdy find () zwraca None.

find_parents () i find_parent ()

W przeciwieństwie do metod find_all () i find (), które przechodzą przez drzewo, patrząc na potomków tagu, metody find_parents () i find_parents () robią odwrotnie, przechodzą przez drzewo w górę i patrzą na rodziców tagu (lub łańcucha).

Składnia

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/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._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>]

Istnieje osiem innych podobnych metod -

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)

Gdzie,

find_next_siblings() i find_next_sibling() metody będą iterować po wszystkich rodzeństwach elementu, który nastąpi po bieżącym.

find_previous_siblings() i find_previous_sibling() metody będą iterować po wszystkich rodzeństwach, które występują przed bieżącym elementem.

find_all_next() i find_next() metody będą iterować po wszystkich znacznikach i ciągach znaków, które występują po bieżącym elemencie.

find_all_previous i find_previous() metody będą iterować po wszystkich znacznikach i ciągach znaków, które występują przed bieżącym elementem.

Selektory CSS

Biblioteka BeautifulSoup do obsługi najczęściej używanych selektorów CSS. Możesz wyszukiwać elementy za pomocą selektorów CSS za pomocą metody select ().

Oto kilka przykładów -

>>> 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>]