diff --git a/browser_automation.py b/browser_automation.py index 90a7cd5..0f3c3ba 100644 --- a/browser_automation.py +++ b/browser_automation.py @@ -407,6 +407,11 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage: co.set_argument('--no-sandbox') # 服务器环境需要 co.set_argument('--disable-blink-features=AutomationControlled') # 隐藏自动化特征 + # 并发模式:为每个实例创建独立的用户数据目录 + import tempfile + temp_user_data = tempfile.mkdtemp(prefix="chrome_worker_") + co.set_argument(f'--user-data-dir={temp_user_data}') + # 设置 User-Agent co.set_argument(f'--user-agent={fingerprint["user_agent"]}') @@ -418,7 +423,7 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage: co.set_argument('--disable-software-rasterizer') co.set_argument('--disable-extensions') co.set_argument('--disable-setuid-sandbox') - co.set_argument('--single-process') # 某些 Linux 环境需要 + # 注意: 不使用 --single-process,因为并发模式下会导致实例冲突 co.set_argument('--remote-debugging-port=0') # 让系统自动分配端口 # 尝试查找 Chrome/Chromium 路径 @@ -451,6 +456,9 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage: page = ChromiumPage(co) + # 存储临时目录路径,用于后续清理 + page._temp_user_data_dir = temp_user_data + # 注入指纹伪装脚本 (仅在启用随机指纹时) if BROWSER_RANDOM_FINGERPRINT: _inject_fingerprint(page, fingerprint) @@ -487,8 +495,11 @@ def browser_context(max_retries: int = BROWSER_MAX_RETRIES): ChromiumPage: 浏览器页面实例 """ page = None + temp_dir = None try: page = init_browser(max_retries) + # 获取临时目录路径 + temp_dir = getattr(page, '_temp_user_data_dir', None) yield page finally: if page: @@ -500,6 +511,13 @@ def browser_context(max_retries: int = BROWSER_MAX_RETRIES): finally: # 确保清理残留进程 cleanup_chrome_processes() + # 清理临时用户数据目录 + if temp_dir and os.path.exists(temp_dir): + try: + import shutil + shutil.rmtree(temp_dir, ignore_errors=True) + except Exception: + pass @contextmanager @@ -591,20 +609,38 @@ class BrowserRetryContext: def _cleanup_page(self): """清理当前页面""" if self.page: + # 获取临时目录路径 + temp_dir = getattr(self.page, '_temp_user_data_dir', None) try: self.page.quit() except Exception: pass + # 清理临时用户数据目录 + if temp_dir and os.path.exists(temp_dir): + try: + import shutil + shutil.rmtree(temp_dir, ignore_errors=True) + except Exception: + pass self.page = None def cleanup(self): """最终清理""" if self.page: log.step("关闭浏览器...") + # 获取临时目录路径 + temp_dir = getattr(self.page, '_temp_user_data_dir', None) try: self.page.quit() except Exception: pass + # 清理临时用户数据目录 + if temp_dir and os.path.exists(temp_dir): + try: + import shutil + shutil.rmtree(temp_dir, ignore_errors=True) + except Exception: + pass self.page = None