Pythonを使用したWebスクレイピングにおいて、HTML要素から特定の情報を抽出する作業は頻繁に発生します。
特に、タグの中に埋め込まれたリンク(href)や画像ソース(src)、独自のデータ属性(data-*)を取得する際に非常に便利なのが、BeautifulSoupライブラリのattrsプロパティです。
このプロパティを活用することで、HTML要素が持つすべての属性をPythonの辞書形式(dict)として効率的に扱うことが可能になります。
本記事では、BeautifulSoupのattrsを用いて、属性情報をスマートに取得・抽出する手法について詳しく解説します。
BeautifulSoupにおけるattrsプロパティとは
BeautifulSoupで解析したHTMLの各要素(Tagオブジェクト)は、attrsというプロパティを保持しています。
これは、そのタグが持っているすべての属性値を格納したPythonの辞書型オブジェクトです。
通常、特定の属性(例えばIDなど)を取得する場合はtag['id']のように記述しますが、attrsを使用することで、その要素に含まれるすべての属性を一度に俯瞰したり、動的に処理したりすることができます。
attrsプロパティの基本的な構造
まずは、簡単なHTMLコードを例に、attrsがどのようなデータを返すのかを確認してみましょう。
from bs4 import BeautifulSoup
# サンプルHTML
html_content = '<a href="https://example.com" id="main-link" class="nav-item" data-category="general">Click Here</a>'
soup = BeautifulSoup(html_content, 'html.parser')
# aタグを選択
a_tag = soup.find('a')
# attrsの内容を表示
print(a_tag.attrs)
print(type(a_tag.attrs))
{'href': 'https://example.com', 'id': 'main-link', 'class': ['nav-item'], 'data-category': 'general'}
<class 'dict'>
実行結果を見るとわかる通り、attrsはキーに属性名、値にその内容を持つ標準的なPython辞書を返します。
特筆すべき点は、class属性が文字列ではなく「リスト形式」で格納されていることです。
これは、HTMLにおいてクラス名がスペース区切りで複数指定される可能性があるため、BeautifulSoupが自動的にリストとして解釈してくれる便利な仕様です。
attrsを使用して特定の属性を取得する方法
辞書形式で取得できるため、属性へのアクセス方法はPythonの辞書操作と全く同じです。
しかし、スクレイピングの実務においては「属性が存在しない場合」の考慮が必要です。
直接アクセスする方法
最もシンプルな方法は、キーを指定してアクセスすることです。
# 直接アクセス
href_value = a_tag.attrs['href']
print(f"URL: {href_value}")
URL: https://example.com
ただし、この方法には注意点があります。
指定した属性がHTML要素内に存在しない場合、KeyErrorが発生してプログラムが停止してしまいます。
不特定多数のページをクロールする場合、特定のタグに必ずしも目的の属性があるとは限らないため、より安全な方法が推奨されます。
getメソッドによる安全な取得
辞書型のget()メソッドを使用することで、属性が存在しない場合でもエラーを出さずに処理を継続できます。
# 存在しない属性にアクセス
target_value = a_tag.attrs.get('target')
print(f"Target: {target_value}")
# デフォルト値を指定して取得
target_value_with_default = a_tag.attrs.get('target', '_self')
print(f"Target (Default): {target_value_with_default}")
Target: None
Target (Default): _self
このように、get()を使用すると属性がない場合にNoneを返し、必要に応じてデフォルト値を設定することも可能です。
安定したスクレイピングコードを書くためには、直接アクセスよりもgetメソッドの利用を優先しましょう。
複数の属性を一括でループ処理する
attrsが辞書型である最大のメリットは、items()メソッドを使用してすべての属性をループで処理できる点にあります。
すべての属性名と値を取得する
以下のコードは、要素が持つすべての属性を順番に取り出す例です。
# すべての属性をループで表示
for attr_name, attr_value in a_tag.attrs.items():
print(f"属性名: {attr_name} | 値: {attr_value}")
属性名: href | 値: https://example.com
属性名: id | 値: main-link
属性名: class | 値: ['nav-item']
属性名: data-category | 値: general
特定のデータ属性(data-で始まる属性)のみを抽出したい場合や、動的に変化する属性名をトラッキングしたい場合にこの手法は非常に強力です。
クラス属性(多値属性)の特殊な挙動
前述の通り、BeautifulSoupではclass属性などは多値属性(Multi-valued attributes)として扱われ、リストとして取得されます。
| 属性名 | HTML例 | attrsでの形式 |
|---|---|---|
| class | class=”btn primary” | [‘btn’, ‘primary’] |
| rel | rel=”nofollow noopener” | [‘nofollow’, ‘noopener’] |
| id | id=”header” | ‘header’ (単一文字列) |
もし、クラス名をリストではなく元のHTMLと同じ「スペース区切りの文字列」として取得したい場合は、Pythonのjoin()メソッドを使用します。
# リストを文字列に変換
class_list = a_tag.attrs.get('class', [])
class_string = " ".join(class_list)
print(f"Class String: {class_string}")
Class String: nav-item
find/find_allの中でattrsを活用する
attrsは取得時だけでなく、検索条件の指定としても利用できます。
find()やfind_all()メソッドの引数にattrsを渡すことで、複雑な条件での絞り込みが可能になります。
特定の属性を持つ要素を検索する
例えば、data-status="active" という属性を持つ要素を探したい場合、以下のように記述します。
html_list = """
<ul>
<li data-status="active" data-id="101">User A</li>
<li data-status="inactive" data-id="102">User B</li>
<li data-status="active" data-id="103">User C</li>
</ul>
"""
soup_list = BeautifulSoup(html_list, 'html.parser')
# attrs引数を使って検索
active_users = soup_list.find_all(attrs={"data-status": "active"})
for user in active_users:
print(f"ID: {user.attrs['data-id']} - Text: {user.text}")
ID: 101 - Text: User A
ID: 103 - Text: User C
classやidは個別の引数としても用意されていますが、ハイフンを含む独自の属性名(data-など)を検索条件にする場合は、このattrs引数に辞書を渡す方法が最も確実です。
実践例:記事リストからリンクとメタ情報を抽出する
Webサイトのニュース一覧などから、記事タイトル・URL・カテゴリを一度に抽出する実戦的なコードを紹介します。
html_news = """
<div class="container">
<article class="post" data-category="tech" data-date="2026-05-01">
<a href="/tech/python-tips" class="title-link">Pythonの便利な機能</a>
</article>
<article class="post" data-category="news" data-date="2026-05-02">
<a href="/news/update" class="title-link">最新アップデート情報</a>
</article>
</div>
"""
soup_news = BeautifulSoup(html_news, 'html.parser')
# すべてのarticleタグを取得
articles = soup_news.find_all('article')
news_data = []
for art in articles:
# aタグの取得
link_tag = art.find('a')
# attrsを駆使して情報を整理
info = {
'title': link_tag.get_text(),
'url': link_tag.attrs.get('href'),
'category': art.attrs.get('data-category'),
'date': art.attrs.get('data-date')
}
news_data.append(info)
# 結果の表示
for data in news_data:
print(data)
{'title': 'Pythonの便利な機能', 'url': '/tech/python-tips', 'category': 'tech', 'date': '2026-05-01'}
{'title': '最新アップデート情報', 'url': '/news/update', 'category': 'news', 'date': '2026-05-02'}
この手法の利点は、HTMLの構造(タグ名)に依存しすぎず、属性に埋め込まれたメタデータを構造化データとして綺麗に抽出できる点にあります。
注意点:attrsが動作しないケース
たまに「attrsを呼び出すとエラーになる」というトラブルに遭遇することがあります。
その多くは、find()の結果がNoneになっている場合です。
# 存在しないタグを探すとNoneが返る
tag = soup.find('non-existent-tag')
# Noneに対してattrsを呼ぶとエラー
# print(tag.attrs) # AttributeError: 'NoneType' object has no attribute 'attrs'
if tag:
print(tag.attrs)
要素を取得した後は、必ずその要素が存在するか(Noneではないか)をチェックしてからattrsにアクセスするのが、プロのコーディングにおける鉄則です。
まとめ
BeautifulSoupのattrsプロパティは、HTML要素の属性情報をPythonの辞書として操作できる非常に強力なツールです。
本記事の重要ポイント:
attrsはタグ内の全属性を辞書形式で保持している。- 属性値の取得には、エラー回避のために
get()メソッドを使用するのが望ましい。 classなどの属性は自動的にリスト形式に変換される。find/find_allの引数としてattrsを使うことで、柔軟な検索が可能になる。
Webサイトの構造が複雑化している現代のスクレイピングにおいて、IDやクラス名だけでなく、カスタムデータ属性に重要な情報が隠されているケースが増えています。
今回解説したattrsの活用術をマスターして、より高度で堅牢なデータ収集を実現しましょう。
