Pythonを用いたWebスクレイピングにおいて、特定の要素がどのようなHTMLタグで構成されているかを知ることは、データ抽出の精度を高めるために極めて重要です。
BeautifulSoupライブラリを利用すれば、抽出した要素に対して.name属性を参照するだけで、そのタグ名を文字列として簡単に取得できます。
この記事では、BeautifulSoupでタグ名を取得する基本的な方法から、条件分岐を用いたフィルタリング、さらにはタグ名の書き換えといった応用テクニックまでを詳しく解説します。
最新のPython環境でも変わらず利用できる標準的な手法をマスターし、スクレイピングの実践に役立ててください。
Python BeautifulSoupでタグ名を取得する基本
HTMLドキュメントを解析して特定の情報を抜き出す際、プログラム側で「今扱っている要素が何であるか」を識別する必要があります。
BeautifulSoupでは、解析された各要素(Tagオブジェクト)が.nameというプロパティを持っており、これにアクセスすることでHTMLタグの名前(p, div, aなど)を返してくれます。
BeautifulSoupの準備とインストール
まずは、BeautifulSoupを使用するための環境を整えましょう。
一般的にはbeautifulsoup4パッケージをインストールして使用します。
また、HTMLを解析するためのパーサーとしてlxmlや標準のhtml.parserが利用されます。
# BeautifulSoupのインストール(未インストールの場合)
# pip install beautifulsoup4 lxml
ライブラリの準備ができたら、基本的なインポートと解析の準備を行います。
from bs4 import BeautifulSoup
# サンプルとなるHTMLデータ
html_content = """
<html>
<body>
<h1 id="title">メインタイトル</h1>
<p class="description">これはサンプルの段落です。</p>
<a href="https://example.com">リンクはこちら</a>
</body>
</html>
"""
# BeautifulSoupオブジェクトの作成
soup = BeautifulSoup(html_content, "html.parser")
.name属性とは何か
BeautifulSoupでHTMLをパースすると、各タグはTagクラスのインスタンスとして扱われます。
.name属性はこのTagオブジェクトが保持する変数で、その要素がどの種類のタグ(要素名)であるかを格納しています。
例えば、<h1>タグから生成されたオブジェクトの.nameを参照すると、文字列として"h1"が得られます。
これは単純な文字列比較に使用できるため、スクレイピングのロジックを組む上で非常に便利です。
実際のコードで学ぶタグ名の取得
それでは、具体的なコード例を見ながら、どのようにタグ名を取得していくのかを確認しましょう。
単一の要素を取得する場合と、複数の要素をまとめて処理する場合の2つのパターンを解説します。
単一の要素からタグ名を取得する
特定のIDやクラス名を持つ要素をfind()メソッドなどで取得し、そのタグ名を確認する方法です。
# IDを指定して要素を取得
header_element = soup.find(id="title")
# タグ名を取得して表示
tag_name = header_element.name
print(f"取得した要素のタグ名: {tag_name}")
# 出力結果に基づいて処理を分岐させる例
if tag_name == "h1":
print("これは大見出しです。")
取得した要素のタグ名: h1
これは大見出しです。
このように、find()で取得したオブジェクトに対して.nameを呼び出すだけで、その正体が判明します。
複数の要素をループで処理してタグ名を取得する
ページ内のすべての要素を走査し、それぞれのタグ名を取得したい場合はfind_all()や.descendants(子孫要素の全取得)を使用します。
# bodyタグ内のすべての子要素を取得
body_tag = soup.body
print("--- body内のタグ一覧 ---")
# .children を使って直接の子要素をループ処理
for child in body_tag.children:
# NavigableString(改行や空白)を除外してTagオブジェクトのみ処理
if child.name is not None:
print(f"タグ名: {child.name}")
--- body内のタグ一覧 ---
タグ名: h1
タグ名: p
タグ名: a
ここで注意したいのは、HTML内の改行や空白も要素としてカウントされる場合があるという点です。
これらはNavigableStringという型になり、.name属性を持たない(Noneを返す)ため、上記のようにis not Noneでチェックするのが一般的です。
タグ名を判定・利用する応用テクニック
タグ名の取得は、単に名前を確認するだけでなく、データの加工や複雑な抽出条件の作成にも役立ちます。
条件分岐で特定のタグのみを抽出する
特定のコンテナ(divなど)の中に、どのようなタグが混在しているか分からない場合、タグ名でフィルタリングを行うことができます。
# 混合したタグが含まれるHTML
mixed_html = """
<div id="container">
<span>ラベル1</span>
<p>テキスト1</p>
<span>ラベル2</span>
<button>クリック</button>
</div>
"""
mixed_soup = BeautifulSoup(mixed_html, "html.parser")
container = mixed_soup.find(id="container")
# spanタグの内容だけを抽出するロジック
labels = []
for element in container.find_all():
if element.name == "span":
labels.append(element.get_text())
print(f"抽出されたラベル: {labels}")
抽出されたラベル: ['ラベル1', 'ラベル2']
もちろん、最初からfind_all("span")と書くことも可能ですが、ループの中で「もしこのタグがaならURLを、pなら本文を取得する」といった複雑な振り分けが必要な場合に、.nameによる判定が威力を発揮します。
.name属性を使ってタグ名を変更する
意外と知られていない機能として、.name属性に新しい値を代入することで、HTMLのタグ名自体を書き換えることが可能です。
これは、スクレイピングしたデータを別の形式(例えばHTMLからXMLへ、あるいは特定のタグを別のタグへ置換)へ変換したい場合に重宝します。
# タグ名の書き換え例
html_to_modify = "<div>現在のタグはdivです</div>"
modify_soup = BeautifulSoup(html_to_modify, "html.parser")
tag = modify_soup.div
print(f"変更前: {tag}")
# タグ名を p に変更
tag.name = "p"
print(f"変更後: {tag}")
変更前: <div>現在のタグはdivです</div>
変更後: <p>現在のタグはdivです</p>
このように、BeautifulSoupは解析だけでなくHTMLの編集ツールとしても非常に強力です。
親要素や子要素のタグ名を確認する
特定の要素を見つけた際、その「親」が何であるかによってデータの意味が変わることがあります。
例えば、<li>タグを見つけたとき、その親が<ul>(箇条書き)なのか<ol></ol>(番号付きリスト)なのかを判定するケースです。
list_html = "<ol><li>項目1</li></ol>"
list_soup = BeautifulSoup(list_html, "html.parser")
item = list_soup.find("li")
# 親要素のタグ名を確認
parent_tag_name = item.parent.name
print(f"liの親タグは: {parent_tag_name}")
| プロパティ | 取得できるもの |
|---|---|
element.name | その要素自身のタグ名 |
element.parent.name | 直上の親要素のタグ名 |
element.next_sibling.name | 同じ階層の次の要素のタグ名 |
実践:複雑なHTML構造から効率よく情報を抜き出す
実際のWebサイトは非常に複雑な構造をしています。
タグ名取得を応用して、実戦に近い形でデータを抽出してみましょう。
find_all()と.nameの組み合わせ
以下の例では、記事のリストから「見出しタグ(h1〜h3)」だけをすべて抜き出し、それぞれのレベルに応じて出力形式を変えるプログラムを示します。
blog_html = """
<article>
<h1>記事タイトル</h1>
<p>導入文です。</p>
<h2>セクション1</h2>
<p>内容1...</p>
<h3>詳細1-1</h3>
<p>詳細内容...</p>
<h2>セクション2</h2>
</article>
"""
blog_soup = BeautifulSoup(blog_html, "html.parser")
# h1, h2, h3タグをすべて取得
import re
headers = blog_soup.find_all(re.compile("^h[1-3]$"))
for h in headers:
# タグ名に応じてインデントを変えて表示
level = h.name # 'h1', 'h2' など
prefix = ""
if level == "h1": prefix = "# "
elif level == "h2": prefix = "## "
elif level == "h3": prefix = "### "
print(f"{prefix}{h.get_text()}")
# 記事タイトル
## セクション1
### 詳細1-1
## セクション2
正規表現re.compile("^h[1-3]$")を使って複数のタグを一括で取得し、その後.nameを使って個別の処理を行うという、非常に効率的なスクレイピングの流れです。
トラブルシューティングと注意点
.name属性を使用する際には、いくつか注意すべき落とし穴があります。
エラーを防ぐためのポイントを押さえておきましょう。
.nameがNoneになるケースとその対策
もっとも多いトラブルは、AttributeError: 'NoneType' object has no attribute 'name' というエラーです。
これはfind()などで要素が見つからなかった(Noneが返ってきた)場合に、その.nameを参照しようとすることで発生します。
# 存在しないIDを指定
target = soup.find(id="non-existent")
# エラーを避けるための安全な書き方
if target:
print(target.name)
else:
print("要素が見つかりませんでした。")
また、前述の通りテキストノード(NavigableString)をループで取得してしまった場合、.nameは値としてNoneを返します。
タグだけを処理したい場合は必ず型や名前の存在をチェックするようにしましょう。
BeautifulSoupのパーサーによる挙動の違い
BeautifulSoupでは、使用するパーサーによってタグ名の扱いが微妙に異なる場合があります。
- html.parser: Python標準。追加インストール不要だが、一部の壊れたHTMLに弱い。
- lxml: 非常に高速で寛容。基本的にはこれを使うのが推奨。
- html5lib: Webブラウザと同じ方法でパースする。非常に低速だが正確。
2026年現在のモダンな環境ではlxmlがデファクトスタンダードですが、環境によっては大文字小文字の正規化ルールが異なることがあるため、タグ名の比較を行う際は念のため.lower()を併用するか、パーサーを固定して運用するのが安全です。
まとめ
PythonのBeautifulSoupにおける.name属性は、スクレイピングの対象となる要素がどのHTMLタグであるかを特定するためのシンプルかつ強力な手段です。
本記事で解説した内容のポイントを振り返ります。
- 基本:
element.nameでタグ名を文字列(”div”, “p”など)として取得できる。 - 応用: ループ処理や正規表現と組み合わせることで、特定のタグ種別に応じた柔軟なデータ抽出が可能。
- 編集:
element.name = "new_tag"とすることで、タグそのものを書き換えることができる。 - 注意: 要素が見つからない場合やテキストノードの場合に備え、Noneチェックを欠かさないことが重要。
タグ名の取得を正しく使いこなせるようになると、スクレイピングコードの可読性と堅牢性が格段に向上します。
ぜひ自身のプロジェクトでも、.nameを活用したスマートなコードを書いてみてください。
