forked from ZheLeiQIAN/Insight-Agent
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscheduler.py
More file actions
150 lines (126 loc) · 5.45 KB
/
Copy pathscheduler.py
File metadata and controls
150 lines (126 loc) · 5.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python3
"""Insight Agent 定时调度器 — 后台自动爬取+分析"""
import sys
import json
import time
import threading
import logging
from pathlib import Path
from datetime import datetime, timedelta
PROJECT_ROOT = Path(__file__).parent
sys.path.insert(0, str(PROJECT_ROOT))
from config import OUTPUT_DIR, CRAWLER_SCRIPTS, LLM_API_KEY
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
SCHEDULE_FILE = OUTPUT_DIR / ".schedule.json"
class Scheduler:
"""轻量级定时任务调度"""
def __init__(self):
self.jobs = self._load()
def _load(self) -> list:
if SCHEDULE_FILE.exists():
try:
return json.loads(SCHEDULE_FILE.read_text())
except json.JSONDecodeError as e:
logger.error(f"调度文件格式错误: {e}")
return []
except Exception as e:
logger.error(f"加载调度文件失败: {e}")
return []
return []
def _save(self):
SCHEDULE_FILE.write_text(json.dumps(self.jobs, ensure_ascii=False, indent=2))
def add(self, crawler: str, params: dict, interval_hours: int = 24, models: list = None):
"""添加定时任务"""
job = {
"id": datetime.now().strftime("%Y%m%d%H%M%S"),
"crawler": crawler,
"params": params,
"interval_hours": interval_hours,
"models": models or ["all"],
"last_run": None,
"next_run": datetime.now().isoformat(),
"enabled": True,
}
self.jobs.append(job)
self._save()
return job["id"]
def list_jobs(self) -> list:
"""列出所有任务"""
now = datetime.now()
result = []
for j in self.jobs:
status = "⏳" if j["enabled"] else "⏸"
next_run = j.get("next_run", "?")[:16]
last = j.get("last_run", "从未")[:16] if j.get("last_run") else "从未"
result.append({
"id": j["id"],
"status": status,
"platform": CRAWLER_SCRIPTS.get(j["crawler"], {}).get("platform", j["crawler"]),
"params": str(j["params"])[:40],
"interval": f"{j['interval_hours']}h",
"last": last,
"next": next_run,
})
return result
def remove(self, job_id: str):
self.jobs = [j for j in self.jobs if j["id"] != job_id]
self._save()
def run_now(self) -> list:
"""立即执行所有到期任务"""
results = []
now = datetime.now()
for job in self.jobs:
if not job["enabled"]:
continue
next_run = datetime.fromisoformat(job["next_run"]) if job.get("next_run") else now
if now < next_run:
continue
try:
from main import load_data
from crawlers.runner import run_crawler, get_latest_output_files
from analysis.quantitative import basic_stats, sentiment_analysis, word_frequency
from report.generator import generate_report
output_dir = run_crawler(job["crawler"], job["params"])
files = get_latest_output_files(output_dir)
if files:
data = load_data(files[0])
if data:
results_data = {}
for m in ["basic_stats", "sentiment", "word_freq"]:
try:
fn = {"basic_stats": basic_stats, "sentiment": sentiment_analysis, "word_freq": word_frequency}[m]
results_data[m] = fn(data, files[0])
except Exception as e:
logger.warning(f"分析模型 {m} 失败: {e}")
continue
crawler_info = {"platform": CRAWLER_SCRIPTS[job["crawler"]]["platform"], "name": files[0].name}
report_path = generate_report(crawler_info, results_data, files[0], output_dir)
results.append({"job": job["id"], "status": "✅", "report": str(report_path)})
else:
results.append({"job": job["id"], "status": "⚠️ 无数据"})
else:
results.append({"job": job["id"], "status": "⚠️ 无输出"})
job["last_run"] = now.isoformat()
job["next_run"] = (now + timedelta(hours=job["interval_hours"])).isoformat()
except Exception as e:
results.append({"job": job["id"], "status": f"❌ {e}"})
job["last_run"] = now.isoformat()
self._save()
return results
def start_scheduler(interval_seconds: int = 600):
"""后台启动调度器(每10分钟检查一次)"""
scheduler = Scheduler()
print(f"📅 调度器已启动(每{interval_seconds}秒检查)")
print(f" 当前任务: {len(scheduler.jobs)} 个")
def loop():
while True:
time.sleep(interval_seconds)
results = scheduler.run_now()
if results:
for r in results:
print(f" [{datetime.now():%H:%M}] {r['status']} {r['job']}")
thread = threading.Thread(target=loop, daemon=True, name="scheduler")
thread.start()
return scheduler