美しいスープ-木を探す

解析ツリーを検索できるBeautifulsoupメソッドはたくさんあります。最も一般的で使用される2つのメソッドは、find()とfind_all()です。

find()とfind_all()について説明する前に、これらのメソッドに渡すことができるさまざまなフィルターの例をいくつか見てみましょう。

フィルタの種類

これらのメソッドに渡すことができるさまざまなフィルターがあり、これらのフィルターは検索API全体で何度も使用されるため、これらのフィルターを理解することが重要です。これらのフィルターは、タグの名前、属性、文字列のテキスト、またはこれらの組み合わせに基づいて使用できます。

文字列

最も単純なタイプのフィルターの1つは文字列です。検索メソッドとBeautifulsoupに文字列を渡すと、その正確な文字列に対して照合が実行されます。

以下のコードは、ドキュメント内のすべての<p>タグを検索します-

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

正規表現

特定の文字列/タグで始まるすべてのタグを見つけることができます。その前に、正規表現を使用するために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>]

リスト

リストを提供することで、複数のタグを渡して検索できます。以下のコードは、すべての<b>タグと<pre>タグを検索します-

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

本当

Trueは、検出できるすべてのタグを返しますが、それ自体では文字列を返しません-

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

上記のスープのタグのみを返すには−

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

find_all()

find_allを使用して、ページ応答から特定のタグのすべてのオカレンスを次のように抽出できます。

構文

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

IMDBからいくつかの興味深いデータを抽出しましょう-これまでの「トップレートの映画」。

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

上記から、find_allは、定義した検索条件に一致するすべてのアイテムを提供することがわかります。find_all()で使用できるすべてのフィルターは、find()や、find_parents()やfind_siblings()などの他の検索メソッドでも使用できます。

find()

上で見たように、find_all()はドキュメント全体をスキャンしてすべてのコンテンツを検索するために使用されますが、何かを見つけるには、1つの結果のみを検索する必要があります。ドキュメントに<body>タグが1つしかないことがわかっている場合は、ドキュメント全体を検索するのは時間の無駄です。1つの方法は、毎回limit = 1でfind_all()を呼び出すことです。そうでない場合は、find()メソッドを使用して同じことを行うことができます。

構文

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

したがって、以下の2つの異なる方法では、同じ出力が得られます。

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

上記の出力では、find_all()メソッドが単一のアイテムを含むリストを返すのに対し、find()メソッドは単一の結果を返すことがわかります。

find()メソッドとfind_all()メソッドのもう1つの違いは、次のとおりです。

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

soup.find_all()メソッドが何も見つからない場合、空のリストを返しますが、find()はNoneを返します。

find_parents()およびfind_parent()

ツリーをトラバースするfind_all()およびfind()メソッドとは異なり、タグの子孫を見ると、find_parents()およびfind_parentsメソッド()は反対のことを行い、ツリーを上向きにトラバースして、タグ(または文字列)の親を調べます。

構文

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

他に8つの同様の方法があります-

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)

どこ、

find_next_siblings() そして find_next_sibling() メソッドは、現在の要素の後に続く要素のすべての兄弟を反復処理します。

find_previous_siblings() そして find_previous_sibling() メソッドは、現在の要素の前にあるすべての兄弟を反復処理します。

find_all_next() そして find_next() メソッドは、現在の要素の後に続くすべてのタグと文字列を繰り返し処理します。

find_all_previous そして find_previous() メソッドは、現在の要素の前にあるすべてのタグと文字列を繰り返し処理します。

CSSセレクター

最も一般的に使用されるCSSセレクターをサポートするBeautifulSoupライブラリ。select()メソッドを使用してCSSセレクターを使用して要素を検索できます。

ここにいくつかの例があります-

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