diff --git a/README.md b/README.md index 32c8461..b103c83 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# 0.0.4 +- 超时守护 # 0.0.3 - 修复bug # 0.0.2 diff --git a/spider/main.py b/spider/main.py index 8050ad3..23c7460 100644 --- a/spider/main.py +++ b/spider/main.py @@ -491,21 +491,42 @@ def close_and_delete_browser(browser_id: str) -> None: except Exception as e: logger.warning(f"删除浏览器失败或已删除: {browser_id} - {e}") +def timeout_guard(browser_id: str, done_event: threading.Event, timeout_sec: float = 300.0) -> None: + """ + 任务超时守护:超过指定时间未完成则关闭并删除对应指纹浏览器 + + 参数: + browser_id: 指纹浏览器ID + done_event: 任务完成事件,完成则终止守护 + timeout_sec: 超时时长(秒),默认 300 秒 + """ + finished = done_event.wait(timeout=timeout_sec) + if finished: + return + logger.warning(f"任务超过 {timeout_sec} 秒未完成,开始清理浏览器: {browser_id}") + try: + close_and_delete_browser(browser_id) + except Exception as e: + logger.warning(f"超时清理浏览器失败: {browser_id} - {e}") def run_task_with_proxy(proxy: str, stop_event: threading.Event) -> None: """ - 使用代理创建指纹浏览器、执行自动化,并在结束后清理 + 使用代理创建指纹浏览器、执行自动化,并在结束后清理;内置 5 分钟超时守护 参数: proxy: 代理字符串 """ browser_id: str | None = None + done_event = threading.Event() try: created = create_fingerprint_browser(proxy) if not created: return browser_id, http = created logger.info(f"browser_id: {browser_id} http: {http}") + # 启动超时守护线程(5分钟) + guard = threading.Thread(target=timeout_guard, args=(browser_id, done_event, 300.0), daemon=True) + guard.start() if stop_event.is_set(): return auto = Auto(http=http) @@ -520,6 +541,11 @@ def run_task_with_proxy(proxy: str, stop_event: threading.Event) -> None: except Exception as e: logger.error(f"执行任务异常: {e}") finally: + # 标记任务已完成,终止守护线程 + try: + done_event.set() + except Exception: + pass if browser_id: try: close_and_delete_browser(browser_id)