プログラミング

BeautifulSoupのfind()とfind_all()の使い方の違い【Python】

スクレイピングするときによく使われるPythonライブラリ「BeautifulSoup」で、HTML要素を取得する際に用いられるメソッドにfindメソッドがありますが、findメソッドにはfind()とfind_all()があります。

find()

find()メソッドは最初の要素のみを取り出す時に使います。

例えば、このサイトのトップページに表示されている記事のタイトルを取得する際に、次のようなコードを実行したとします。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen(‘https://kubogen.com/’)
bs = BeautifulSoup(html.read(), ‘html.parser’)

article = bs.find(‘h2’, {‘class’:’entry-title’})
print(article.get_text())

トップページには16個の記事が表示されていますが、find()メソッドだと一番最近更新された記事タイトルのみが出力されます。

find_all()

一方find_all()メソッドは、最初の要素のみだけでなく、全ての要素を取り出す時に使います。

先ほどのコードのfind()メソッドをfind_all()メソッドに変え、ブログの記事タイトルをリストで表示させたいと思います。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen(‘https://kubogen.com/’)
bs = BeautifulSoup(html.read(), ‘html.parser’)

articleList = bs.find_all(‘h2’, {‘class’:’entry-title’})
for article in articleList:
  print(article.get_text())

次のようにトップページに表示されている16個の記事タイトルが出力されます。

find()とfind_all()の引数

find()とfind_all()では、次のような引数を指定することができます。

  • find(tag, attributes, recursive, text, keywords)
  • find_all(tag, attributes, recursive, text, limit, keywords)

tag

tagは取得するタグを指定する引数です。次のようにして、全ての見出しタグのリストを返したりもできます。

.find_all([‘h1′,’h2′,’h3′,’h4′,’h5′,’h6’])

attributes

attributesはPythonの辞書型をとって、その中の属性を含むタグに対応させる引数です。

.find_all(‘span’, {‘class’:{‘title’,’category’}})

この場合だと、クラス名がtitleとcategoryの両方のspanタグを返します。

recursive

recursiveはどこまで深く探すかの論理値をとる引数です。

Trueなら引数に合致するタグを求めて、子要素や孫要素というようにレイヤーを下り、Falseならトップレベルのタグのみを探します。

基本的にはデフォルトのTrueでいいと思います。

text

textはタグのテキストコンテンツが合致するものを取り出す引数です。

nameList = bs.find_all(text=’name’)
print(len(nameList))

このように、テキスト(上記の例だとname)が何回タグに囲まれているか数えたりするときに使えます。

limit

limitはページの最初から数えて何個の要素を取り出すかを指定する引数で、find_allメソッドだけで使われます。

limitに1を指定すると、find()と同じです。

ただし、ページの中の探索順序で最初の方の要素から返すので、必ずしも期待した最初のものからになるとは限りません。

keywords

keywordsは特別な属性を持つタグを選ぶ時に指定する引数です。

次のようにすると、id属性がtitleのものを取り出します。

.find_all(id=’title’)

tagとattributesを指定しても同じ結果が得られるので、次のコードは同じ結果になります。

.find_all(id=’title’)
.find_all(”, {‘id’:title})

class属性も指定することができるが注意が必要です。

なぜならclassはPythonの予約語で変数や引数の名前に使えないからです。

そのため、少し違和感があるかもしれませんが、下線を加えて次のように記述します。

.find_all(class_=’title’)

次の2行は同じですが、辞書型で属性を関数に渡す場合はORフィルタになり、キーワード引数の場合はANDフィルタになります。

.find_all(class_=’title’)
.find_all(”. {‘class’:’title’})

まとめ

find()メソッドは最初の要素のみを取り出し、find_all()メソッドは全ての要素を取り出すという違いがあります。

また、指定できる引数は以下の通り

  • find(tag, attributes, recursive, text, keywords)
  • find_all(tag, attributes, recursive, text, limit, keywords)

引数に関して、基本的にはtagとattributesを指定することが多く、必要なければ他の引数は特に指定しなくていいかなと思います。

Leave a Comment