Webスクレイピングの現場において、PythonのBeautiful Soupライブラリは非常に強力なツールです。
しかし、取得したHTMLコードが一行に凝縮されていたり、インデントが崩れていたりすると、構造を把握するのが非常に困難になります。
そこで重宝するのがprettify()メソッドです。
このメソッドを使用することで、複雑なHTML構造を人間が読みやすい形式に整形し、デバッグの効率を劇的に向上させることが可能です。
一方で、日本語環境においては特有の「文字化け(Unicodeエスケープ)」という課題も存在します。
本記事では、2026年現在の最新のベストプラクティスを交えながら、prettify()の基本的な使い方から、日本語を正しく扱うためのテクニック、実用的な出力設定までを詳しく解説します。
BeautifulSoupのprettifyメソッドとは
Beautiful Soupにおけるprettify()は、パースされたHTMLのツリー構造を視覚的に分かりやすいインデント付きの文字列に変換するためのメソッドです。
スクレイピング対象のWebサイトは、データ転送量を削減するためにHTMLが「難読化」や「圧縮(Minify)」されていることが少なくありません。
改行や空白が一切ない状態のHTMLソースコードをそのままプリントしても、どのタグがどこで閉じているのか、親子関係がどうなっているのかを判別するのは至難の業です。
prettify()を適用すると、各タグが独自の行に配置され、階層構造に基づいたインデントが挿入されます。
これにより、開発者はブラウザの「検証」ツールで見ているような整然としたソースコードをコンソール上で確認できるようになります。
基本的な使い方と出力の変化
まずは、最もシンプルな使用例を見てみましょう。
標準的なHTMLをパースし、そのまま出力した場合とprettify()を通した場合の差を確認します。
from bs4 import BeautifulSoup
# サンプルとなる圧縮されたHTML
html_doc = "<html><head><title>サンプルサイト</title></head><body><h1>こんにちは</h1><p>これはテストです。</p></body></html>"
# BeautifulSoupオブジェクトの作成
soup = BeautifulSoup(html_doc, 'html.parser')
# 通常の出力
print("--- 通常の出力 ---")
print(soup)
# prettify() を適用した出力
print("\n--- prettify() を適用した出力 ---")
print(soup.prettify())
--- 通常の出力 ---
<html><head><title>サンプルサイト</title></head><body><h1>こんにちは</h1><p>これはテストです。</p></body></html>
--- prettify() を適用した出力 ---
<html>
<head>
<title>
サンプルサイト
</title>
</head>
<body>
<h1>
こんにちは
</h1>
<p>
これはテストです。
</p>
</body>
</html>
このように、タグごとに改行が入り、視認性が大幅に向上していることがわかります。
デフォルトでは1つのスペースを用いたインデントが適用されます。
日本語が文字化けする原因と対策
多くのユーザーがprettify()を使用して最初に行き当たる壁が、日本語部分がUnicodeエスケープ形式(例:\u3053\u3093…)で出力されてしまう現象です。
これは厳密には「文字化け」ではなく、Beautiful SoupがHTMLエンティティを安全に処理しようとするための仕様ですが、人間が読む分には不便です。
なぜエスケープされるのか
Beautiful Soupのprettify()は、デフォルトで出力をASCIIエンコーディングに準拠させようとします。
その結果、日本語のような非ASCII文字は、すべてUnicodeエスケープシーケンスに変換されます。
これを回避して、日本語をそのままの文字として表示・保存するためには、出力時のエンコーディングやフォーマッタの設定を変更する必要があります。
日本語を正しく表示する方法
日本語をそのまま出力したい場合、prettify()の結果を特定のエンコーディング(主にutf-8)でエンコードし、それをデコードし直すという手法がよく使われます。
from bs4 import BeautifulSoup
html_doc = "<div><p>Pythonでスクレイピング</p></div>"
soup = BeautifulSoup(html_doc, 'html.parser')
# 方法1: エンコードとデコードを組み合わせる
formatted_html = soup.prettify().encode('utf-8').decode('utf-8')
print(formatted_html)
<div>
<p>
Pythonでスクレイピング
</p>
</div>
この方法を用いることで、コンソール上でも日本語が読み取れる状態で整形出力されます。
現代のPython 3環境では、内部的にUnicodeを扱うため、この変換処理が最も確実です。
formatter引数による実用的な出力設定
prettify()メソッドには、出力のカスタマイズを行うためのformatterという引数が存在します。
これを利用することで、特殊文字の扱いを制御できます。
formatter=”html” の活用
Beautiful Soupはデフォルトで、特定の記号(& など)をHTMLエンティティ(& など)に変換します。
しかし、場合によってはそのままの状態で出力したいこともあります。
| 指定値 | 動作の概要 |
|---|---|
"minimal" | デフォルト。最小限のHTMLエンティティ変換を行う |
"html" | HTML5のルールに則った変換を行う |
None | 変換を一切行わず、元の文字を維持しようとする |
日本語の出力をより自然に保ちたい場合、このformatterにNoneを指定する方法も有効です。
ただし、この場合はHTMLとして無効な構造(タグ内に不正な文字が含まれる等)になるリスクがあるため、用途に応じて使い分けるのがプロのテクニックです。
# formatterにNoneを指定してエスケープを抑制する
print(soup.prettify(formatter=None))
インデントのカスタマイズ
実は、Beautiful Soupの標準的なprettify()メソッド単体では、インデントのスペース数を直接指定する引数は用意されていません。
しかし、生成された文字列に対して、後処理を行うことで対応可能です。
もし厳格に「インデントはスペース4つ」といったルールを適用したい場合は、自作のラッパー関数を用意するか、あるいは出力された文字列のインデントを置換する処理を検討します。
ただし、デバッグ目的であればデフォルトの1スペースでも十分に機能します。
ファイルへの保存とエンコーディング
整形したHTMLをファイルに保存する際も、文字コードの扱いに注意が必要です。
Windows環境などで標準のopen()関数をエンコーディング指定なしで使うと、cp932(Shift-JIS系)で書き込まれ、エラーが発生することがあります。
必ずencoding=’utf-8′を明示的に指定しましょう。
# 整形したHTMLをファイルに保存する
output_file = "formatted_index.html"
with open(output_file, "w", encoding="utf-8") as f:
# 日本語をエスケープさせずに保存
f.write(soup.prettify())
print(f"{output_file} に保存しました。")
このコードを実行すると、保存されたHTMLファイルをVS Codeなどのエディタで開いた際、美しく整形された日本語のソースコードを確認できます。
prettifyの応用:特定の要素だけを整形する
prettify()はBeautifulSoupオブジェクト全体だけでなく、特定のTagオブジェクトに対しても呼び出すことができます。
これは、巨大なWebページの一部だけを抽出して確認したい場合に非常に便利です。
# 特定のdivタグだけを抜き出して整形
target_div = soup.find("div", class_="content-area")
if target_div:
print(target_div.prettify())
ページ全体を整形すると出力が長くなりすぎて、かえって目的のデータが見つかりにくくなることがあります。
必要なパーツだけをfind()やselect()で取得し、その要素に対してのみprettify()を適用するのがスマートなデバッグ手法です。
動作環境による出力の違いと注意点
Beautiful Soupが背後で使用する「パーサー」によって、prettify()の結果が微妙に異なる場合があります。
パーサー(lxml / html.parser)による挙動の差
Python標準のhtml.parserと、高速な外部ライブラリであるlxmlでは、HTMLの補完ルールが異なります。
- html.parser: Python標準。追加インストール不要だが、不完全なHTMLの修復能力は中程度。
- lxml: 非常に高速で、壊れたHTMLの修復能力が高い。ただし、
prettify()した際に自動的に<html>や<body>タグを補完してしまうことがある。
# lxmlを使用する場合
soup = BeautifulSoup(html_doc, 'lxml')
もし、元のHTMLに存在しないタグがprettify()の結果に含まれている場合は、パーサーの影響を疑ってみてください。
特定のタグだけを確認したい場合は、前述のように特定のTagオブジェクトに対してメソッドを実行することで回避できます。
2026年現在の環境におけるパフォーマンス
近年のPCスペック向上により、数MB程度のHTMLであればprettify()の処理速度が問題になることは稀です。
しかし、数十MBを超えるような巨大なデータ(ログファイルがHTML化されている場合など)に対して実行すると、文字列の再構築にメモリと時間を消費します。
本番環境の自動処理プログラム(バッチ処理)の中に prettify() を組み込むのは避けるべきです。
あくまで開発時の確認用、あるいは人間が読むためのレポート生成用として限定的に利用するのが推奨されます。
実践的なデータスクレイピングでの活用フロー
実際の開発プロジェクトでは、以下のような流れでprettify()を活用します。
- リクエスト取得:
requestsやhttpxを使用してHTMLを取得。 - 仮パース: BeautifulSoupオブジェクトを作成。
- 構造確認:
print(soup.find('main').prettify())などで、抽出したいデータの正確な階層を確認。 - 抽出ロジック作成: 整形されたコードを見ながら、CSSセレクタや属性の条件を記述。
- 最終クリーンアップ: 本番コードからは
prettify()を削除し、生のデータ抽出処理のみを残す。
このように、prettify()は「地図」のような役割を果たします。
複雑に入り組んだ現代のWebサイト構造を紐解くための必須ツールと言えるでしょう。
まとめ
Beautiful Soupのprettify()メソッドは、スクレイピングにおける作業効率を大きく変えてくれる機能です。
- HTMLを構造化して出力し、タグの親子関係を明確にする。
- 日本語の文字化け(エスケープ)を防ぐには、
.encode('utf-8').decode('utf-8')の組み合わせが有効。 formatter引数を使って、特殊文字の変換ルールを制御できる。- ファイル保存時は必ず
encoding='utf-8'を指定する。 - ページ全体ではなく、特定のタグに対して適用することでデバッグを効率化する。
これらのテクニックを駆使することで、読みづらいソースコードに悩まされることなく、スムーズにデータ抽出のロジック構築に専念できるようになります。
最新のPython環境でも変わらず愛用されているこの機能を正しく理解し、日々のコーディングに役立ててください。
