8
This commit is contained in:
@@ -233,7 +233,7 @@ def log_url_change(page, old_url: str, action: str = None):
|
|||||||
log.warning(f"记录URL变化失败: {e}")
|
log.warning(f"记录URL变化失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
def acquire_lock_with_keepalive(lock, page, timeout: float = 120, check_interval: float = 2.0) -> bool:
|
def acquire_lock_with_keepalive(lock, page, timeout: float = 120, check_interval: float = 1.0) -> bool:
|
||||||
"""获取锁的同时保持浏览器活跃,防止等待期间浏览器连接断开
|
"""获取锁的同时保持浏览器活跃,防止等待期间浏览器连接断开
|
||||||
|
|
||||||
在并发模式下,多个 Worker 可能需要等待授权回调锁。
|
在并发模式下,多个 Worker 可能需要等待授权回调锁。
|
||||||
@@ -244,46 +244,85 @@ def acquire_lock_with_keepalive(lock, page, timeout: float = 120, check_interval
|
|||||||
lock: threading.Lock 对象
|
lock: threading.Lock 对象
|
||||||
page: 浏览器页面对象
|
page: 浏览器页面对象
|
||||||
timeout: 最大等待时间 (秒)
|
timeout: 最大等待时间 (秒)
|
||||||
check_interval: 检查间隔 (秒)
|
check_interval: 检查间隔 (秒),默认 1 秒
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: 是否成功获取锁
|
bool: 是否成功获取锁(且浏览器仍可用)
|
||||||
"""
|
"""
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
acquired = False
|
keepalive_counter = 0
|
||||||
|
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
# 尝试非阻塞获取锁
|
# 尝试非阻塞获取锁
|
||||||
acquired = lock.acquire(blocking=False)
|
acquired = lock.acquire(blocking=False)
|
||||||
if acquired:
|
if acquired:
|
||||||
|
# 获取锁成功,验证浏览器是否仍然可用
|
||||||
|
try:
|
||||||
|
_ = page.url # 测试连接
|
||||||
|
page.run_js("1+1") # 确保 JS 引擎可用
|
||||||
return True
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
# 浏览器已断开,释放锁让其他人重试
|
||||||
|
log.warning(f"获取锁后发现浏览器已断开: {e}")
|
||||||
|
lock.release()
|
||||||
|
return False
|
||||||
|
|
||||||
# 未获取到锁,保持浏览器活跃
|
# 未获取到锁,保持浏览器活跃
|
||||||
try:
|
try:
|
||||||
# 访问页面属性以保持连接活跃
|
# 每次都访问页面属性以保持连接活跃
|
||||||
_ = page.url
|
current_url = page.url
|
||||||
# 可选:执行一个轻量级操作
|
|
||||||
|
# 执行轻量级 JavaScript 保持活跃
|
||||||
|
page.run_js("1+1")
|
||||||
|
|
||||||
|
# 每 5 次(约 5 秒)执行一次更积极的保活操作
|
||||||
|
keepalive_counter += 1
|
||||||
|
if keepalive_counter % 5 == 0:
|
||||||
|
# 导航到 about:blank 再返回,强制保持连接
|
||||||
try:
|
try:
|
||||||
page.run_js("1+1") # 执行简单的 JavaScript 保持活跃
|
page.run_js("window.focus()") # 尝试激活窗口
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# 浏览器连接可能已断开
|
# 浏览器连接已断开
|
||||||
log.warning(f"保持浏览器活跃时出错: {e}")
|
log.warning(f"保持浏览器活跃时出错: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 等待一小段时间后重试
|
# 等待一小段时间后重试(使用较短间隔)
|
||||||
time.sleep(check_interval)
|
time.sleep(check_interval)
|
||||||
|
|
||||||
# 超时,尝试最后一次阻塞获取 (短暂)
|
# 超时,尝试最后一次阻塞获取 (短暂)
|
||||||
acquired = lock.acquire(blocking=True, timeout=0.1)
|
acquired = lock.acquire(blocking=True, timeout=0.1)
|
||||||
return acquired
|
if acquired:
|
||||||
|
# 验证浏览器
|
||||||
|
try:
|
||||||
|
_ = page.url
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
lock.release()
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def cleanup_chrome_processes():
|
def cleanup_chrome_processes(force: bool = False):
|
||||||
"""清理残留的 Chrome 进程 (跨平台支持)"""
|
"""清理残留的 Chrome 进程 (跨平台支持)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
force: 是否强制清理。在并发模式下默认跳过,除非 force=True
|
||||||
|
"""
|
||||||
|
# 检查是否在并发模式下运行,如果是则跳过清理(避免杀死其他 Worker 的浏览器)
|
||||||
|
if not force:
|
||||||
|
try:
|
||||||
|
from config import CONCURRENT_ENABLED
|
||||||
|
if CONCURRENT_ENABLED:
|
||||||
|
# 并发模式下跳过全局清理,避免影响其他 Worker
|
||||||
|
return
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
# Windows: 使用 taskkill 清理 chromedriver 和 chrome
|
# Windows: 使用 taskkill 清理 chromedriver 和 chrome
|
||||||
|
|||||||
Reference in New Issue
Block a user