【Python】BeautifulSoup4のfind()の使い方をわかりやすく解説
- 作成日: 2021-08-09
- 更新日: 2023-12-26
- カテゴリ: Python
BeautifulSoup4のfindの使い方
Pythonの外部ライブラリであるBeautifulSoup4を使うとHTML/XMLを簡単にパースすることが出来ます。
この記事ではBeautifulSoup4の中でも利用頻度の高いfind()
メソッドについて解説します。
find()
メソッドと同じインターフェースを持つメソッドは複数あり、find()
の使い方を覚えればこれらのメソッドも使うことが出来るようになります。
具体的には↓を見ていきます。
- 前提とするHTML
- find()を使う準備
- find()の構造
- find()は見つからなかったらNoneを返す
- nameにタグ名を指定してタグを取得
- attrsに属性名と属性値を指定して要素を取得する
- **kwargsにidとclass_を指定して要素を取得する
- textに文字列を指定して要素を取得する
- recursiveで検索深度を調整する
関連記事
BeautifulSoup4のattrsの使い方【Python】
BeautifulSoup4でtableをパースする方法【Python, スクレイピング】
BeautifulSoup4でhrefの値を捕まえる方法
前提とするHTML
今回の解説では↓のHTMLコードを前提に解説します。
このHTMLをBeautifulSoup4でパースして、タグなどを取得します。
html = '''
<div>
<p>one</p>
<span class="bird">two</span>
<strong id="pig" class="dog">three</strong>
<p key1="value1">four</p>
<p key1="value1" key2="value2">five</p>
<div>
<p class="cow">six</p>
</div>
</div>
'''
HTMLは<p>
タグや<span>
や<strong>
などのタグが複数含まれるHTMLで、階層もあります。
find()
は階層を辿っていくメソッドなので、このようにサンプルのHTMLで階層を付けるようにしています。
また、各タグにはid
やclass
などの属性も付けています。これらはfind()
の引数で指定されます。
find()を使う準備
find()
を使うにはBeautifulSoup
をインポートしておく必要があります。
from bs4 import BeautifulSoup
そして先述のHTMLをコンストラクタに渡してスープにします。
soup = BeautifulSoup(html, 'html.parser')
print(type(soup))
# <class 'bs4.BeautifulSoup'>
今回はパーサーはhtml.parser
を指定しています。
これは標準ライブラリで用意されている標準的なPythonのHTMLパーサーです。
速度も厳密性もほどほどな中立的なパーサーです。
find()
メソッドはこのsoup
のメソッドです。
以降はこのsoup
変数からfind()
を使います。
find()の構造
find()
メソッドの構造は↓のようになっています。
def find(
self,
name=None, # 検索するタグ名
attrs={}, # 検索する属性と属性値
recursive=True, # 再帰的に検索するならTrue
text=None, # 検索するタグのテキスト
**kwargs # キーワード引数
):
...
find()
は↑のような引数を取り、返り値を1つ返します。
タグが見つかった場合はタグ(bs4.element.Tag
)を返し、タグが見つからなかった場合はNone
を返します。
name
はタグ名です。これに検索したいタグ名を指定します。たとえばp
とかdiv
です。
attrs
は検索するタグの属性名と属性値の辞書です。これはたとえば{ 'class': 'bird' }
などのようになります。
recursive
は検索を再帰的に行うかどうかのフラグです。このフラグはデフォルトでTrue
です。フラグがFalse
のとき、検索は1階層にのみ行われ、再帰的に階層を辿らなくなります。
text
は検索するタグのテキスト・コンテンツです。text
を指定した場合、返り値はタグではなくNavigableString
になります。
find()
の実装は非常にシンプルです。内部ではfind_all()
を呼び出して、その結果の第1要素を返すだけのメソッドです。
つまりfind()
の実装のほとんどはfind_all()
です。
find()は見つからなかったらNoneを返す
find()
はタグが見つからなかった場合はNone
を返します。
↓の場合、第1引数にタグ名nothing
を指定していますが、そのようなタグ名のタグは存在しないため、None
が返ってきています。
tag = soup.find('nothing')
print(tag)
# None
nameにタグ名を指定してタグを取得
find()
の第1引数のname
にタグ名を指定すると、find()
はそのタグ名のタグを検索します。
tag = soup.find('p')
print(type(tag)) # <class 'bs4.element.Tag'>
print(tag.text) # one
明示的にname
を指定しても問題ありません。
tag = soup.find(name='p')
print(tag.text)
# one
タグ名にはタグの名前(div
, p
, span
など)をどれでも指定可能です。
tag = soup.find('span')
print(tag.text)
# two
attrsに属性名と属性値を指定して要素を取得する
find()
の引数のattrs
に辞書で属性と属性値を指定すると、その属性と属性値を持つタグを検索できます。
tag = soup.find(attrs={ 'class': 'bird' })
print(type(tag)) # <class 'bs4.element.Tag'>
print(tag.text) # two
attrs
の値を複数指定した場合、検索はAND
検索になります。
つまり↓の場合、key1
とkey2
の両方を持っているタグを取得することになります。
tag = soup.find(attrs={ 'key1': 'value1', 'key2': 'value2' })
print(tag.text)
# five
attrs
にはclass
やid
も指定可能ですが、これらは利用頻度の高い属性のため、後述のキーワード引数で指定することが出来ます。
**kwargsにidとclass_を指定して要素を取得する
find()
のキーワード引数にid
を指定すると、その値のid
属性を持つタグを検索できます。
tag = soup.find(id='pig')
print(tag.text)
# three
↑の場合はid
がpig
のタグを検索しています。
tag = soup.find(class_='dog')
print(tag.text)
# three
textに文字列を指定して要素を取得する
find()
の引数text
に文字列を指定すると、その文字列を持つタグを検索できます。
ns = soup.find(text='two')
print(type(ns)) # <class 'bs4.element.NavigableString'>
print(ns) # two
text
を指定した場合は返り値はNavigableString
になります。
見つからなかった場合はNone
を返すので、目的のテキストを持っているタグがあるかどうかの判定に使えそうです。
def has_text(soup, text):
return bool(soup.find(text=text))
print(has_text(soup, 'one')) # True
print(has_text(soup, 'nothing')) # False
recursiveで検索深度を調整する
find()
の引数recursive
にTrue
を指定すると、検索で再帰的にタグの子要素を辿るようになります。
デフォルトではTrue
になってます。
tag = soup.find(class_='cow', recursive=True)
print(tag.text)
# six
recursive
をFalse
にするとタグの子要素を再帰的に辿らなくなります。
tag = soup.find(class_='cow', recursive=False)
print(tag)
# None
つまり第1階層のタグのみを取得できるということになります。
tag = soup.find('div', recursive=False)
print(tag.name)
# div
おわりに
今回はBeautifulSoup4のfind()
メソッドについて見てみました。
find()
は利用頻度の高いメソッドと言えます。
🦝 < 探し物は何ですか?
🐭 < バイナリの中も、HTMLの中も・・・