HTML構造の変化に対する耐性のあるコードの書き方

ライブラリBeautiful Soupを用いたWebスクレイピングにおいて、HTML構造の変化は非常に一般的な問題です。サイト側の微小な変更(クラス名の変更、タグの追加・削除、ネスト構造の変更など)によってスクレイピングコードが動作しなくなる可能性があります。以下に、HTML構造の変化に対して耐性のあるコードの書き方について詳しく説明します。


1. 特定のタグやクラスに依存しすぎない

過度に具体的なタグやクラス名に依存すると、HTML構造が少しでも変化した際に動作しなくなります。

改善策:

  • クラス名の変化を想定し、class_の指定を最小限にする

  • タグの位置ではなく、内容や構造に基づいて柔軟に検索する

例:

python
# 脆弱な例(クラス名変更で動作しない) soup.find('div', class_='article-content') # より堅牢な例(複数条件、タグの組み合わせ) soup.select_one('div[class*=content]')

2. .find().find_all()の戻り値の確認

HTML構造が変わって目的の要素が存在しなくなると、Noneが返され、後続の.text.get()などでエラーが発生します。

改善策:

  • if文やtry-exceptを用いて存在確認を行う

  • デフォルト値を設定することで安全に取得する

例:

python
element = soup.find('h1') title = element.get_text(strip=True) if element else 'タイトル未取得'

3. 複数の候補に対応できるロジック

同一の意味を持つ要素が複数のタグで表現される可能性を考慮し、複数の検索条件を試す実装にしておくと堅牢です。

例:

python
title = (soup.find('h1') or soup.find('h2') or soup.find('div', class_='title')) if title: print(title.get_text(strip=True))

4. select()/select_one()による柔軟なCSSセレクタ

複雑なネストや親子関係の構造がある場合、CSSセレクタを使用するとより柔軟に要素を指定できます。

例:

python
# div内のaタグを取得 link = soup.select_one('div.article > a')

5. エラーハンドリングの実装

Beautiful Soup単体での処理に加えて、構造変化による例外に備えて例外処理を設けることが重要です。

例:

python
try: data = soup.find('table').find_all('tr') except AttributeError: print('構造変更によりtableが見つかりません')

6. テストとHTMLサンプルの保持

定期的に対象サイトのHTMLを保存し、構造変更の検知や再現テストに活用することで、変更に対する対応が容易になります。


まとめ

HTML構造の変化に強いBeautiful Soupのコードを書くためには、以下のポイントを意識することが重要です:

  • 特定の構造やクラス名に依存しすぎない

  • 要素が存在しない可能性を常に想定する

  • 柔軟な条件分岐や複数候補に対応する

  • 例外処理を加える

  • 定期的にHTML構造を確認・記録する

これにより、Webページ側の変更に対してもスクレイピング処理を安定して保守できます。

ChatGPT4o 生成日:2025/06/19