"""浏览采集:取消标记与增量落盘(供 GUI 停止后返回已采数据)。""" from __future__ import annotations import json import os from pathlib import Path from typing import Any def _path_from_env(key: str) -> Path | None: raw = (os.environ.get(key) or "").strip() return Path(raw) if raw else None def clear_session() -> None: """重置增量落盘;取消标记由 GUI 在 browse 会话中单独管理。""" partial = _path_from_env("XHS_PARTIAL_FEEDS_FILE") if partial: partial.parent.mkdir(parents=True, exist_ok=True) partial.write_text(json.dumps({"feeds": []}, ensure_ascii=False), encoding="utf-8") def request_cancel() -> None: cancel = _path_from_env("XHS_CANCEL_FILE") if cancel: cancel.parent.mkdir(parents=True, exist_ok=True) cancel.write_text("1", encoding="utf-8") def is_cancelled() -> bool: cancel = _path_from_env("XHS_CANCEL_FILE") return bool(cancel and cancel.exists()) def persist_collected(collected: dict[str, dict]) -> None: partial = _path_from_env("XHS_PARTIAL_FEEDS_FILE") if not partial: return payload = {"feeds": list(collected.values())} partial.parent.mkdir(parents=True, exist_ok=True) partial.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8") def load_partial_feeds() -> list[dict[str, Any]]: partial = _path_from_env("XHS_PARTIAL_FEEDS_FILE") if not partial or not partial.is_file(): return [] try: data = json.loads(partial.read_text(encoding="utf-8")) except (json.JSONDecodeError, OSError): return [] feeds = data.get("feeds") if isinstance(data, dict) else data return feeds if isinstance(feeds, list) else [] def raise_if_cancelled() -> None: from .errors import BrowseCancelledError if is_cancelled(): raise BrowseCancelledError()