This commit is contained in:
2026-01-15 23:53:33 +08:00
parent b1953b5d95
commit 51d03038e0
5 changed files with 232 additions and 51 deletions

View File

@@ -6,6 +6,7 @@ import time
import random
import subprocess
import os
import platform
from contextlib import contextmanager
from DrissionPage import ChromiumPage, ChromiumOptions
@@ -156,22 +157,27 @@ def log_url_change(page, old_url: str, action: str = None):
def cleanup_chrome_processes():
"""清理残留的 Chrome 进程 (Windows)"""
"""清理残留的 Chrome 进程 (跨平台支持)"""
try:
# 查找并终止残留的 chrome 进程 (仅限无头或调试模式的)
result = subprocess.run(
['tasklist', '/FI', 'IMAGENAME eq chrome.exe', '/FO', 'CSV'],
capture_output=True, text=True, timeout=5
)
if 'chrome.exe' in result.stdout:
# 只清理可能是自动化残留的进程,不影响用户正常使用的浏览器
# 通过检查命令行参数来判断
if platform.system() == "Windows":
# Windows: 使用 tasklist 和 taskkill
result = subprocess.run(
['tasklist', '/FI', 'IMAGENAME eq chrome.exe', '/FO', 'CSV'],
capture_output=True, text=True, timeout=5
)
if 'chrome.exe' in result.stdout:
subprocess.run(
['taskkill', '/F', '/IM', 'chromedriver.exe'],
capture_output=True, timeout=5
)
log.step("已清理 chromedriver 残留进程")
else:
# Linux/Mac: 使用 pkill
subprocess.run(
['taskkill', '/F', '/IM', 'chromedriver.exe'],
['pkill', '-f', 'chromedriver'],
capture_output=True, timeout=5
)
log.step("已清理 chromedriver 残留进程")
except Exception:
pass # 静默处理,不影响主流程
@@ -186,9 +192,10 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage:
ChromiumPage: 浏览器实例
"""
log.info("初始化浏览器...", icon="browser")
last_error = None
is_linux = platform.system() == "Linux"
for attempt in range(max_retries):
try:
# 首次尝试或重试前清理残留进程
@@ -196,7 +203,7 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage:
log.warning(f"浏览器启动重试 ({attempt + 1}/{max_retries})...")
cleanup_chrome_processes()
time.sleep(BROWSER_RETRY_DELAY)
co = ChromiumOptions()
co.set_argument('--no-first-run')
co.set_argument('--disable-infobars')
@@ -204,8 +211,31 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage:
co.set_argument('--disable-gpu') # 减少资源占用
co.set_argument('--disable-dev-shm-usage') # 避免共享内存问题
co.set_argument('--no-sandbox') # 服务器环境需要
co.auto_port() # 自动分配端口,确保每次都是新实例
# Linux 服务器特殊配置
if is_linux:
co.set_argument('--disable-software-rasterizer')
co.set_argument('--disable-extensions')
co.set_argument('--disable-setuid-sandbox')
co.set_argument('--single-process') # 某些 Linux 环境需要
co.set_argument('--remote-debugging-port=0') # 让系统自动分配端口
# 尝试查找 Chrome/Chromium 路径
chrome_paths = [
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium-browser',
'/usr/bin/chromium',
'/snap/bin/chromium',
]
for chrome_path in chrome_paths:
if os.path.exists(chrome_path):
co.set_browser_path(chrome_path)
log.step(f"使用浏览器: {chrome_path}")
break
else:
co.auto_port() # Windows 使用自动分配端口
# 无头模式 (服务器运行)
if BROWSER_HEADLESS:
co.set_argument('--headless=new')
@@ -213,10 +243,10 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage:
log.step("启动 Chrome (无头模式)...")
else:
log.step("启动 Chrome (无痕模式)...")
# 设置超时
co.set_timeouts(base=PAGE_LOAD_TIMEOUT, page_load=PAGE_LOAD_TIMEOUT * 2)
page = ChromiumPage(co)
log.success("浏览器启动成功")
return page
@@ -224,10 +254,10 @@ def init_browser(max_retries: int = BROWSER_MAX_RETRIES) -> ChromiumPage:
except Exception as e:
last_error = e
log.warning(f"浏览器启动失败 (尝试 {attempt + 1}/{max_retries}): {e}")
# 清理可能的残留
cleanup_chrome_processes()
# 所有重试都失败
log.error(f"浏览器启动失败,已重试 {max_retries} 次: {last_error}")
raise last_error