自動化 Python 案例分析

Python 爬蟲實戰:自動監控競品價格與動向

2026年5月1日 約 10 分鐘閱讀 Digitools Studio

這是一個來自真實客戶需求的案例:電商業者每天需要追蹤 5 個競品網站的特定商品定價,過去由業務人員手動查看記錄,費時費力且容易遺漏。我們為他們建立了一套 Python 自動化監控系統,每天定時執行,發現價格異動即透過 LINE 推播通知。

📋 本文技術棧:Python 3.11 / requests / BeautifulSoup4 / pandas / APScheduler / LINE Messaging API

需求分析與架構設計

在動手寫程式前,我們先和客戶確認以下幾點:

確認後,整體架構如下:爬蟲抓取 → 解析比對 → 存入 CSV → 差異通知。

建立基礎爬蟲

安裝必要套件:

pip install requests beautifulsoup4 pandas apscheduler

基礎爬蟲結構:

import requests
from bs4 import BeautifulSoup

HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                  'AppleWebKit/537.36 Chrome/122.0 Safari/537.36'
}

def fetch_price(url: str, selector: str) -> str | None:
    """從指定 URL 抓取價格文字"""
    try:
        res = requests.get(url, headers=HEADERS, timeout=10)
        res.raise_for_status()
        soup = BeautifulSoup(res.text, 'html.parser')
        el = soup.select_one(selector)
        return el.get_text(strip=True) if el else None
    except Exception as e:
        print(f"[ERROR] {url} → {e}")
        return None

⚠️ 注意:部分網站會擋爬蟲,需加入延遲(time.sleep())或使用 rotating proxy。永遠先確認目標網站的 robots.txt 與服務條款。

設定監控目標

將競品清單定義在 JSON 或 Python dict 中,方便日後維護:

TARGETS = [
    {
        "name": "競品 A — 32吋螢幕",
        "url": "https://example-shop-a.com/product/monitor-32",
        "selector": ".price-main",
    },
    {
        "name": "競品 B — 32吋螢幕",
        "url": "https://example-shop-b.com/items/12345",
        "selector": "#pdp-price span",
    },
]

比對與存儲歷史紀錄

每次執行時,把新舊價格存到 CSV,方便日後分析趨勢:

import pandas as pd
from datetime import datetime
import os

CSV_FILE = 'price_history.csv'

def save_and_compare(name: str, new_price: str) -> dict:
    """存新資料並回傳是否有變動"""
    now = datetime.now().strftime('%Y-%m-%d %H:%M')
    row = {'time': now, 'name': name, 'price': new_price}

    df_new = pd.DataFrame([row])

    if os.path.exists(CSV_FILE):
        df = pd.read_csv(CSV_FILE)
        # 取上次同商品的最後一筆
        prev = df[df['name'] == name].tail(1)
        old_price = prev['price'].values[0] if len(prev) else None
        changed = (old_price != new_price)
        df = pd.concat([df, df_new], ignore_index=True)
    else:
        df = df_new
        old_price = None
        changed = False

    df.to_csv(CSV_FILE, index=False)
    return {'changed': changed, 'old': old_price, 'new': new_price}

LINE 推播通知

價格有變動時,透過 LINE Messaging API 推播給指定用戶或群組:

import requests as req

LINE_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN'
LINE_USER_ID = 'Uxxxxxxxxxxxxxxxxx'  # 目標用戶的 userId

def notify_line(message: str):
    req.post(
        'https://api.line.me/v2/bot/message/push',
        headers={
            'Authorization': f'Bearer {LINE_TOKEN}',
            'Content-Type': 'application/json'
        },
        json={
            'to': LINE_USER_ID,
            'messages': [{'type': 'text', 'text': message}]
        }
    )

排程執行(APScheduler)

設定每天早上 9 點自動執行一次:

from apscheduler.schedulers.blocking import BlockingScheduler

def daily_check():
    alerts = []
    for target in TARGETS:
        price = fetch_price(target['url'], target['selector'])
        if price:
            result = save_and_compare(target['name'], price)
            if result['changed']:
                alerts.append(
                    f"⚠️ {target['name']}\n"
                    f"原價:{result['old']}\n"
                    f"現價:{result['new']}"
                )
    if alerts:
        notify_line('📊 競品價格異動通知\n\n' + '\n\n'.join(alerts))
    else:
        print('[OK] 今日無價格變動')

scheduler = BlockingScheduler()
scheduler.add_job(daily_check, 'cron', hour=9, minute=0)
scheduler.start()

實際成效

上線 3 個月後的結果:

這套系統可以很容易地擴展:加更多商品、加更多通知管道(Email / Slack)、加入趨勢圖表、或把資料存到 Google Sheets 讓非技術人員查看。如果你有類似需求,歡迎聯繫我們討論。

D

Digitools Studio

有競品監控、資料自動化的需求?我們提供完整的 Python 爬蟲與自動化系統開發服務,初次諮詢免費。