はじめに
Pythonスクレイピング 前編
はじめに:価格調査ツールを自作しようとして0件だった話
こんにちは、ニンジンです🥕
この記事は、Pythonで「Webサイトから情報を自動収集するツール」を作ろうとして、いきなり 取得件数0件 の壁にぶつかった記録です。RequestsとSeleniumという定番の2つで挑んで、どちらも0件になった理由と、スクレイピングを始める前に知っておくべき「作法」をまとめます。
この記事で分かること
- スクレイピング前に確認する3つの作法(robots.txt・待機時間・練習用サイト)
- Requests + BeautifulSoup で記事一覧を取ろうとすると0件になる理由(JavaScript描画)
- Selenium でブラウザを動かしても、クラス名・構造の問題で苦戦する理由
- 「どんなサイトからでも取れる汎用ツール」が現実的でない理由
スクレイピング前に確認する3つの作法
スクレイピングは強力ですが、相手のサーバーに負担をかける行為でもあります。まず守るべき3つを確認します。
① サイトの意思表示「robots.txt」を確認する
Webサイトには「ここはプログラム(ロボット)でアクセスしてよい/ダメ」という意思表示を書いたファイル robots.txt があります。URLの末尾に /robots.txt を付けてアクセスすると読めます。
User-agent: *(すべてのロボット向け)に対して Disallow: /admin/ のような記述があれば、その場所へのアクセスは控えます。技術的な強制力はありませんが、エンジニア同士の暗黙のルールです。
② アクセス間隔(time.sleep)を空ける
1秒に何十回もアクセスするのは、実質的にDoS攻撃と同じです。import time して time.sleep(3) のような待機を必ず入れ、「1秒に1回以上は相手への攻撃になり得る」という意識を持ちます。
③ 練習は「練習用サイト」で行う
いきなり商用サイトで試すのはマナー違反です。スクレイピング練習用に公開されている「砂場(サンドボックス)」を使います。定番は Books to Scrape(books.toscrape.com)や Quotes to Scrape です。ここで基礎を固めてから実戦に進みます。
Requests + BeautifulSoup 編:自分のブログを取得してみる
作法を確認したところで、自分のブログ(https://py-vbalab.com)を対象に、軽量・高速な定番コンビ「Requests + BeautifulSoup」で挑みます。
インストール
テストコード
import requests
from bs4 import BeautifulSoup
import openpyxl
from datetime import datetime
import time
# 1. ターゲットURL
TARGET_URL = "https://py-vbalab.com/"
def get_blog_data():
# 相手サーバー(自分のブログ)への負荷軽減
time.sleep(3)
try:
response = requests.get(TARGET_URL)
response.encoding = response.apparent_encoding # 文字化け防止
soup = BeautifulSoup(response.text, 'html.parser')
# 記事カードの塊を特定(WordPressなどの一般的な構造を想定)
# ※実際のHTML構造に合わせて 'entry-card' 等のクラス名は調整が必要な場合があります
articles = soup.find_all('div', class_='entry-card-content')
print(f"取得できた記事数: {len(articles)}")
data_list = []
for article in articles:
# タイトルの取得
title_tag = article.find('h2')
title = title_tag.text.strip() if title_tag else "タイトルなし"
# URLの取得
link_tag = article.find('a')
url = link_tag['href'] if link_tag else "URLなし"
# 投稿日の取得(timeタグや特定クラスのspanを想定)
date_tag = article.find('span', class_='post-date')
date_text = date_tag.text.strip() if date_tag else "日付不明"
data_list.append([date_text, title, url])
return data_list
except Exception as e:
print(f"エラーが発生しました: {e}")
return []
def save_to_excel(data):
# Excel新規作成
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "記事リスト"
# ヘッダー
ws.append(["投稿日", "記事タイトル", "URL"])
# データの書き込み
for row in data:
ws.append(row)
# ファイル名に実行日時を付けて保存
file_name = f"BlogList_{datetime.now().strftime('%Y%m%d_%H%M')}.xlsx"
wb.save(file_name)
print(f"✅ Excelファイル '{file_name}' を作成しました!")
# 実行
if __name__ == "__main__":
print("データ取得中...")
blog_data = get_blog_data()
if blog_data:
save_to_excel(blog_data)
else:
print("データが取得できませんでした。HTML構造を確認してください。")結果:取得できた記事数 0
原因は、最近のモダンなブログテーマ(SWELLなど)が採用している 遅延読み込み(Lazy Load) でした。記事一覧のデータがHTMLに直接書かれておらず、JavaScriptで後から描画される仕組みだったため、requests.get() が受け取る素のHTMLには記事がまだ存在しなかったのです。
Selenium 編:本物のブラウザを動かしてみる
「素のHTMLがダメなら、本物のブラウザを動かせばいい」——次に投入したのは、ブラウザを自動操作する Selenium です。
インストール
テストコード
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
options = Options()
driver = webdriver.Chrome(options=options)
try:
print("ブラウザを起動してアクセス中...")
driver.get("https://py-vbalab.com/")
# 読み込み待ち(10秒くらい余裕を持たせてみる)
time.sleep(8)
# --- 修正ポイント:複数の探し方を試す ---
print("要素を探しています...")
# 案A: SWELLの標準的なタイトルクラス
elements = driver.find_elements(By.CSS_SELECTOR, ".p-postList__title")
# 案B: もしAがダメなら、記事カード内のh2を全部取る
if len(elements) == 0:
elements = driver.find_elements(By.CSS_SELECTOR, "h2.post_title, .c-postitem__title, .p-postList__item h2")
print(f"取得できた記事数: {len(elements)}")
for i, el in enumerate(elements):
# 画面に映っていないとテキストが取れない場合があるので、取得方法を工夫
title = el.get_attribute("textContent").strip()
print(f"{i+1}: {title}")
finally:
print("3秒後に終了します...")
time.sleep(3)
driver.quit()結果:取得できた記事数 0
前編のまとめ:スクレイピングの甘くない現実
当初は「どんなサイトからでも情報を引っこ抜ける汎用ツール」を夢見ていましたが、現実はそう甘くありませんでした。
- サイトごとにHTMLの構造が違うため、汎用化が難しい
- モダンなサイトはJavaScriptで後からデータを描画するため、単純な取得ができない
- 無理なスクレイピングは、相手にも自分にもリスクがある
- サイトのデザイン変更のたびにコードを直し続ける、運用の壁
「個人では無理なのか」と諦めかけたとき、HTMLを解析しなくてもデータを取れる「裏口」を見つけました。後編で解説します。
続きの記事
よくある質問(FAQ)
Qrobots.txt に Disallow が無ければ、何をスクレイピングしてもよいのですか?
Arobots.txtは技術的な許可ではなく、あくまで運営者の意思表示です。サイトの利用規約、著作権、サーバーへの負荷は別の問題として残ります。個人利用の範囲で、十分な間隔を空けて行うのが前提です。
QRequestsで取得件数が0件になるのはなぜですか?
A最近のブログテーマ(SWELLなど)は、記事一覧をJavaScriptで後から描画します。requests.get()が受け取るのは描画前の素のHTMLなので、その時点では記事の要素がまだ存在せず0件になります。
QSeleniumを使えば必ず取得できますか?
Aブラウザを実際に動かすのでJavaScript描画には対応できます。ただし、狙う要素のクラス名や構造がテーマの更新で変わると壊れるため、動いても「メンテナンスし続ける前提」になります。
Qtime.sleep は何秒に設定すればよいですか?
A1リクエストにつき最低1秒、できれば3秒以上を空けます。相手が個人運営の小規模サイトなら、さらに長めにするのが安全です。
Q練習用サイトは他にもありますか?
A同じ運営の Quotes to Scrape(quotes.toscrape.com)があります。HTTPの挙動そのものを確認したいときは httpbin.org も便利です。
Q会社のPCでスクレイピングしてもよいですか?
A会社のネットワークやセキュリティポリシー次第です。まず情報システム部門に確認してください。学習目的なら、自分のブログや練習用サイトで行うのが無難です。
Follow me on X
本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕
@ninjin_py_vba をフォローシリーズ記事一覧
電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。
-
FILE.01 — IoT
Raspberry Pi Pico W × GASラズパイPico W×GASで自作!「LINEで動く温湿度&スマートリモコン」完全ロードマップ
「外出中のペットの室温が心配…」そんな思いからスタートしたIoT自作プロジェクトの総集編。温湿度監視からエアコン遠隔操作まで、仕組みをゼロから作りたい方のための全5回の開発記録です。
シリーズを読む -
FILE.02 — CNC
Arduino × レーザー刻印CNCCNC自作シリーズ
高精度な加工を目指し、本格的な自作CNC製作に挑戦中。現在は基幹パーツであるオリエンタルモーターの納品を待つ「設計・準備編」を公開。ハードとソフトの両面から、理想のマシンを形にする過程をリアルタイムにお届けします。
シリーズを読む -
FILE.03 — XY軸制御
Raspberry Pi × ステッピングモーターXYテーブルシリーズ
Raspberry Piとステッパモーターを使い、ゼロから2軸制御に挑む記録。OS設定から回路設計、多軸制御のPythonコードまで、躓きやすいポイントを徹底図解。電子工作初心者が「動く感動」を味わうための実戦ガイドです。
シリーズを読む -
FILE.04 — 業務自動化
Python × Excel × CustomTkinter【Python開発記】NINJIN Mail制作記
PythonとExcelを連携させ、実務で即戦力となるメール送信ツールを開発。CustomTkinterによるUI構築や、ミスを防ぐテンプレート活用術など、現場の「痒い所に手が届く」自動化ノウハウを細部まで丁寧に解説します。
シリーズを読む -
FILE.05 — 業務自動化
Python × Excel × GUIアプリ化Invoice Maker(請求書・見積書自動作成)
手作業の請求書作成から卒業!PythonでExcelデータを読み込み一括PDF化する「Invoice_Maker」の作り方を全3回で解説。基本ロジックからGUIアプリ化まで、実務で役立つ自動化ノウハウが満載です。
シリーズを読む








コメント