第5章(実践開発:スクレイピング・データ分析・生成AI活用)で学んだWebスクレイピング技術を応用し、競合ECサイトやターゲット商品の価格変動・在庫状況を自動パトロールし、セール開始や価格改定を検知してDiscordへ自動通知するボットを構築します。
1. システムの設計と要件
本自動化ツールは、以下の実務的な技術要素を組み合わせて実現します。
- Playwright(ブラウザ自動化): JavaScriptによって動的に価格が書き換わるモダンなECサイトや、ログインが必要なページに対応。
- BeautifulSoup4(HTML解析): 抽出したHTMLから、商品名・価格・在庫ステータスを高速にパース。
- Discord Webhook(通知連携): 差分やターゲット価格を下回ったイベントを即座にチャットへプッシュ通知。
- cron(定期実行): サーバー上で定期的にスクリプトを自動実行し、24時間の監視体制を構築。
2. 実装コード(ec_price_watcher.py)
以下のコードを ec_price_watcher.py というファイル名で保存し、手元で動作させてみましょう(事前に pip install playwright beautifulsoup4 requests および playwright install が必要です)。
Python
import asyncio
import requests
from bs4 import BeautifulSoup
from playwright.async_api import async_playwright
# --- 設定値 ---
TARGET_URL = "https://example.com/sample-product" # 監視対象のECサイトURL
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/your_webhook_id/your_token"
TARGET_PRICE_THRESHOLD = 5000 # この金額を下回ったら特別通知する閾値
async def fetch_dynamic_html(url: str) -> str:
"""Playwrightを用いてJavaScript描画後のHTMLを取得する (第5章)"""
async with async_playwright() as p:
# ヘッドレスモードでブラウザを起動
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
# ページにアクセスしてネットワークが落ち着くまで待機
await page.goto(url, wait_until="networkidle")
html_content = await page.content()
await browser.close()
return html_content
def parse_product_info(html: str):
"""BeautifulSoupで商品名と価格を抽出する (第5章)"""
soup = BeautifulSoup(html, "html.parser")
# サイトのHTML構造に合わせてセレクタを調整
title_elem = soup.select_one(".product-title")
price_elem = soup.select_one(".product-price")
stock_elem = soup.select_one(".stock-status")
title = title_elem.get_text(strip=True) if title_elem else "商品名不明"
price_text = price_elem.get_text(strip=True) if price_elem else "0"
# 価格文字列から数値のみを抽出 (例: "¥4,800(税込)" -> 4800)
import re
numeric_price = int("".join(re.findall(r'\d+', price_text)))
stock_status = stock_elem.get_text(strip=True) if stock_elem else "在庫あり"
return {
"title": title,
"price": numeric_price,
"stock": stock_status
}
def send_discord_notification(message: str):
"""Discord Webhook経由でメッセージをプッシュ通知する"""
payload = {"content": message}
try:
response = requests.post(DISCORD_WEBHOOK_URL, json=payload)
response.raise_for_status()
print("📢 Discord通知を送信しました。")
except requests.exceptions.RequestException as e:
print(f"❌ Discord通知の送信に失敗しました: {e}")
async def main():
print(f"🔍 競合ECサイトのリサーチを開始します: {TARGET_URL}")
try:
# 1. 動的HTMLの取得
html = await fetch_dynamic_html(TARGET_URL)
# 2. データの解析
product = parse_product_info(html)
print(f"取得結果: {product['title']} / ¥{product['price']:,} / {product['stock']}")
# 3. 条件判定と通知
if product["price"] <= TARGET_PRICE_THRESHOLD:
msg = f"🔥 【価格下落アラート】\n監視対象商品が目標価格を下回りました!\n商品名: {product['title']}\n価格: ¥{product['price']:,}\nURL: {TARGET_URL}"
send_discord_notification(msg)
else:
print(f"現在の価格(¥{product['price']:,})は目標値(¥{TARGET_PRICE_THRESHOLD:,})の範囲内です。")
except Exception as e:
print(f"❌ スクレイピング処理中にエラーが発生しました: {e}")
if __name__ == "__main__":
asyncio.run(main())
3. サーバーでの定期実行(cron)設定
第8章(付録2)で解説したお名前.comサーバーやLinux環境のcronを使い、このスクリプトを1日数回自動実行させます。
Bash
# crontab -e で編集画面を開き、以下を追加(例: 3時間おきに実行)
0 */3 * * * /home/username/public_html/python-lab.net/venv/bin/python3 /home/username/public_html/python-lab.net/ec_price_watcher.py > /dev/null 2>&1
まとめ
本記事では、Playwrightによる動的ブラウザ操作とBeautifulSoupによるHTML解析を組み合わせ、競合ECサイトの価格変動を自動検知してDiscordへ通知する実用的なBotの構築を学びました。

コメント