直接复用页面,避免CF验证

This commit is contained in:
2026-06-09 16:22:31 +08:00
parent 28fcc619a5
commit 2d75d21edc
3 changed files with 63 additions and 52 deletions
+15 -15
View File
@@ -302,18 +302,25 @@ class BrowserPool:
async def create_persistent_context(self, storage_state: dict[str, Any] | None = None) -> Any:
"""创建一个由调用方负责生命周期的长存上下文。
用于 cf_clearance 保活复用:通过挑战后保留该上下文,后续请求在其内
开新页面访问目标页(同一上下文内 cf_clearance 有效)。调用方需在不再
使用时调用 close_context 释放。
用于 cf_clearance 保活复用:通过挑战后保留该上下文及其页面,后续请求
复用同一页面(当前标签页)重新导航。调用方需在不再使用时调用
close_context 释放。
"""
await self._ensure_browser_ready()
return await self._build_context_obj(storage_state)
@asynccontextmanager
async def page_in_context(self, context: Any) -> AsyncIterator[Any]:
"""在既有(长存)上下文中开一个页面,复用并发信号量。
async def create_persistent_page(self, context: Any) -> Any:
"""在长存上下文中创建一个长存页面(设置反检测请求头)。
结束时仅关闭页面,不关闭上下文(上下文生命周期由调用方维护)
该页面不会被自动关闭,调用方通过 close_context 关闭其所属上下文时一并释放
"""
return await self._configure_page(context)
@asynccontextmanager
async def navigation_slot(self) -> AsyncIterator[None]:
"""获取一个并发槽位用于一次页面导航(不创建/关闭页面)。
用于在长存页面上做导航时复用全局并发信号量与回收计数。
Raises:
ResourceBusyError: 等待可用槽位超时
@@ -327,19 +334,12 @@ class BrowserPool:
except TimeoutError as exc:
raise ResourceBusyError() from exc
page = None
counted = False
try:
self._active_contexts += 1
counted = True
page = await self._configure_page(context)
yield page
yield
finally:
if page is not None:
try:
await page.close()
except Exception:
logger.debug("关闭复用上下文页面失败", exc_info=True)
if counted:
self._active_contexts -= 1
self._semaphore.release()