Files
ewoooc/routes/crawler_management_routes.py
OoO d51d8031f5 refactor(routes): 遷移公開系統與 ABC 路由
ADR-017 Phase 3f-1 system sprint;新增無 prefix system_public_bp,保留公開 URL 與 backup CSRF;ABC detail 併入 sales_bp。
2026-04-29 21:22:29 +08:00

177 lines
5.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
爬蟲管理 API 路由
提供網頁介面來管理爬蟲的啟用/停用狀態
"""
from flask import Blueprint, jsonify, request, render_template, redirect, url_for
from services.crawler_config_loader import (
load_crawler_config,
update_crawler_status,
get_crawler_info,
get_enabled_crawlers,
get_paused_crawlers
)
import json
import os
from datetime import datetime
# 創建 Blueprint
crawler_bp = Blueprint('crawler_management', __name__)
CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'data', 'crawler_config.json')
@crawler_bp.route('/crawler_management')
def crawler_management_page():
"""爬蟲管理頁面 - 重定向到整合後的 settings 頁面"""
return redirect(url_for('system_public.settings'))
@crawler_bp.route('/api/crawlers', methods=['GET'])
def get_crawlers():
"""API: 取得所有爬蟲配置"""
try:
config = load_crawler_config()
return jsonify({
"status": "success",
"data": config.get('crawlers', {})
})
except Exception as e:
return jsonify({
"status": "error",
"message": str(e)
}), 500
@crawler_bp.route('/api/crawlers/<crawler_key>', methods=['GET'])
def get_crawler(crawler_key):
"""API: 取得單一爬蟲資訊"""
try:
info = get_crawler_info(crawler_key)
if info is None:
return jsonify({
"status": "error",
"message": f"爬蟲 {crawler_key} 不存在"
}), 404
return jsonify({
"status": "success",
"data": info
})
except Exception as e:
return jsonify({
"status": "error",
"message": str(e)
}), 500
@crawler_bp.route('/api/crawlers/<crawler_key>/toggle', methods=['POST'])
def toggle_crawler(crawler_key):
"""API: 切換爬蟲啟用/停用狀態"""
try:
data = request.get_json() or {}
enabled = data.get('enabled')
reason = data.get('reason', '')
if enabled is None:
return jsonify({
"status": "error",
"message": "缺少 enabled 參數"
}), 400
# 更新配置
success = update_crawler_status(crawler_key, enabled, reason)
if not success:
return jsonify({
"status": "error",
"message": "更新失敗"
}), 500
# 取得更新後的資訊
info = get_crawler_info(crawler_key)
return jsonify({
"status": "success",
"message": f"爬蟲 {info.get('name', crawler_key)}{'啟用' if enabled else '停用'}",
"data": info
})
except Exception as e:
return jsonify({
"status": "error",
"message": str(e)
}), 500
@crawler_bp.route('/api/crawlers/<crawler_key>/schedule', methods=['PUT'])
def update_crawler_schedule(crawler_key):
"""API: 更新爬蟲執行頻率"""
try:
data = request.get_json() or {}
schedule_hours = data.get('schedule_hours')
if schedule_hours is None:
return jsonify({
"status": "error",
"message": "缺少 schedule_hours 參數"
}), 400
try:
schedule_hours = int(schedule_hours)
if schedule_hours < 1 or schedule_hours > 24:
raise ValueError("執行頻率必須在 1-24 小時之間")
except ValueError as e:
return jsonify({
"status": "error",
"message": str(e)
}), 400
# 載入配置
config = load_crawler_config()
if crawler_key not in config.get('crawlers', {}):
return jsonify({
"status": "error",
"message": f"爬蟲 {crawler_key} 不存在"
}), 404
# 更新執行頻率
config['crawlers'][crawler_key]['schedule_hours'] = schedule_hours
config['metadata']['last_updated'] = datetime.now().isoformat()
# 寫回配置文件
with open(CONFIG_PATH, 'w', encoding='utf-8') as f:
json.dump(config, f, ensure_ascii=False, indent=2)
return jsonify({
"status": "success",
"message": f"執行頻率已更新為每 {schedule_hours} 小時",
"data": config['crawlers'][crawler_key]
})
except Exception as e:
return jsonify({
"status": "error",
"message": str(e)
}), 500
@crawler_bp.route('/api/crawlers/status', methods=['GET'])
def get_crawlers_status():
"""API: 取得爬蟲狀態總覽"""
try:
enabled = get_enabled_crawlers()
paused = get_paused_crawlers()
return jsonify({
"status": "success",
"data": {
"enabled_count": len(enabled),
"paused_count": len(paused),
"enabled_crawlers": list(enabled.keys()),
"paused_crawlers": list(paused.keys())
}
})
except Exception as e:
return jsonify({
"status": "error",
"message": str(e)
}), 500