0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Beautiful Soup 4 で要素を取得する find 系と select 系の違い

Last updated at Posted at 2025-12-14

beautifulsoup4==4.12.3 で動作確認しています。

まとめ

Beautiful Soup 4 で特定の HTML 要素を取得するには、要素のタグ名・属性・内部文字列に条件指定する .find() .find_all() と、要素を CSS セレクタで指定する .select_one() .select() があります。

  • find 系はタグ名・属性・内部文字列への条件を関数で渡すこともできるので柔軟です。
  • select 系で内部文字列への判定をするには Beautiful Soup 4 用 CSS セレクタライブラリ Soup Sieve の独自疑似クラス :-soup-contains(-own) を使う必要があります。ただし、判定できるのは「文字列を含むか」までで、先頭一致や正規表現マッチはとれません。select 系で要素を取得するのは CSS セレクタの利用が便利な場合になると思います。

スニペット

以下の HTML は 7 つの div があります (6, 7 番目の div は 5 番目の div の子要素です)。

from bs4 import BeautifulSoup

text = (
    '<div class="red fruit">APPLE</div>'
    '<div class="red fruit">FIG</div>'
    '<div class="yellow fruit">BANANA</div>'
    '<div class="yellow fruit">LEMON</div>'
    '<div class="red vehicle">'
    'FIRE ENGINE'
    '<div>HOSE</div>'
    '<div>LADDER</div>'
    '</div>'
)
soup = BeautifulSoup(text, 'html.parser')

# すべての div を取得する
elms = soup.find_all('div')
assert len(elms) == 7
elms = soup.select('div')
assert len(elms) == 7

# 黄色い果物クラスである div を一つ取得する (黄色いと果物は順不同)
elm = soup.find('div', class_=lambda v: v and ('yellow' in v) and ('fruit' in v))
assert elm.string == 'BANANA'
elm = soup.select_one('div.yellow.fruit')
assert elm.string == 'BANANA'

# 赤い車クラスである div の2番目の子 div を取得する (赤いと車は順序指定)
elm = soup.find('div', class_=lambda v: v == 'red vehicle').find_all('div', recursive=False)[1]
assert elm.string == 'LADDER'
elm = soup.select_one('div[class="red vehicle"] > div:nth-of-type(2)')
assert elm.string == 'LADDER'

# 中身が文字列のみでかつその文字列が L で始まる div を取得する
# ※ 中身が文字列のみのとき .string でアクセス可 (文字列のみでないときこれは None)
elms = soup.find_all('div', string=lambda v: v and v.startswith('L'))
assert len(elms) == 2
assert elms[0].string == 'LEMON'
assert elms[1].string == 'LADDER'
elms = soup.select('div:-soup-contains-own("L")')  # 「直下に L を含む」は取れるが先頭かは判定不可
assert len(elms) == 3  # 先頭かまでは判定不可なので APPLE も取得される
elms = [elm for elm in elms if elm.string and elm.string.startswith('L')]  # 改めて先頭が L かで絞る
assert len(elms) == 2
assert elms[0].string == 'LEMON'
assert elms[1].string == 'LADDER'

# 中身が文字列のみでなくても F で始まる div を取得する
elms = soup.find_all(lambda tag: (tag.name == 'div') and tag.get_text().startswith('F'))
assert len(elms) == 2
assert elms[0].string == 'FIG'
assert elms[1].contents[0].string == 'FIRE ENGINE'
elms = soup.select('div:-soup-contains-own("F")')  # 「直下に F を含む」は取れるが先頭かは判定不可
elms = [elm for elm in elms if elm.get_text().startswith('F')]  # 改めて先頭が F かで絞る
assert len(elms) == 2
assert elms[0].string == 'FIG'
assert elms[1].contents[0].string == 'FIRE ENGINE'

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?