# 返利班浏览器适配。共享协议在 rpa_browser,这里只留 Chrome junction / 端口差异。 # # RPA_USE_USER_CHROME 打开时 profile 走仓库外 daily-chrome junction(不要 resolve),调试口 9222。 # 未开时 REBATE_* 节点共用查号会话目录和 9335 口。 from __future__ import annotations import os import subprocess import sys from pathlib import Path _REPO_ROOT = Path(__file__).resolve().parents[1] if str(_REPO_ROOT) not in sys.path: sys.path.insert(0, str(_REPO_ROOT)) from rpa_browser.adapter import ( # noqa: E402 ApaBrowserAdapter as _SharedAdapter, REPO_ROOT, launch_independent_chrome, resolve_chrome_profile_base, wait_debug_port, wait_devtools_port, ) _USER_CHROME_PORT = 9222 _FLOW_DEBUG_PORTS = { "REBATE_FIND": 9335, "default": 9335, } __all__ = [ "ApaBrowserAdapter", "REPO_ROOT", "chrome_debug_port", "chrome_session_flow", "resolve_chrome_profile_base", "resolve_chrome_profile_dir", "use_user_chrome", "user_chrome_profile_dir", "user_chrome_real_profile_dir", "wait_debug_port", "wait_devtools_port", ] # 是否改用本机日常 Chrome 用户目录(RPA_USE_USER_CHROME)。 def use_user_chrome() -> bool: raw = (os.getenv("RPA_USE_USER_CHROME") or "").strip().lower() return raw in {"1", "true", "yes", "on"} # 本机 Chrome 默认 User Data 目录(Windows LOCALAPPDATA)。 def user_chrome_real_profile_dir() -> Path: return (Path(os.environ.get("LOCALAPPDATA", "")) / "Google" / "Chrome" / "User Data").resolve() # junction 不存在时用 mklink /J 指向真实 User Data。已存在则不动。非 Windows 只保证父目录。 def _ensure_user_chrome_junction(link: Path, real: Path) -> None: if link.exists(): return link.parent.mkdir(parents=True, exist_ok=True) if os.name != "nt": return subprocess.run( ["cmd.exe", "/c", "mklink", "/J", str(link), str(real)], check=False, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) # 日常 Chrome 的调试入口目录。Chrome 禁止在默认 User Data 上开调试口,用仓库外 junction。 # # 返回值不要 resolve,否则又变回默认路径。 def user_chrome_profile_dir() -> Path: link = REPO_ROOT.parent / "rpa-chrome-profile" / "daily-chrome" real = user_chrome_real_profile_dir() _ensure_user_chrome_junction(link, real) return link # REBATE_* 节点共用查号已登录的 Chrome 会话名。 def chrome_session_flow(flow: str) -> str: name = (flow or "default").strip() or "default" if name.startswith("REBATE"): return "REBATE_FIND" return name # 本班次 Chrome 用户目录。用户 Chrome 走 junction;否则按查号会话分子目录。 def resolve_chrome_profile_dir( flow: str = "default", requested: str | None = None, *, repo_root: Path | None = None, ) -> Path: if use_user_chrome(): return user_chrome_profile_dir() base = resolve_chrome_profile_base(requested, repo_root=repo_root) session = chrome_session_flow(flow) safe = "".join(ch if ch.isalnum() or ch in "-_" else "_" for ch in session) return (base / (safe or "default")).resolve() # 本班次调试口。环境变量优先;用户 Chrome 9222;否则查号会话 9335。 def chrome_debug_port(flow: str = "default") -> int: raw = (os.getenv("RPA_CHROME_DEBUG_PORT") or "").strip() if raw: try: return int(raw) except ValueError: pass if use_user_chrome(): return _USER_CHROME_PORT session = chrome_session_flow(flow) return _FLOW_DEBUG_PORTS.get(session, 9335) # 在已打开的窗口里切到采购协议页签。找不到返回 False。 def _focus_agreement_tab(driver) -> bool: try: handles = list(driver.window_handles) except Exception: return False for handle in handles: try: driver.switch_to.window(handle) href = str(driver.current_url or "") title = str(driver.title or "") except Exception: continue if "procurementAgree" in href or "采购协议" in title: return True return False # 返利班浏览器适配器。用户 Chrome junction / 端口按本模块解析。 class ApaBrowserAdapter(_SharedAdapter): # 本班次 Chrome 用户目录:用户 Chrome 走 junction,否则按查号会话。 def _profile_dir(self) -> Path: return resolve_chrome_profile_dir(self._flow) # 本班次调试口:用户 Chrome 9222,否则查号会话 9335。 def _debug_port(self) -> int: return chrome_debug_port(self._flow) # 是否按日常 Chrome 用户目录重开并恢复标签。 def _restore_session(self) -> bool: return use_user_chrome() # 用户 Chrome 时切到已打开的采购协议页。 def _focus_existing_tab(self, driver) -> bool: if not use_user_chrome(): return False return _focus_agreement_tab(driver) # 独立进程拉起 Chrome 再附着,Python 退出后窗口还在。 def _launch_driver(self, service, profile_dir: Path, port: int): return launch_independent_chrome( service, profile_dir, port, restore_session=use_user_chrome(), )