| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- # -*- coding: utf-8 -*-
- # Author : Charley
- # Python : 3.12.10
- # Date : 2026/08/21
- """集物星球爬虫一键启动:把 5 个常驻任务各自拉成独立子进程并守护(崩溃自动重启)。
- 服务器部署只跑这一个文件即可:`python run_all.py`。
- 每个任务是独立子进程(各自维护自己的 schedule 定时与日志、互不干扰),本脚本轮询它们的存活状态,
- 发现哪个退出就隔 RESTART_DELAY 秒重启那个(无人值守长跑用)。
- 想单独调试某个任务时,仍可直接 `python jw_xxx.py` 单跑,不必用本文件。
- """
- import os
- import sys
- import time
- import subprocess
- from loguru import logger
- # 待启动的常驻任务:(展示名, 脚本文件)
- TASKS = [
- ("在售抓取", "jw_onsale_spider.py"), # 每天 09/15/20/01 四档
- ("已售抓取", "jw_sold_spider.py"), # 每天 08:00(含拆卡报告/购买记录)
- ("在售日报", "jw_onsale_report.py"), # 每天 09/15/20/01 四档发企微
- ("已售日报", "jw_sold_report.py"), # 每天 09:10 发企微
- ("在售监控", "jw_onsale_alert.py"), # 常驻轮询、上架/过半/结束提醒
- ]
- RESTART_DELAY = 5 # 子进程退出后重启前的等待秒数
- CHECK_INTERVAL = 10 # 存活巡检间隔秒数
- BASE_DIR = os.path.dirname(os.path.abspath(__file__))
- logger.remove()
- # logger.add(sys.stderr, level="INFO", format="[{time:YYYY-MM-DD HH:mm:ss}] {level} {message}")
- logger.add("./logs/run_all_{time:YYYYMMDD}.log", encoding="utf-8", rotation="00:00",
- format="[{time:YYYY-MM-DD HH:mm:ss.SSS}] {level} {message}", level="INFO", retention="7 day")
- def start_one(script: str) -> subprocess.Popen:
- """用当前 Python 解释器在项目目录下拉起一个任务子进程。
- Args:
- script (str): 任务脚本文件名(相对项目目录)。
- Returns:
- subprocess.Popen: 已启动的子进程句柄。
- """
- return subprocess.Popen([sys.executable, os.path.join(BASE_DIR, script)], cwd=BASE_DIR)
- def main() -> None:
- """启动全部任务并守护:巡检存活,退出的子进程自动重启(无限守护)。"""
- procs = {name: [script, start_one(script)] for name, script in TASKS}
- logger.success(f"已启动 {len(procs)} 个任务:{', '.join(procs.keys())}")
- try:
- while True:
- for name, item in procs.items():
- script, proc = item
- if proc.poll() is not None: # 该子进程已退出 → 重启
- logger.warning(f"[{name}] {script} 退出(code={proc.returncode}),{RESTART_DELAY}s 后重启")
- time.sleep(RESTART_DELAY)
- item[1] = start_one(script)
- logger.info(f"[{name}] {script} 已重启")
- time.sleep(CHECK_INTERVAL)
- except KeyboardInterrupt: # Ctrl+C:优雅关掉所有子进程
- logger.info("收到退出信号,正在关闭所有子进程" + "." * 10)
- for name, (script, proc) in procs.items():
- proc.terminate()
- logger.info("已全部关闭")
- if __name__ == "__main__":
- main()
|