Closed3
soup.find() vs soup.select() in Python BeautifulSoup4
モチベーション
PythonのBeautifulSoup4でsoup.find()
かsoup.select()
の使い分けを悩んで調べたのでメモ
個人的見解
単純なスクレイピングの場合、この(プロダクトの実装)レベルでパフォーマンスチューニングに走るのは悪手なので、読みやすさやメンテナンス性を重視して使い分けるとよい
特に1回数ページほどのバッチタスクの場合、顕著ではないのは自明であるため。
パフォーマンス的な話
- 内部実装のパフォーマンス的には
.find()
の方が効率的- dictのindex accessをつかっているから
-
.select
だと、一度re
モジュールを呼び出してタグの中身を解析している- BeautifulSoup 4.7で追加されたコードとのことなので、こちらの方がtype hintもある
細かい使い分けをどうするか
-
.select
はHTML構造的に深いタグを取る場合に使いやすい-
.find
をチェーンして使うことになると、早期ガードの可能性も増える-
bs4.Tag
の.find("div").div
などになり、未定義属性にアクセスすることになるので、メンテナンス性が損なわれる
-
-
- 深くない(直接の子要素でclass指定などで取れる)場合は
.find
でよい - 再帰的に取りたい場合は
.find
を使うしかない
Example
<body>
<h1 class="heading1">This is title!!</h1>
<div>
<a class="link-style1" href="#h1">this is an external URL</a>
</div>
<div>this is a veeeeery loooong detail</div>
<div>
<h2>This is the summary<h2>
<ul>
<li>
<a class="link-style2" href="#section1">this is an internal URL 1</a>
</li>
<li>
<a class="link-style2" href="#section2">this is an internal URL 2</a>
</li>
<li>
<a class="link-style2" href="#section3">this is an internal URL 3</a>
</li>
</ul>
</div>
</body>
soup = bs4.beautifulsoup(html, "html.parser")
recomennded_select: str = soup.select_one("#main > div > a.link-style1")
# -> '<a class="some-class">this is an anchor URL</a>'
may_use_find1 = soup.find("h1", class_="heading1")
# -> '<h1 class="heading1">This is title!!</h1>'
recommended_find2 = soup.find_all("a", recursive=True)
# ->
# [
# '<a class="link-style1" href="#h1">this is an external URL</a>',
# '<a class="link-style2" href="#section1">this is an internal URL 1</a>'
# ...
# ]
このスクラップは2023/01/03にクローズされました