本記事では、PythonのBeautifulSoup応用編として、find_allメソッドで複数条件を指定してスクレイピングする方法について解説をしていきます
PythonのBeautifulSoupの使い方については、以下の記事で理解を深めていきましょう
BeautifulSoupを応用して活用してみたい方は、そちらも参考にしてください
多すぎるキャンペーンを監視してキャンペーンが開始したらメールで通知するプログラム
PythonでスクレイピングするWebサイト(Web Scraper)を作ったよ
筆者について
2021年から本格的にPython学習を始め、今ではPythonによる収益化に成功しフリーランスエンジニアに
大学院時代には、R言語とPythonを使って統計処理を行っていたため、Pythonを使ったデータサイエンスの知識が豊富
医療データを機械学習を用いて解析したり、学会発表も行なっている
Contents
BeautifulSoupのfind_allメソッド
find_allメソッドはWebスクレイピングで最もよく使われる方法です。
find_allメソッドを使うことで、ページ内にある特定のタグや属性を持つ要素をすべて見つけてリストとして返すために使われます。
find_allメソッドでは、正規表現やタグ属性などの引数を使用すると、条件を指定して検索を絞り込むことも出来ます
find_allメソッドの構造
find_allメソッドの構造は次のようになっています
find_all(
self,
name=None, # タグ名を表す文字列
attrs={}, # 属性を表す辞書
recursive=True, # 再帰をするならTrue
text=None, # 要素内のテキストを表す文字列
limit=None, # 再帰上限数
**kwargs # キーワード引数
)
name(第1引数)
目的:特定のタグ名に一致する要素を検索します。
使用例:soup.find_all(name=”a”)は、すべてのタグ(アンカータグ)を検索します。
単一のタグを取得するには、name引数にそのタグ名を文字列で指定します。例えば、divタグを取得したい場合は以下のようにします。
soup.find_all('div')
もし複数のタグを同時に取得したい場合は、name引数にリストやタプルを使用します。
これにより、リスト内のすべてのタグ名に一致するタグが取得されます。例えば、pとspanタグを取得するには以下のようにします。
soup.find_all(['p', 'span'])
さらに、find_all()にTrueを指定すると、すべてのタグが取得されます。
これは、特定のクラス名やID名でタグを絞り込む際に便利です。
soup.find_all(True)
これらの方法を使えば、Beautiful SoupでHTML文書内の特定のタグを効率的に検索できます。
attrs(第2引数)
目的:特定の属性を持つ要素を検索します。
使用例:soup.find_all(attrs={“class”: “myClass”})は、class=”myClass”属性を持つすべての要素を検索します。
BeautifulSoupのfind_all()関数では、特定の属性を持つタグを見つけるために属性値の辞書を利用できます。
例えば、class属性がdogであるpタグを見つけたい場合、以下のように記述します。
soup.find_all('p', attrs={'class': 'dog'})
また、複数の属性を指定することも可能です。
例として、classがdogで、かつidがbirdである要素を検索するには、以下のようにします。
soup.find_all('p', attrs={'class': 'dog', 'id': 'bird'})
ここで、辞書に複数の属性を指定した場合、検索条件は「AND」論理で組み合わされます。
さらに、辞書の値にリストやタプルを指定することで、複数の値を持つ属性を「OR」論理で検索できます。
たとえば、class属性がaまたはbであるpタグを検索するには以下のようにします。
soup.find_all('p', attrs={'class': ['a', 'b']})
正規表現を使用して属性を検索することも可能です。
この場合、class属性が「Dr」で始まる任意の値に一致するpタグを見つけるには、次のように記述します。
import re
soup.find_all('p', attrs={'class': re.compile(r'Dr.*')})
これらの方法を使用することで、Beautiful Soupを使ってHTML文書から特定の条件を満たすタグを柔軟に検索できます。
recursive(第3引数)
目的:検索を文書の全階層にわたって行うかどうかを制御します。
使用例:soup.find_all(“div”, recursive=False)は、直下の階層にあるタグのみを検索します。
BeautifulSoupのfind_all()関数では、デフォルトで再帰的に検索を行います。
これは、指定したタグが見つかると、そのタグの子要素に対しても同じ検索条件を適用し続けることを意味します。つまり、指定したタグの全ての子孫要素が検索範囲に含まれます。
しかし、この再帰的な検索を行いたくない場合には、find_all()関数のrecursive引数にFalseを設定することで、非再帰的な検索を実行できます。
非再帰的な検索では、指定されたタグの直接の子要素のみが検索され、その子孫要素は検索対象に含まれません。
例えば、divタグ内の直接の子要素だけを検索する場合には、以下のように記述します。
soup.find_all('div', recursive=False)
この設定により、divタグの直接の子要素のみが検索され、それより下位の子孫要素は無視されます。
この機能は、HTMLドキュメントの特定の階層のみに焦点を当てたい場合に特に便利です。
text(第4引数)
目的:特定のテキスト内容を持つ要素を検索します。
使用例:soup.find_all(text=”Hello World”)は、”Hello World”というテキストを含むすべての要素を検索します。
BeautifulSoupのfind_all()関数では、text引数を用いてタグのテキスト内容に基づいて検索を行うことができます。
これは、タグが含む特定のテキストを基準にして、そのテキストを含むタグを見つけ出すために使用されます。
例えば、<p>Happy!</p>のようなタグがある場合、そのテキスト内容「Happy!」を使ってこのタグを見つけたい場合、以下のように記述します。
soup.find_all('p', text='Happy!')
この方法では、text引数に文字列を指定することで、その文字列を含むテキストを持つタグを検索できます。
もし複数の異なるテキストを基準に検索したい場合は、text引数にリストやタプルを使用します。
これにより、「OR」論理で複数のテキストに一致するタグを検索できます。例えば、「Bob」または「Alice」というテキストを含むpタグを検索するには、以下のようにします。
soup.find_all('p', text=['Bob', 'Alice'])
さらに、text引数にコンパイルされた正規表現オブジェクトを指定することで、正規表現を用いた柔軟なテキスト検索が可能です。
たとえば、テキストが「The」で始まるpタグを見つけたい場合は、以下のように記述します。
import re
soup.find_all('p', text=re.compile(r'The.*$'))
これらの方法を使用することで、Beautiful Soupを使ってHTML文書内の特定のテキストを含むタグを効率的に検索できます。
limit(第5引数)
目的:検索結果の数を制限します。
使用例:soup.find_all(“a”, limit=2)は、最初の2つのタグのみを返します。
BeautifulSoupのfind_all()関数では、limit引数を使用して検索の再帰上限数を指定できます。
このlimit引数は、検索がどれだけの深さまでHTMLツリーを探索するかを制御します。
デフォルトではNoneに設定されており、これは検索が制限なく全ての深さを探索することを意味します。
例として、HTMLツリーの深さが2である場合、以下のような構造を考えます。
<div>
<p>I'm here!</p>
</div>
この場合、<div>タグは深さ1、その中の<p>タグは深さ2に位置します。
もし<div>タグの検索を深さ1までに限定したい場合、つまりその中の<p>タグまで辿らないようにしたい場合は、limit引数に1を設定します。
soup.find_all('div', limit=1)
この設定により、find_all()関数は指定されたタグを検索する際に、最初の階層(この例では<div>タグ)までしか探索しません。
この機能は、特定の深さの要素にのみ興味がある場合や、検索範囲を制限したい場合に特に便利です。
kwargs(第6引数)
目的:タグの属性を直接指定するためのキーワード引数です。
使用例:soup.find_all(id=”link1″)は、id=”link1″属性を持つすべての要素を検索します。
BeautifulSoupのfind_all()関数では、class_やidのようなオプションの引数を使用することができます。
これらは、attrs引数を使う代わりに、特定の属性を直接指定するためのショートカットとして機能します。
たとえば、class属性がbirdであるpタグを検索したい場合、以下のようにclass_引数を使用することができます。
soup.find_all('p', class_='bird')
ここで、class_引数が使われている点に注意してください。
Pythonではclassが予約語であるため、BeautifulSoupではclass_(末尾にアンダースコアが付いています)を使用します。
同様に、id属性を持つタグを検索する場合は、id引数を使用します。例えば、idがpigであるpタグを検索するには、以下のように記述します。
soup.find_all('p', id='pig')
これらのショートカットは、特定のHTML属性を持つタグを簡単にかつ迅速に検索するために役立ちます。
attrs引数を使用するよりも簡潔で直感的な方法で、HTML文書内の特定の要素を探すことができます。
BeautifulSoupやRequests,Seleniumなどのスクレイピングスキル全て効率よく学びたい方は、Pythonによるビジネスに役立つWebスクレイピングがおすすめです
HTMLの基本から、実際のデータ取得まで一貫して学ぶことが出来ます
Python BeautifulSoupのfind_allメソッドで複数条件指定する
では、実際にここからBeautifulSoupのfind_allメソッドで複数条件を指定して、検索・抽出する方法について解説をしていきます
特定のclass名を持つdivタグを見つける
例えば、特定のclass名を持つdivタグを見つけるには、以下のように実装します
from bs4 import BeautifulSoup
import requests
url = "https://aistock.tech/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
results = soup.find_all("div", class_="特定のクラス名")
for result in results:
print(result.prettify())
特定のIDを持つspan名を見つける
また、特定のIDを持つspan名を見つけるには、以下のようにします
from bs4 import BeautifulSoup
import requests
url = "https://aistock.tech/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
results = soup.find_all("span", id="特定のID")
for result in results:
print(result.prettify())
さらに複数の属性を組み合わせて検索することも可能です。
特定のクラスを持ち、かつ特定の属性(例えばdata-attribute=”value”)を持つタグを検索する
例えば、特定のクラスを持ち、かつ特定の属性(例えばdata-attribute=”value”)を持つタグを検索するには、以下のようにします
from bs4 import BeautifulSoup
import requests
url = "https://aistock.tech/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
results = soup.find_all("a", class_="特定のクラス名", attrs={"data-attribute": "value"})
for result in results:
print(result.prettify())
find_allメソッドで複数条件指定して情報を取得する
例えば、teratailに上がっていた質問に以下のようなものがあります
teratail-BeautifulSoupで複数の属性でfind_allする方法を教えてください
<span style="font-size:16px">hoge</span>
<span style="font-size:12px">title1</span>
<p id="1">text01</p>
<p id="2">text02</p>
<p id="3">text03</p>
<span>huga</span>
<span style="font-size:12px">title2</span>
<p id="1">text01</p>
<p id="2">text02</p>
<p id="3">text03</p>
<span>huga</span>
実際に実装するには、次の手順になります
- HTMLをパースする:BeautifulSoupを使ってHTMLコンテンツを解析します。
- 特定のspanタグを検索する:style属性を持つspanタグをfind_allメソッドで検索します。
- 特定のpタグを検索する:特定のid属性を持つpタグをfind_allメソッドで検索します。
- テキストの抽出:検索したタグからテキストを抽出します。
HTMLのパースについては、こちらの記事で解説しているので、パースが何かよくわからない方は、参考にしてください。
from bs4 import BeautifulSoup
# HTMLコンテンツ
html_content = """
<span style="font-size:16px">hoge</span>
<span style="font-size:12px">title1</span>
<p id="1">text01</p>
<p id="2">text02</p>
<p id="3">text03</p>
<span>huga</span>
<span style="font-size:12px">title2</span>
<p id="1">text01</p>
<p id="2">text02</p>
<p id="3">text03</p>
<span>huga</span>
"""
# BeautifulSoupオブジェクトの作成
soup = BeautifulSoup(html_content, 'html.parser')
# style属性を持つ<span>タグをすべて検索
span_tags_with_style = soup.find_all('span', style=True)
# 特定のidを持つ<p>タグをすべて検索
p_tags_with_specific_id = soup.find_all('p', id=['1', '2', '3'])
# titleとtextのリストを作成
titles_and_texts = []
for tag in span_tags_with_style + p_tags_with_specific_id:
titles_and_texts.append(tag.get_text())
# 結果の表示
for item in titles_and_texts:
print(item)
これでBeautifulSoupのfind_all関数を使って、複数条件を指定して、情報を抽出することが出来ます
取得したい情報に応じて、コードを変えてもらえれば、いくらでも活用することが出来ます
また、BeautifulSoupやRequests,Seleniumを使ったスクレイピングについて効率よく学びたい方は、Pythonによるビジネスに役立つWebスクレイピングがおすすめです
HTMLの基本から、実際のデータ取得まで一貫して学ぶことが出来ます
まとめ
- find_all関数で複数条件指定してのスクレイピングが可能
- 引数を設定することで正規表現を用いてスクレイピングすることができる
- 論理演算子「AND」「OR」を使ってスクレイピング可能