PythonのPandasでWebページのHTMLテーブルを簡単スクレイピングする方法
WebページからHTMLのtableタグで構成された表データを取得したい場面は多くあります。PythonのPandasライブラリを使用すれば、わずか数行のコードでWebページの表データを簡単にスクレイピングできます。本記事では、Pandasを使った効率的なWebスクレイピング手法を詳しく解説します。
目次
Pandasによる表スクレイピングの基本
必要なライブラリのインストール
まず、必要なライブラリをインストールします。
pip install pandas beautifulsoup4 lxml requests
基本的なスクレイピング方法
Pandasのread_html()関数を使用すると、WebページのHTMLテーブルを直接DataFrameとして取得できます。
import pandas as pd
# URLから直接テーブルを読み込み
url = "https://example.com/data.html"
tables = pd.read_html(url)
# 最初のテーブルを取得
df = tables[0]
print(df.head())
この方法では、指定したURLから全てのtableタグを自動的に検出し、それぞれをDataFrameのリストとして返します。
より詳細なスクレイピング手法
特定のテーブルを指定して取得
複数のテーブルが存在するページで、特定のテーブルのみを取得したい場合は以下のようにします。
import pandas as pd
# 特定の属性を持つテーブルを指定
url = "https://example.com/data.html"
tables = pd.read_html(url, attrs={'class': 'data-table'})
# またはテーブル内の特定文字列で絞り込み
tables = pd.read_html(url, match='売上データ')
df = tables[0]
print(df.info())
ヘッダー行の指定
テーブルのヘッダー行が複数行にわたる場合や、特定の行をヘッダーとして使用したい場合はheaderパラメータを使用します。
import pandas as pd
# 2行目をヘッダーとして使用
tables = pd.read_html(url, header=1)
# 複数行をヘッダーとして使用
tables = pd.read_html(url, header=[0, 1])
df = tables[0]
print(df.columns)
requestsとBeautifulSoupを組み合わせた高度な手法
セッション管理とカスタムヘッダー
ログインが必要なサイトや、特定のヘッダーが必要な場合はrequestsライブラリと組み合わせます。
import pandas as pd
import requests
from io import StringIO
# セッション作成
session = requests.Session()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
# HTMLを取得
response = session.get(url, headers=headers)
html_content = response.text
# pandasでテーブルを解析
tables = pd.read_html(StringIO(html_content))
df = tables[0]
特定の要素内のテーブルを取得
BeautifulSoupを使って、特定のdivやセクション内のテーブルのみを取得することも可能です。
import pandas as pd
import requests
from bs4 import BeautifulSoup
# HTMLを取得
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# 特定の親要素内のテーブルを取得
target_div = soup.find('div', {'class': 'content-area'})
tables = pd.read_html(str(target_div))
df = tables[0]
データクリーニングとエラーハンドリング
基本的なデータクリーニング
スクレイピングしたデータは、しばしばクリーニングが必要です。
import pandas as pd
import numpy as np
# テーブル取得
tables = pd.read_html(url)
df = tables[0]
# 欠損値の処理
df = df.dropna() # 欠損値行を削除
# または
df = df.fillna(0) # 欠損値を0で置換
# 数値列の型変換
df['売上'] = pd.to_numeric(df['売上'], errors='coerce')
# 不要な文字の除去
df['商品名'] = df['商品名'].str.replace('※', '')
エラーハンドリングの実装
ネットワークエラーや存在しないテーブルに対する適切な処理を行います。
import pandas as pd
import requests
from requests.exceptions import RequestException
def scrape_table(url, table_index=0):
try:
# タイムアウト設定
tables = pd.read_html(url, timeout=10)
if len(tables) <= table_index:
print(f"テーブルが{table_index + 1}個未満です")
return None
return tables[table_index]
except RequestException as e:
print(f"ネットワークエラー: {e}")
return None
except ValueError as e:
print(f"テーブルが見つかりません: {e}")
return None
# 使用例
df = scrape_table(url)
if df is not None:
print(df.head())
実践的な応用例
複数ページからのデータ統合
複数のページからテーブルデータを取得し、統合する例です。
import pandas as pd
import time
def scrape_multiple_pages(base_url, pages):
all_data = []
for page in range(1, pages + 1):
url = f"{base_url}?page={page}"
try:
tables = pd.read_html(url)
df = tables[0]
df['ページ'] = page
all_data.append(df)
# サーバーへの負荷軽減
time.sleep(1)
except Exception as e:
print(f"ページ{page}でエラー: {e}")
continue
# 全データを統合
combined_df = pd.concat(all_data, ignore_index=True)
return combined_df
# 使用例
df = scrape_multiple_pages("https://example.com/data", 5)
動的なテーブルの取得
JavaScriptで動的に生成されるテーブルの場合は、Seleniumとの組み合わせが必要です。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import pandas as pd
import time
# ヘッドレスモードでブラウザ起動
options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
# JavaScriptの実行完了を待機
time.sleep(3)
# ページソースを取得
html = driver.page_source
# pandasでテーブル解析
tables = pd.read_html(html)
df = tables[0]
finally:
driver.quit()
パフォーマンスの最適化
効率的なスクレイピングのコツ
大量のデータを扱う際のパフォーマンス向上のテクニックです。
import pandas as pd
from concurrent.futures import ThreadPoolExecutor
import requests
def scrape_single_url(url):
try:
tables = pd.read_html(url)
return tables[0]
except:
return None
# 並列処理でスクレイピング
urls = ["https://example.com/page1", "https://example.com/page2"]
with ThreadPoolExecutor(max_workers=3) as executor:
results = list(executor.map(scrape_single_url, urls))
# 結果をフィルタリングして統合
valid_results = [df for df in results if df is not None]
combined_df = pd.concat(valid_results, ignore_index=True)
まとめ
PandasのWebスクレイピング機能を活用することで、HTMLテーブルから効率的にデータを取得できます。基本的なread_html()から始まり、requestsやBeautifulSoupとの組み合わせ、さらには動的コンテンツへの対応まで、様々な手法を使い分けることで、あらゆるWebページからデータを取得できるようになります。
スクレイピングを行う際は、対象サイトの利用規約やrobot.txtを確認し、適切な間隔でのアクセスを心がけることが重要です。また、エラーハンドリングとデータの品質管理を徹底することで、安定したデータ収集システムを構築できます。
■らくらくPython塾 – 読むだけでマスター
■初心者歓迎「AI駆動開発/生成AIエンジニアコース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
格安のプログラミングスクールといえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
対面型でより早くスキル獲得、月額2万円のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<オンライン無料>ゼロから始めるPython爆速講座
