導入:Webスクレイピング+PandasによるCSV出力の必要性と課題
実務経験1〜3年目のエンジニアの皆さん、Web上からデータを自動で収集し、Pandasを使って解析・保存するフローは、日常業務やデータ活用に非常に役立ちます。しかし、HTML構造の変化によるエラー、複数ページの処理漏れ、大量アクセスによるスクレイピング禁止リスクなど、実装時に注意すべき課題も多くあります。
背景:関連技術とトレンド
- 昨今はPython+BeautifulSoup/Selenium+Pandasで、Webデータの取得→加工→保存の流れが一般的。
- 特に、pandas.read_html() によるtable抽出は頻出ニーズ(公式ドキュメントにあるが詳細不足)
- Seleniumを組み合わせた動的ページ対応も増加傾向
過去Qiitaで人気のコード例
- BeautifulSoup + tableタグ抽出後→CSV出力(tr/tdループ)
- Selenium+pandas.to_csv()による複数ページデータの取得自動化
技術的課題&エラー・パターン
- table構造が変更されると、BeautifulSoupのセレクタが一致せずnull取得。
- 多ページ取得で
requests
がタイムアウト、robots.txt非遵守によるアクセス禁止。 - Seleniumのheadlessブラウザ起動時にドライバ不整合エラー。
公式ドキュメントの要点/ギャップ
- Pandas公式では
read_html()
を推奨しているが、jsレンダリング非対応・ページ内tableが複数ある場合の対応が記載不足。 - to_csv()はエンコーディングやインデックス制御が可能だが、実運用の細かい設定例が不足
実務で役立つTips/失敗例
- requestsにタイムアウトやUser‑Agent指定を追加し、失敗時リトライ処理を入れる。
- robots.txt確認&アクセス間隔に
time.sleep()
挿入でAPI規約違反を回避。 - CSV出力後、
index=False
を必ず指定し、列名や文字化けも確認。
具体的構成:Web→Pandas→CSV自動出力プログラム
ステップ1:必要ライブラリ・環境準備
pip install requests beautifulsoup4 pandas lxml selenium # 必要に応じて
※動的ページには Selenium、静的HTMLなら requests + BeautifulSoup + pandas でOK。
ステップ2:HTML取得と解析
import requests
from bs4 import BeautifulSoup
import pandas as pd
def fetch_static(url):
resp = requests.get(url, timeout=10, headers={'User-Agent':'Mozilla/5.0'})
resp.raise_for_status()
return resp.text
def parse_table(html):
soup = BeautifulSoup(html, 'lxml')
table = soup.find('table', {'class':'target-table'})
rows = []
for tr in table.find_all('tr'):
cols = [td.get_text(strip=True) for td in tr.find_all(['th','td'])]
if cols:
rows.append(cols)
df = pd.DataFrame(rows[1:], columns=rows[0])
return df
ステップ3:CSV出力まで
def save_csv(df, filename):
df.to_csv(filename, index=False, encoding='utf-8-sig')
print(f"✅ Saved {filename}")
def main():
url = 'https://example.com/data'
html = fetch_static(url)
df = parse_table(html)
save_csv(df, 'output.csv')
if name == 'main':
main()
ステップ4:複数ページ/JS対応
from selenium import webdriver
from bs4 import BeautifulSoup
def fetch_dynamic(url):
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
driver.get(url)
html = driver.page_source
driver.quit()
return html
必要に応じて fetch_static → fetch_dynamic に切り替えて利用。
ステップ5:マルチページ処理とエラー対策
import time
def multi_page(base_url, pages=5):
dfs = []
for p in range(1, pages+1):
url = f"{base_url}?page={p}"
html = fetch_static(url)
df = parse_table(html)
dfs.append(df)
time.sleep(1) # アクセス間隔
return pd.concat(dfs, ignore_index=True)
ステップ6:出力プログラムまとめ
def run_all():
base_url = 'https://example.com/list'
df = multi_page(base_url, pages=10)
save_csv(df, 'multi_output.csv')
ベストプラクティス・運用上の注意
- 例外処理:requests.get()やSelenium起動はtry/exceptで囲む。
- ログ出力:進行状況やエラーをログに残す。
- robots.txt確認:リクエスト前に規約確認し、アクセス頻度を調整。
- ファイル命名:日付やタイムスタンプを含めると管理しやすい。
- エンコーディング:UTF‑8‑SIGでBOM付き出力し、Excel互換性を確保。
まとめと今後の展望
ここまで、Webスクレイピング→Pandasのデータフレーム化→CSVファイルに自動出力するまでの一連フローを、静的・動的サイト対応、マルチページ処理、運用上のガード(例外・ログ・robots.txt)までカバーしました。
今後は以下のような発展的取組がおすすめです:
・API取得→JSON→Pandas →CSV(公式APIがある場合)
・大規模データを扱う場合、分散処理やDaskによる高速化
・取得データの可視化やBI連携(例:Power BI、Tableau)
この構成をベースに、実務現場でのデータ自動収集・活用をぜひ進めてください。