PythonでWebスクレイピングを行う際、HTML内の改行を正しく取得できずに困るケースは少なくありません。
特に<br>タグが含まれる要素からテキストを抽出すると、Beautiful Soupの標準的な処理では改行が無視され、文字が繋がってしまうことがあります。
この記事では、Beautiful Soupを使用して<br>タグを適切に改行コードへ変換し、人間が読みやすい形式でデータを取得する手法を詳しく解説します。
最新のPython環境でも利用できる効率的な置換テクニックをマスターして、スクレイピングの精度を向上させましょう。
なぜBeautiful Soupで改行が消えてしまうのか
Beautiful Soupのget_text()メソッドは、HTMLタグをすべて取り除いてテキストのみを抽出する便利な機能です。
しかし、<br>タグは「改行」という指示を出すタグでありながら、中身にテキストを持たないため、単純に削除されると前後の文字が連結されてしまいます。
例えば、「東京都<br>新宿区」というデータがあった場合、何も対策をしないと「東京都新宿区」という1つの文字列として取得されます。
住所や商品の説明文、ニュース記事など、改行に意味があるデータを扱う場合、この挙動は大きな問題となります。
スクレイピング後のデータ加工を容易にするためには、タグを削除する前に改行文字への変換が必要です。
方法1:replace_withを使用してbrタグを置換する
最も確実で細かな制御ができる方法は、replace_withメソッドを使用して、すべての<br>タグを明示的に改行コード(\n)に置き換える手法です。
具体的な実装コード
以下のコードは、Beautiful Soupで解析したドキュメント内のすべての<br>タグを見つけ、それをテキストの改行に置換する処理を示しています。
from bs4 import BeautifulSoup
# サンプルHTMLデータ
html_content = """
<div class="address">
〒160-0022<br>
東京都新宿区<br>
新宿ビル1F
</div>
"""
soup = BeautifulSoup(html_content, 'html.parser')
target_div = soup.find('div', class_='address')
# すべてのbrタグを取得して改行コードに置換
for br in target_div.find_all("br"):
br.replace_with("\n")
# テキストを抽出
result_text = target_div.get_text()
print(result_text)
〒160-0022
東京都新宿区
新宿ビル1F
この方法のメリットは、特定の要素内にあるタグだけを対象にするなど、柔軟なカスタマイズが可能である点にあります。
replace_withは元のツリー構造を書き換えるため、その後にget_text()を呼び出すだけで理想的なテキストが得られます。
方法2:get_textのseparator引数を利用する
もっとシンプルに記述したい場合は、get_text()メソッドに用意されているseparator引数を利用するのが効率的です。
この引数に改行コードを指定すると、タグの区切り目ごとに指定した文字を挿入してくれます。
separator引数の活用例
コードの記述量を減らしつつ、要素間の区切りを明確にしたい場合に非常に有効な手段です。
from bs4 import BeautifulSoup
html_content = "<p>第一行<br>第二行<br>第三行</p>"
soup = BeautifulSoup(html_content, 'html.parser')
# separator引数に改行コードを指定
clean_text = soup.get_text(separator="\n")
print(clean_text)
第一行
第二行
第三行
注意点として、この方法は<br>タグだけでなく、すべてのタグの境界に改行が挿入されます。
そのため、複雑なHTML構造の場合は、意図しない場所に多くの空行が発生する可能性があります。
strip=True引数を併用することで、余計な空白を除去し、結果を綺麗に整えることができます。
どちらの方法を選ぶべきか?
プロジェクトの要件に応じて、適切な手法を選択することが重要です。
以下の表に、それぞれの特徴をまとめました。
| 手法 | メリット | デメリット |
|---|---|---|
| replace_with | 特定のタグのみをピンポイントで置換できる。 | ループ処理が必要でコードが数行増える。 |
| separator引数 | 1行で記述でき、処理が高速。 | 全てのタグに適用されるため微調整が難しい。 |
基本的には「まずはseparatorを試し、結果が崩れるようならreplace_withで個別対応する」という流れが推奨されます。
実践的なデータクリーニング:余分な空白の除去
改行を取得した際、HTML上のインデント(空白文字)が一緒に取得されてしまい、データが汚くなることがあります。
これを解決するには、Python標準の文字列メソッドstrip()や、リスト内包表記を組み合わせると効果的です。
raw_text = target_div.get_text(separator="\n")
# 各行の前後空白を削除し、空行を除外して再結合
lines = [line.strip() for line in raw_text.splitlines() if line.strip()]
final_text = "\n".join(lines)
print(final_text)
このように、抽出後の文字列操作をワンセットで行うことで、機械学習やデータベース保存に適したクリーンなデータを作成できます。
まとめ
Beautiful Soupで<br>タグを改行として扱うには、replace_withによる明示的な置換か、get_text(separator="\n")による一括処理が有効です。
構造が単純な場合はseparator引数が最も手軽ですが、精密なデータ抽出が求められる場面では、対象となるタグを個別に置換する手法が適しています。
Webサイトの構造は多様であるため、取得したいデータの形式に合わせてこれらの手法を使い分けてみてください。
適切な改行処理を行うだけで、スクレイピングデータの可読性と実用性は格段に向上します。
