BeautifulSoup(ビューティフルスープ/bs4)とは、PythonでHTMLやXMLを解析(パース)し、タイトル・リンク・特定のタグの文章などを取り出すためのライブラリです。インストールはpip install beautifulsoup4で、パッケージ名の末尾の「4」を落とすとPython 2.7向けの旧版(BeautifulSoup 3.2.2)を探しにいってエラーになります。2026年9月26日時点のPyPI掲載版は4.15.0(2026年6月7日公開)で、Python 3.7以上が必要です。
本記事では、インストール手順、パーサの選び方、find・find_all・selectの使い分け、requestsと組み合わせたスクレイピングの実践、利用上の注意点を、手元で動くコード付きで解説します。スクレイピングそのものの仕組みや、クローリング・APIとの違い、法務上の注意点はスクレイピングとは何かを整理した解説記事で扱っています。
まとめ
BeautifulSoupの要点を整理します。
- BeautifulSoup(bs4)とは、PythonでHTML/XMLを解析しデータを抽出できるライブラリ
- インストールは
pip install beautifulsoup4(「beautifulsoup4」と正確に指定)。requestsと組み合わせて使う - パーサは標準の
html.parserでOK。高速処理ならlxml - 基本は
find/find_all(タグ・属性)とselect/select_one(CSSセレクタ)。クラス検索はclass_ - スクレイピングは利用規約・robots.txtの確認、アクセス間隔、著作権・個人情報への配慮を忘れずに
以下の章では、インストールから順にコード付きで解説します。まずは標準のhtml.parserで、身近なページのタイトルやリンクを取り出すところから試してください。
BeautifulSoupとは
BeautifulSoupは、HTMLの文字列を「プログラムで扱える形」に変換し、タグや属性を指定して目的の要素を取り出せるようにするライブラリです。たとえば「ページ内のすべてのリンク」「特定のクラスを持つ見出し」などを、数行のコードで抽出できます。
HTMLを直接文字列処理するのは大変ですが、BeautifulSoupを使えば、タグの階層構造をたどって直感的にデータを取得できます。通常は、Webページを取得するrequestsライブラリと組み合わせて使います。requestsでHTMLを取ってきて、BeautifulSoupで解析する、という流れが基本です。
BeautifulSoupのインストール
BeautifulSoupは、pipでインストールします。パッケージ名は「beautifulsoup4」です。
pip install beautifulsoup4
注意点として、「beautifulsoup4」と正確に指定してください。「beautifulsoup」とだけ書くと古いBeautifulSoup3が入ってしまうことがあり、これはPython 3系では正しく動作しません。あわせて、Webページを取得するためのrequestsもインストールしておきます。
pip install requests
必要に応じて、高速なパーサであるlxmlも入れておくと便利です(後述)。
pip install lxml
パーサの種類
BeautifulSoupでHTMLを解析するときは、「パーサ(解析器)」を指定します。代表的なものは次の3つです。
- html.parser:Python標準で追加インストール不要。手軽に使え、基本的にはこれで十分です。
- lxml:高速で、多少崩れたHTMLにも対応しやすい。大量に処理する場合に向きます(別途インストールが必要)。
- html5lib:壊れたHTMLにもっとも強いが、動作は遅め(別途インストールが必要)。
迷ったら、まずは標準のhtml.parserを使えば問題ありません。
BeautifulSoupの基本的な使い方
BeautifulSoupの基本は、HTMLを読み込んでBeautifulSoupオブジェクトを作り、そこからメソッドで要素を取り出すことです。次のサンプルHTMLで見ていきます。
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>サンプルページ</title></head>
<body>
<p class="story">むかしむかし、3姉妹がいました。
<a href="http://example.com/1" class="sister" id="link1">エルシー</a>、
<a href="http://example.com/2" class="sister" id="link2">レイシー</a>。
</p>
</body></html>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
タグや文字列を取得する
タグ名を指定すると、最初に見つかった要素を取得できます。.stringは、タグ内の内容が単一の文字列として定まる場合に取得できます。テキストと子タグが混在するとNoneになるため、子孫要素を含むテキスト全体には.get_text()を使います。
# titleタグの中の文字列を取得
print(soup.title.string) # サンプルページ
# 最初のaタグを取得(soup.find('a') と同じ)
print(soup.a)
# リンク先(href属性)を取得
print(soup.a.get('href')) # http://example.com/1
find と find_all
もっともよく使うのがfindとfind_allです。findは条件に合う最初の1つ、find_allはすべてを取得します。
# 最初のaタグ
first_link = soup.find('a')
# すべてのaタグを取得して、リンク先を順に表示
for link in soup.find_all('a'):
print(link.get('href'))
クラスや属性で絞り込むこともできます。クラスを指定するときは、Pythonの予約語classと区別するためclass_(末尾にアンダースコア)を使う点に注意します。
# class="story" のpタグをすべて取得
soup.find_all('p', class_='story')
# id="link1" の要素を取得
soup.find(id='link1')
select(CSSセレクタ)
CSSセレクタで指定したい場合はselect(すべて取得)とselect_one(最初の1つ)を使います。普段からCSSに慣れている人には直感的です。
# CSSセレクタで取得
soup.select_one('title') # 最初のtitle
soup.select('p.story a') # p.story の中のaタグをすべて
soup.select('#link1') # id="link1"
このように、find系(タグ・属性で指定)とselect系(CSSセレクタで指定)の2通りがあり、好みや状況に応じて使い分けられます。
requestsと組み合わせたスクレイピングの実践
実際のWebページを対象にする場合は、requestsでHTMLを取得し、それをBeautifulSoupで解析します。基本の流れは次の通りです。
import requests
from bs4 import BeautifulSoup
url = 'https://example.com'
res = requests.get(url, timeout=(5, 30))
res.raise_for_status() # HTTPエラーステータスなら例外にする
soup = BeautifulSoup(res.content, 'html.parser')
# ページ内のすべてのリンクのテキストとURLを取得
for a in soup.find_all('a'):
text = a.get_text(strip=True)
href = a.get('href')
print(text, href)
取得したデータは、CSVファイルに保存できます。集計や加工をしたい場合は、データ分析ライブラリのpandasと組み合わせると、表形式での整形や分析がしやすくなります。
import csv
rows = []
for a in soup.find_all('a'):
rows.append([a.get_text(strip=True), a.get('href')])
with open('links.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['text', 'url'])
writer.writerows(rows)
記事本文のように特定の場所だけ取りたい場合は、その部分を囲んでいるタグやクラスを指定します。後のコードにあるarticle-contentは説明用のクラス名なので、対象ページに実在するクラス名へ変更してください。ブラウザの「開発者ツール」でHTML構造を確認し、対象のタグ・クラスを調べるのが実践のコツです。
なお、JavaScriptで後から内容が描画されるページは、requestsで取得したHTMLには目的のデータが含まれないことがあります。その場合は、ブラウザを自動操作してページを描画させるSeleniumで目的の要素が描画されるまで待機してからHTMLを取得し、それをBeautifulSoupで解析する組み合わせが有効です。
# 例:本文がある領域を指定して、段落テキストをまとめて取得
body = soup.find('div', class_='article-content')
if body:
text = "\n".join(p.get_text() for p in body.find_all('p'))
print(text)
BeautifulSoupを使う際の注意点
スクレイピングは便利ですが、ルールとマナーを守って行う必要があります。次の点に注意しましょう。
- 利用規約・robots.txtを確認する:対象サイトがスクレイピングを禁止していないかを必ず確認します。公式のAPIが用意されている場合は、そちらを優先します。
- サーバーに負荷をかけない:短時間に大量のリクエストを送らないよう、アクセスの間隔をあけます(例:
time.sleep(1)で1秒待つ)。 - 著作権・個人情報に配慮する:取得したデータの利用目的が、著作権や個人情報保護の観点で問題ないかを確認します。
- HTML構造の変化に備える:Webページの構造は変わることがあります。要素が取得できなかった場合(
Noneが返る場合)に備えて、エラー処理を入れておくと安定します。
import time
urls = ['https://example.com/page1', 'https://example.com/page2']
for url in urls:
res = requests.get(url, timeout=(5, 30))
res.raise_for_status()
soup = BeautifulSoup(res.content, 'html.parser')
# ここで解析処理
time.sleep(1) # 1秒あけて次のリクエストへ
よくある質問(FAQ)
BeautifulSoupのインストールでエラーになるのはなぜ?
原因の一つはパッケージ名の指定ミスです。pip install beautifulsoupと「4」を付けずに実行すると、PyPI上の旧版BeautifulSoup 3系(最終版3.2.2、Python 2.7向け)が選ばれ、Python 3ではsetup.py内のprint "..."がSyntaxError: Missing parentheses in call to 'print'になってインストールに失敗します。pip install beautifulsoup4と正確に指定してください。
「No module named ‘bs4’」と出るときの対処は?
インストール名はbeautifulsoup4、コード上のimport名はbs4で、両者は別の文字列です。インストール済みなのにこのエラーが出る場合は、pipが入れた先と実行中のPythonが別環境になっていることが典型です。スクリプトを動かすのと同じインタプリタでpython -m pip install beautifulsoup4を実行すると、入れ先がそろいます。仮想環境を使っているなら、有効化してから入れ直します。
findとfind_allの違いは?
findは条件に合う最初の1つの要素を返し、見つからなければNoneを返します。find_allは条件に合うすべての要素をリストで返し、見つからなければ空のリストです。findの戻り値にそのまま.get_text()をつなぐと、要素が無いページでAttributeErrorになるため、ifでNoneを確かめてから使います。
クラスで要素を探すときの書き方は?
classはPythonの予約語のため、末尾にアンダースコアを付けたclass_を使います。例:soup.find_all('p', class_='story')。CSSセレクタに慣れているなら、soup.select('p.story')と書いても同じ要素が取れます。
パーサは何を選べばいいですか?
追加インストールが不要な標準のhtml.parserで十分です。大量のページを処理して速度が欲しい場合はlxml、ブラウザと同じ解釈で崩れたHTMLを読みたい場合はhtml5libを検討します。どちらもpip install lxml/pip install html5libで別途入れ、BeautifulSoup(html, 'lxml')のように第2引数で指定します。
BeautifulSoupとSeleniumの違いは?
BeautifulSoupは受け取ったHTML文字列を解析するだけで、ページの取得もJavaScriptの実行もしません。Seleniumはブラウザを自動操作するツールで、JavaScriptで描画された後のページを扱えます。静的なページならrequests+BeautifulSoupで足り、描画後の内容が必要なときだけSeleniumで取得したHTMLをBeautifulSoupに渡す、という分担が基本です。
スクレイピングは自由に行ってよいですか?
対象サイトの利用規約とrobots.txtを確認してください。ただし、robots.txtはクローラー向けのアクセス規則であり、取得やデータ利用を許諾するものではありません。公式のAPIがあるならそちらを優先します。アクセス間隔をあけてサーバーに負荷をかけないこと、取得したデータの利用が著作権や個人情報保護の観点で問題ないかを確かめることも重要です。