BeautifulSoup4でclass名を指定して要素を得る

117, 2020-11-23

目次

クラス名を指定して要素を得る

BeautifulSoup4(ビューティフル・スープ・フォー)」はHTML/XMLをパースするPythonの外部ライブラリです。
最近のPythonを使ったスクレイピングではひんぱんに利用されるライブラリの1つです。

HTMLの要素(タグ)の属性にclassとそのクラス名を指定できますが、BeautifulSoup4でこの要素のクラス名を指定して、要素を検索し取得する方法を解説します。
結論から言うとよく使われるclass名の指定方法は↓のうちのどれかです。

soup.find('p', class_='myclass')
soup.find_all('p', class_='myclass')
soup.select('p.myclass')

↑の方法の他にもclass名の指定方法はありますが、それは以降の記事で解説します。
今回は具体的には↓を見ていきます。

  • find()でクラス名を指定する

  • find_all()でクラス名を指定する

  • select()でクラス名を指定する

find()でクラス名を指定する

BeautifulSoupクラスのオブジェクトはfind(ファインド)メソッドを持っています。
これは単一の要素を検索したい時に使用するメソッドです。
find()bs4.BeautifulSoupbs4.element.Tagのオブジェクトから使用できます。

find()の構造

find()メソッドは↓のような構造になっています。

find(
    self,
    name=None,  # タグ名を表す文字列
    attrs={},  # 属性値を表す辞書
    recursive=True,  # 再帰するならTrue
    text=None,  # タグのテキストを表す文字列
    **kwargs  # キーワード引数
)

↑のうちclass名の検索に使用するのはattrs引数と**kwargs引数です。

find()の返り値

find()の返り値はbs4.element.TagNoneです。
要素が見つかった場合はbs4.element.Tagを返し、見つからなかった場合はNoneを返します。
Tagfind()find_all(), select()メソッドを持っているので再帰的に検索が可能です。

attrs引数にクラス名を指定する

find()メソッドのattrs引数にクラス名を指定して検索すると、そのクラス名の要素を得ることが出来ます。

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

例えば↓のように使います。

from bs4 import BeautifulSoup

html = '''
<p>1</p>
<p class="bird">2</p>
<p class="bird">3</p>
'''
soup = BeautifulSoup(html, 'html.parser')

# class名がbirdのpタグを検索
el = soup.find('p', attrs={ 'class': 'bird' })

# タグのテキストを表示
print(el.text)

↑の出力結果↓。

2

find()メソッドは最初に見つけた要素を返します。
↑の場合、クラス名にbirdを持っているタグは2つありますが、find()では最初のタグを見つけて返しています。

attrs引数にクラス名のリストを指定する

attrs引数の辞書の値にはリストを指定することも出来ます。
リストの要素にクラス名を指定することで、クラス名をOR検索することが可能です。

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

たとえば↓のように使います。

from bs4 import BeautifulSoup

html = '''
<p>1</p>
<p class="bird">2</p>
<p class="dog">3</p>
'''
soup = BeautifulSoup(html, 'html.parser')

# class名がbirdまたはcatのpタグを検索
el = soup.find('p', attrs={ 'class': ['bird', 'cat'] })

# タグのテキストを表示
print(el.text)

↑の出力結果↓。

2

↑の場合、find()class名にbirdまたはcatをリストで指定しています。
そのためこのfind()のクラス名の検索はOR検索になります。
つまりクラス名にbirdまたはcatを持つ要素を取得するようになります。
↑の場合、クラス名にbirdを持っているpタグがヒットしています。

attrs引数に正規表現を指定する

attrs引数の辞書の値には正規表現オブジェクトを指定することも出来ます。
正規表現でクラス名を検索したい時は↓のようにします。

import re
soup.find('p', attrs={ 'class': re.compile(r'blue-.*') })

↓のように使います。

from bs4 import BeautifulSoup
import re

html = '''
<p class="red-ocean">1</p>
<p class="blue-ocean">2</p>
<p class="green-ocean">3</p>
'''
soup = BeautifulSoup(html, 'html.parser')

# 正規表現「blue-.*」にヒットする要素を取得
el = soup.find('p', attrs={ 'class': re.compile(r'blue-.*') })

# タグのテキストを表示
print(el.text)

↑の出力結果↓。

2

attrs引数にはリストを指定できますが、リスト内の要素にも正規表現オブジェクトは指定できます。

soup.find('p', attrs={ 'class': [re.compile(r'blue-.*'), re.compile(r'red-.*')] })

キーワード引数でclass名を指定

