スポンサーリンク

コードが書ける!数式が書ける!AAが書ける!スタンプが貼れる!

無料の匿名掲示板型SNS「このはちゃんねる

新規会員募集中!

【Python】BeautifulSoupのfindとfind_allの使い方【スクレイピング】

265, 2019-12-12

目次

はじめに

BeautifulSoupのfindメソッドの使い方を解説しています。

findの使い方

findメソッドは↓のようにして使います。

from bs4 import BeautifulSoup

html = '''
<h1>海賊王に俺はなる!</h1>
<p>俺は世界一の海賊になるんだ!</p>
'''

soup = BeautifulSoup(html, 'html.parser')
el = soup.find('h1')
print(el)

↑のコードを実行すると↓のような結果になります。

<h1>海賊王に俺はなる!</h1>

findメソッドの公式ドキュメントとヘルプを見てみます。

bs4.elementモジュールのfindメソッドのヘルプ:

find(name=None, attrs={}, recursive=True, text=None, **kwargs) bs4.BeautifulSoupインスタンスのメソッド
    指定されたタグに一致するこのタグの最初の子のみを返します。

findメソッドは引数nameで指定されたタグ名を検索し、最初に見つけた要素を返します。
たとえば↓のようなHTMLがあった場合、

<p>にっちも</p>
<p>さっちも</p>
<p>どっちも</p>

soup.find('p')したときに取得できる要素は<p>にっちも</p>になります。
これはsoup.find_all('p', limit=1)soup.pと等価です。

soup.find_all('p', limit=1)
soup.p

findメソッドは指定した要素が見つからなかった場合はNoneを返します。

el = soup.find('nothing')
print(el) # None

attrsで属性を指定する

findメソッドの引数attrsに属性を指定することが出来ます。
attrsは辞書で指定します。この辞書の値には文字列、文字列のリスト、正規表現オブジェクト、
または文字列を引数に取りその文字列が「matches」のカスタム定義に一致するかを返す
呼び出し可能なオブジェクトを指定できます(つまりただのラムダ式です)。

たとえばクラス名を指定して検索したい場合は↓のようにします。

soup.find('p', attrs={ 'class': 'cat' })

クラス名についてはclass_というショートカットが利用できます。

soup.find('p', class_='cat')

IDについても同様です。

soup.find('p', attrs={ 'id': 'bird' })
soup.find('p', id='bird')

文字列のリストを指定した場合はOR検索を行います。
たとえばcatまたはdogのクラス名を持つ要素にヒットさせたい場合は↓のようにします。

soup.find('p', attrs={ 'class': ['cat', 'dog'] }) # OR検索

正規表現を指定するにはreモジュールを使います。

import re

soup.find('p', attrs={ 'class': re.compile('c.*') }) # 正規表現

リスト内にも正規表現を指定できます。

import re

soup.find('p', attrs={ 'class': [re.compile('c.*'), re.compile('d.*')] }) # リストと正規表現のOR検索

関数オブジェクトを指定すると内部でマッチされるたびにその関数オブジェクトが呼び出されます。
例えば↓のコードでは、

from bs4 import BeautifulSoup
import re

html = '''
<p class="cat dog">猫と犬</p>
<p class="cat bird">猫と鳥</p>
'''

soup = BeautifulSoup(html, 'html.parser')
soup.find('p', attrs={ 'class': lambda val: print(f'val[{val}]')  }) # OR検索

↓のような結果になります。

val[cat]
val[dog]
val[cat dog]
val[cat]
val[bird]
val[cat bird]

関数オブジェクトがマッチのたびに呼び出されているのがわかります。
この関数オブジェクトがTrueを返すと検索にヒットします。
例えば↓のようにです。

soup.find('p', attrs={ 'class': lambda val: val in ['cat', 'dog'] }) 

再帰を無効にする

↓のようなHTMLから、

<div>
    <p>ライ麦畑で捕まえて</p>
</div>

pタグを取りたいとします。
その場合↓のようにすれば取れますが、

soup.find('p') # <p>ライ麦畑で捕まえて</p>

recursive=Falseを指定すると再帰的な検索が無効になります。

soup.find('p', recursive=False) # None

タグの内容を指定する

findメソッドの引数textにタグの内容を指定することが出来ます。
たとえばThe catという内容を持つタグpを取得したい場合は↓のようにします。

soup.find('p', text='The cat')

また、reモジュールを使って正規表現を指定することも出来ます。

import re

soup.find('p', text=re.compile('The .*'))

find_allの使い方

find_allは複数のタグを取得したい時に使います。

from bs4 import BeautifulSoup

html = '''
<h1>海賊王に俺はなる!</h1>
<p>俺は世界一の海賊になるんだ!</p>
<p>たくさんの仲間! 女! 酒!</p>
'''

soup = BeautifulSoup(html, 'html.parser')
els = soup.find_all('p')
print(els)

↑のコードを実行すると↓のような結果になります。

[<p>俺は世界一の海賊になるんだ!</p>, <p>たくさんの仲間! 女! 酒!</p>]

find_allの公式ドキュメントとヘルプを見てみます。

bs4.elementモジュールのfind_allメソッドのヘルプ:

find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs) bs4.BeautifulSoupインスタンスのメソッド

指定された基準に一致するTagオブジェクトのリストを抽出します。
タグの名前と、タグに付ける属性を指定できます。

引数の辞書attrsの値には文字列、文字列のリスト、正規表現オブジェクト、
または文字列を引数に取りその文字列が「matches」のカスタム定義に一致するかを返す
呼び出し可能なオブジェクトを指定できます。

引数はほとんどfindと一緒です。

find_allメソッドは指定した要素が見つからなかった場合に空のリストを返します。

soup.find_all('nothing') # []

要素の最大取得数を指定する

find_allメソッドの引数limitに要素の最大取得数を指定することが出来ます。

from bs4 import BeautifulSoup

html = '''
<p>海賊王に俺はなる!</p>
<p>俺は世界一の海賊になるんだ!</p>
<p>たくさんの仲間! 女! 酒!</p>
'''

soup = BeautifulSoup(html, 'html.parser')

els = soup.find_all('p', limit=1)
print(els)
# [<p>海賊王に俺はなる!</p>]

els = soup.find_all('p', limit=2)
print(els)
# [<p>海賊王に俺はなる!</p>, <p>俺は世界一の海賊になるんだ!</p>]

els = soup.find_all('p', limit=3)
print(els)
# [<p>海賊王に俺はなる!</p>, <p>俺は世界一の海賊になるんだ!</p>, <p>たくさんの仲間! 女! 酒!</p>]

おわりに

findfind_allが使えればほとんど用は足りそうです。
それぐらいポピュラーなメソッドといえます。

美しいスープを飲んで満腹になりましょう

関連記事

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。

スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク