#!/usr/bin/env python3 """ 獨立排程器服務 負責定時執行商品看板和活動看板的爬蟲任務 """ import os import sys import time import logging import schedule from datetime import datetime, timedelta, timezone # 確保在正確的目錄運行 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) os.chdir(BASE_DIR) sys.path.insert(0, BASE_DIR) # 設定台北時區 TAIPEI_TZ = timezone(timedelta(hours=8)) # 設定日誌 logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s', handlers=[ logging.FileHandler(os.path.join(BASE_DIR, "logs/scheduler.log"), encoding="utf-8"), logging.StreamHandler() ] ) logger = logging.getLogger("SchedulerService") # 導入爬蟲任務 from scheduler import run_momo_task, run_edm_task, run_festival_task, run_auto_import_task def safe_task_wrapper(task_func, task_name): """安全的任務包裝器,捕獲異常避免排程中斷""" def wrapper(): try: timestamp = datetime.now(TAIPEI_TZ).strftime('%Y-%m-%d %H:%M:%S') logger.info(f"⏰ [{timestamp}] 開始執行任務: {task_name}") task_func() logger.info(f"✅ [{timestamp}] 任務完成: {task_name}") except Exception as e: logger.error(f"❌ 任務執行失敗: {task_name} | Error: {e}", exc_info=True) return wrapper def main(): """主程序""" logger.info("=" * 60) logger.info("🚀 WOOO TECH 排程器服務啟動") logger.info("=" * 60) # 設定排程任務 # V-Opt 2026-01-14: 商品看板和 EDM 需每小時執行以監控價格變化 # 商品看板(主站爬蟲)- 每 1 小時執行 schedule.every(1).hours.do(safe_task_wrapper(run_momo_task, "商品看板爬蟲")) logger.info("📅 已設定:商品看板爬蟲 - 每 1 小時執行一次") # EDM 限時搶購看板 - 每 1 小時執行 schedule.every(1).hours.do(safe_task_wrapper(run_edm_task, "EDM 限時搶購爬蟲")) logger.info("📅 已設定:EDM 限時搶購爬蟲 - 每 1 小時執行一次") # 購物節活動看板 - 每 6 小時執行 schedule.every(6).hours.do(safe_task_wrapper(run_festival_task, "購物節活動爬蟲")) logger.info("📅 已設定:購物節活動爬蟲 - 每 6 小時執行一次") # Google Drive 自動匯入 - 每 30 分鐘執行 schedule.every(30).minutes.do(safe_task_wrapper(run_auto_import_task, "Google Drive 自動匯入")) logger.info("📅 已設定:Google Drive 自動匯入 - 每 30 分鐘執行一次") logger.info("=" * 60) logger.info("✅ 所有排程任務已設定完成,開始監聽...") logger.info("=" * 60) # 主循環 try: while True: schedule.run_pending() time.sleep(1) except KeyboardInterrupt: logger.info("🔌 收到中斷信號,排程器服務正在關閉...") except Exception as e: logger.error(f"🚨 排程器服務異常: {e}", exc_info=True) sys.exit(1) if __name__ == "__main__": main()