find()のキーワード引数class_にクラス名を指定することで検索することも出来ます。

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

↓のように使います。

from bs4 import BeautifulSoup

html = '''
<p class="red">1</p>
<p class="blue">2</p>
<p class="green">3</p>
'''
soup = BeautifulSoup(html, 'html.parser')

# クラス名blueにヒットする要素を取得
el = soup.find('p', class_='blue')

# タグのテキストを表示
print(el.text)

↑の出力結果↓。

2

キーワード引数class_の値にはリストや正規表現オブジェクトを指定することも出来ます。
リストの場合はOR検索になります。

# OR検索
soup.find('p', class_=['blue', 'red'])
# 正規表現による検索
import re
soup.find('p', class_=re.compile(r'blue-.*'))

タグ名を無視してクラス名のみを指定する

find()の引数nameTrueを指定すると、タグ名を無視した検索を行えます。

from bs4 import BeautifulSoup

html = '''
<p class="red">1</p>
<p class="blue">2</p>
<p class="green">3</p>
'''
soup = BeautifulSoup(html, 'html.parser')

# クラス名blueにヒットする要素を取得
el = soup.find(True, class_='blue')
print(el.text)

↑の出力結果↓。

2

find_all()でクラス名を指定する

find_all(ファインド・オール)メソッドは検索条件にヒットした複数の要素をまとめて取得するメソッドです。
find_all()find()に似たインターフェースを持っています。
find_all()bs4.BeautifulSoupbs4.element.Tagのオブジェクトから使用できます。

find_all()の構造

find_all()の構造は↓になります。

find_all(
    self,
    name=None,  # タグ名を表す文字列
    attrs={},  # 属性を表す辞書
    recursive=True,  # 再帰をするならTrue
    text=None,  # 要素内のテキストを表す文字列
    limit=None,  # 再帰上限数
    **kwargs  # キーワード引数
)

find()と同様に、クラス名の指定に使うのはattrs引数と**kwargs引数です。

find_all()によるクラス名の検索方法

クラス名を指定するfind_all()の使い方は、find()と同じです。
違いは、find_all()の検索結果がbs4.element.ResultSetで返ってくる点です。

attrs引数によるクラス名の指定↓。

soup.find_all('p', attrs={ 'class': 'blue' })

attrs引数の値にリストを指定する↓。
この場合はOR検索です。

soup.find_all('p', attrs={ 'class': ['blue', 'red'] })

attrs引数の値に正規表現オブジェクトを指定する↓。

import re
soup.find_all('p', attrs={ 'class': re.compile('blue-.*') })

attrs引数のリストに正規表現オブジェクトを指定する↓。

import re
soup.find_all('p', attrs={ 'class': [re.compile('blue-.*'), re.compile('red-.*')] })

タグ名を無視してクラス名のみで指定する↓。

soup.find_all(True, class_='blue')

find_all()の返り値(ResultSet)

find_all()の結果はbs4.element.ResultSetで返ってきます。

els = soup.find_all('p', class_='blue')
print(type(els))
# <class 'bs4.element.ResultSet'>

このResultSetlistを継承したクラスです。
そのため↓のようにfor文で回したり、インデックス参照したりできます。

els = soup.find_all('p', class_='blue')

for el in els:
    print(el.text)

print(els[0].text)

select()でクラス名を指定する

select()はセレクターを指定して要素を検索できるメソッドです。
find()find_all()より視覚的にわかりやすく検索することが出来ます。

select()の構造

select()の構造は↓のようになっています。

select(self, selector, _candidate_generator=None)

selectorにはセレクターを指定します。
これはCSSなどでお馴染みの記法です。
select()の返り値はfind_all()と同じResultSetです。

クラス名を指定して検索する

たとえばクラス名blueがくっついているpタグを検索したい場合は↓のようにします。

el = soup.select('p.blue')

↓のように使います。

from bs4 import BeautifulSoup

html = '''
<p class="red">1</p>
<p class="blue">2</p>
<p class="green">3</p>
'''
soup = BeautifulSoup(html, 'html.parser')

# クラス名blueにヒットする要素pを取得
els = soup.select('p.blue')
print(els[0].text)

↑の出力結果↓。

2

また、クラス名単体で検索したい場合は↓のように指定します。

el = soup.select('.blue')

おわりに

BeautifulSoup4では柔軟にクラス名を指定して要素を検索することが出来ます。
もしよかったら、ぜひこの記事をブックマークして使い方を覚えるまで参照してみてください。

(^ _ ^)

クラス名を制する者はHTMLを制す



この記事のアンケートを送信する