Pythonを活用したWebスクレイピングにおいて、最も頻繁に行われる操作の一つが、HTML要素からの「テキストの抽出」です。
数あるライブラリの中でもBeautifulSoupは直感的な操作が可能であり、特にget_text()メソッドは、複雑なタグ構造から必要な文字列だけを取り出すための非常に強力なツールとなります。
しかし、単純にget_text()を呼び出すだけでは、意図しない改行が含まれたり、タグ同士のテキストが繋がってしまったりといった問題に直面することも少なくありません。
本記事では、BeautifulSoupのget_text()を使いこなし、ノイズの少ない綺麗なテキストデータを取得するためのテクニックを、基本から応用まで詳しく解説します。
BeautifulSoupにおけるテキスト取得の基本
HTMLドキュメントからテキストを取得する際、最もシンプルで多用されるのがget_text()メソッドです。
このメソッドは、指定した要素内にあるすべてのタグを取り除き、テキスト部分のみを結合して返します。
まずは、基本的な使い方を確認してみましょう。
from bs4 import BeautifulSoup
# サンプルのHTML
html_content = """
<div id="main-content">
<h1>最新のテクノロジー動向</h1>
<p>2026年のAI技術は、さらなる進化を遂げています。</p>
<p>スクレイピングはデータ分析の第一歩です。</p>
</div>
"""
# BeautifulSoupオブジェクトの作成
soup = BeautifulSoup(html_content, 'html.parser')
# div要素を取得
main_div = soup.find('div', id='main-content')
# get_text()でテキストのみを抽出
text = main_div.get_text()
print(text)
最新のテクノロジー動向
2026年のAI技術は、さらなる進化を遂げています。
スクレイピングはデータ分析の第一歩です。
上記の例では、<h1>や<p>、さらには<b>といったタグがすべて除去され、中のテキストだけが取り出されていることがわかります。
しかし、出力結果をよく見ると、不必要な空行や空白が含まれていることに気づくはずです。
これはHTML内の改行やインデントがそのまま保持されているためです。
get_text()の引数を活用したクレンジング
get_text()には、取得するテキストを整形するための重要な引数が用意されています。
これらを使いこなすことで、後処理の手間を大幅に削減できます。
separator引数でテキストの繋がりを防ぐ
デフォルトのget_text()は、タグ間のテキストをそのまま連結します。
そのため、タグの配置によっては、本来スペースが必要な場所で文字が繋がってしまうことがあります。
これを防ぐのがseparator引数です。
html_list = "<ul><li>Python</li><li>BeautifulSoup</li><li>Scraping</li></ul>"
soup = BeautifulSoup(html_list, 'html.parser')
# 引数なしの場合
print(f"デフォルト: {soup.get_text()}")
# separatorを指定した場合
print(f"カンマ区切り: {soup.get_text(separator=', ')}")
デフォルト: PythonBeautifulSoupScraping
カンマ区切り: Python, BeautifulSoup, Scraping
separatorに任意の文字列を指定することで、各タグの境界にその文字列を挿入できます。CSV形式に近い形でデータを取得したい場合や、単語間の結合を防ぎたい場合に非常に便利です。
strip引数で余分な空白を除去する
先ほどの基本例で見たような、テキストの前後にある余計な空白や改行を取り除きたい場合は、strip=Trueを指定します。
# strip=True を指定して取得
clean_text = main_div.get_text(strip=True)
print(clean_text)
最新のテクノロジー動向2026年のAI技術は、さらなる進化を遂げています。スクレイピングはデータ分析の第一歩です。
strip=Trueにすると、各テキストノードの前後にある空白文字が削除されます。
ただし、これだけでは文章同士が密着してしまうため、多くの場合、separatorとstripを組み合わせて使用するのがベストプラクティスとなります。
# separatorとstripの組み合わせ
best_practice_text = main_div.get_text(separator='\n', strip=True)
print(best_practice_text)
最新のテクノロジー動向
2026年のAI技術は、さらなる進化を遂げています。
スクレイピングはデータ分析の第一歩です。
このように、separator='\n'で各要素の間に改行を入れつつ、strip=Trueで無駄な空白を削ることで、非常に読みやすいテキストが得られます。
特定のタグを除去してテキストを取得する方法
Webページには、本文以外にもナビゲーションメニュー、広告、あるいはJavaScriptのコード(scriptタグ)など、テキストとして抽出したくない要素が多々含まれています。
get_text()を実行する前に、これらの不要なタグを除去(分解)しておくことが重要です。
decompose()によるタグの完全除去
BeautifulSoupのdecompose()メソッドを使用すると、指定したタグとその中身を完全に削除できます。
html_complex = """
<article>
<h2>記事タイトル</h2>
<script>var ads = 'dummy';</script>
<p>ここが重要な本文です。</p>
<aside>関連記事の広告など</aside>
</article>
"""
soup = BeautifulSoup(html_complex, 'html.parser')
# 不要なscriptタグとasideタグを除去
for unwanted in soup.find_all(['script', 'aside']):
unwanted.decompose()
# 除去した後のテキストを取得
final_text = soup.get_text(separator=' ', strip=True)
print(final_text)
記事タイトル ここが重要な本文です。
decompose()を適用すると、soupオブジェクト自体からその要素が消滅します。そのため、その後のget_text()の結果には、不要なスクリプトや広告のテキストが含まれなくなります。
get_text()と.string、.textの違い
BeautifulSoupでテキストを取得する際、get_text()以外にも似たようなプロパティが存在します。
それぞれの違いを正しく理解して使い分ける必要があります。
.text プロパティ
.textは、内部的にget_text()を呼び出しているプロパティです。
基本的にはget_text()と同じ結果を返しますが、引数を渡すことができません。
細かい制御が必要な場合はget_text()を、単にそのまま取得したい場合は.textを使うという使い分けが一般的です。
.string プロパティ
.stringは、その要素が「直下に一つのテキストノードだけを持っている場合」にその文字列を返します。
タグの中にさらに別のタグ(子要素)が含まれている場合、.stringはNoneを返します。
| プロパティ/メソッド | 複数の子要素がある場合 | 引数の指定 | 特徴 |
|---|---|---|---|
get\_text() | すべてのテキストを結合して取得 | 可能 | 最も柔軟で一般的 |
.text | get\_text() と同じ | 不可 | 簡潔に記述できる |
.string | None を返す | 不可 | 単一のテキストのみ対象 |
実務レベルのスクレイピングでは、要素内にどのようなタグが含まれているか厳密に予測できないことが多いため、基本的にはget_text()を使用するのが最も安全です。
応用:実戦的なテキスト取得と加工
Webサイトの構造は千差万別です。
ここでは、実務で遭遇しやすいケースに対する応用テクニックを紹介します。
改行タグ
を適切な改行に変換する
HTMLの<br>タグは、get_text(strip=True)を使うと無視されて文字が繋がってしまうことがあります。
これを適切に処理するには、あらかじめ<br>タグを改行文字に置換しておく方法が有効です。
html_br = "<div>東京都<br>千代田区<br>1-1-1</div>"
soup = BeautifulSoup(html_br, 'html.parser')
# 全てのbrタグを改行文字に置換
for br in soup.find_all("br"):
br.replace_with("\n")
print(soup.get_text())
東京都
千代田区
1-1-1
このようにreplace_with()を用いることで、HTMLの視覚的な改行をテキストデータ上でも再現することが可能になります。
正規表現を用いたテキストのクレンジング
get_text()で取得した後の文字列には、連続する空白や特殊な記号が含まれていることがあります。
Pythonの標準ライブラリであるreモジュールを組み合わせることで、さらに精度の高いデータを作成できます。
import re
raw_text = " Python Web Scraping \t 2026 "
# 連続する空白(スペース、タブ、改行)を一つのスペースに集約
cleaned_text = re.sub(r'\s+', ' ', raw_text).strip()
print(f"修正前: '{raw_text}'")
print(f"修正後: '{cleaned_text}'")
修正前: ' Python Web Scraping 2026 '
修正後: 'Python Web Scraping 2026'
Webサイトから取得したデータは、機械学習の学習データや検索エンジンのインデックスとして利用されることも多いため、このようなノイズ除去の工程は非常に重要です。
表データのテキスト取得テクニック
HTMLのテーブル要素からテキストを抽出する場合、単純なget_text()では行や列の区切りが失われてしまいます。
ここではリスト内包表記を活用して、構造を保ったままテキストを取得する方法を解説します。
html_table = """
<table>
<tr><th>言語</th><th>用途</th></tr>
<tr><td>Python</td><td>AI/スクレイピング</td></tr>
<tr><td>JavaScript</td><td>フロントエンド</td></tr>
</table>
"""
soup = BeautifulSoup(html_table, 'html.parser')
# 各行(tr)ごとにテキストを取得しリスト化
table_data = []
for row in soup.find_all('tr'):
cols = row.find_all(['th', 'td'])
# 各セルからテキストを取得し、余分な空白を除去
col_text = [ele.get_text(strip=True) for ele in cols]
table_data.append(col_text)
for line in table_data:
print(line)
['言語', '用途']
['Python', 'AI/スクレイピング']
['JavaScript', 'フロントエンド']
この手法を使えば、HTMLの構造をPythonのリスト形式として保持できるため、その後のPandasなどを用いたデータ分析への移行がスムーズになります。
効率的なスクレイピングのための注意点
BeautifulSoupとget_text()は非常に便利ですが、大規模なWebサイトを対象にする場合は、パフォーマンスとエチケットにも配慮が必要です。
- 対象を絞ってから取得する
soup.get\_text()をドキュメント全体に対して実行するのではなく、まずはsoup.find()などで必要な範囲を特定し、その要素に対してのみ実行するようにしましょう。これにより、メモリ消費を抑え、不要なデータの混入を防げます。 - エンコーディングの確認
取得したテキストが文字化けしている場合、BeautifulSoupに渡す前のレスポンスデータのエンコーディングが正しく認識されていない可能性があります。requestsライブラリなどを使用している場合は、response.encoding = response.apparent\_encodingを設定することを検討してください。 - サーバーへの負荷軽減
連続して大量のページからテキストを取得する際は、必ずtime.sleep()を挟み、相手サーバーに過度な負荷をかけないようにしましょう。
まとめ
BeautifulSoupのget_text()は、Webスクレイピングにおけるテキスト抽出の核心となるメソッドです。
単純なテキスト取得から、separatorやstripを活用した高度な整形、さらにはdecompose()によるノイズ除去まで、その活用範囲は非常に多岐にわたります。
「どのようにデータを取得したいか」を明確にし、適切な引数や前処理を組み合わせることで、スクレイピングの精度と効率は劇的に向上します。
今回紹介したテクニックを駆使して、あなたのデータ収集プロジェクトをより洗練されたものに進化させてください。
Webサイトの構造は日々変化しますが、基本となるテキスト抽出の考え方をマスターしておけば、どのような変化にも柔軟に対応できるはずです。
まずは身近なサイトの解析から、get_text()の挙動を実際に試してみることから始めてみましょう。
