优化1
This commit is contained in:
@@ -25,6 +25,7 @@ class BrowserPool:
|
||||
def __init__(self, settings: Settings):
|
||||
self._settings = settings
|
||||
self._playwright: Any | None = None
|
||||
self._playwright_cm: Any | None = None # stealth 钩子包装的 playwright 上下文管理器
|
||||
self._browser: Any | None = None
|
||||
self._semaphore = asyncio.Semaphore(settings.max_site_concurrency)
|
||||
self._restart_lock = asyncio.Lock()
|
||||
@@ -66,15 +67,29 @@ class BrowserPool:
|
||||
|
||||
headless = self._settings.browser_headless_effective
|
||||
logger.info(
|
||||
"启动浏览器:enabled=%s headless=%s keep_open_on_error=%s channel=%s proxy=%s env=%s",
|
||||
"启动浏览器:enabled=%s headless=%s keep_open_on_error=%s channel=%s proxy=%s stealth=%s env=%s",
|
||||
self._settings.browser_enabled,
|
||||
headless,
|
||||
self._settings.browser_keep_open_on_error_effective,
|
||||
self._settings.browser_channel,
|
||||
bool(self._settings.proxy_server),
|
||||
self._settings.browser_stealth_enabled,
|
||||
self._settings.app_env,
|
||||
)
|
||||
self._playwright = await async_playwright().start()
|
||||
if self._settings.browser_stealth_enabled:
|
||||
# 用 playwright-stealth 钩子包装 playwright:后续 new_context/new_page
|
||||
# 会自动应用 stealth(含 HTTP sec-ch-ua 客户端提示),并令 navigator.languages
|
||||
# 与日语环境保持一致,避免指纹自相矛盾。
|
||||
from playwright_stealth import Stealth
|
||||
|
||||
stealth = Stealth(
|
||||
navigator_languages_override=("ja-JP", "ja", "en-US", "en"),
|
||||
)
|
||||
self._playwright_cm = stealth.use_async(async_playwright())
|
||||
self._playwright = await self._playwright_cm.__aenter__()
|
||||
else:
|
||||
self._playwright_cm = None
|
||||
self._playwright = await async_playwright().start()
|
||||
chromium = self._playwright.chromium
|
||||
launch_args = [
|
||||
"--disable-blink-features=AutomationControlled",
|
||||
@@ -138,13 +153,20 @@ class BrowserPool:
|
||||
await self._browser.close()
|
||||
except Exception:
|
||||
logger.exception("关闭浏览器实例失败")
|
||||
if self._playwright is not None:
|
||||
if self._playwright_cm is not None:
|
||||
# stealth 钩子包装:通过上下文管理器退出来停止 playwright
|
||||
try:
|
||||
await self._playwright_cm.__aexit__(None, None, None)
|
||||
except Exception:
|
||||
logger.exception("停止 Playwright(stealth 包装)运行时失败")
|
||||
elif self._playwright is not None:
|
||||
try:
|
||||
await self._playwright.stop()
|
||||
except Exception:
|
||||
logger.exception("停止 Playwright 运行时失败")
|
||||
self._browser = None
|
||||
self._playwright = None
|
||||
self._playwright_cm = None
|
||||
self._started = False
|
||||
|
||||
async def _restart_browser(self, reason: str) -> None:
|
||||
@@ -251,9 +273,11 @@ class BrowserPool:
|
||||
logger.exception("关闭旧的保留调试上下文失败")
|
||||
|
||||
async def _build_context_obj(self, storage_state: dict[str, Any] | None) -> Any:
|
||||
"""创建浏览器上下文(含断链重试与 stealth),仅负责创建本身。
|
||||
"""创建浏览器上下文(含断链重试),仅负责创建本身。
|
||||
|
||||
计入回收阈值统计;不负责并发信号量与关闭,由调用方管理生命周期。
|
||||
启用 stealth 时,playwright 已被 use_async 钩子包装,new_context 会自动
|
||||
应用 stealth(含 HTTP sec-ch-ua),此处无需再手动 apply。
|
||||
"""
|
||||
context = None
|
||||
for attempt in range(2):
|
||||
@@ -275,15 +299,6 @@ class BrowserPool:
|
||||
|
||||
# 上下文创建成功,计入回收阈值统计
|
||||
self._contexts_since_start += 1
|
||||
|
||||
if self._settings.browser_stealth_enabled:
|
||||
try:
|
||||
from playwright_stealth import Stealth
|
||||
|
||||
await Stealth().apply_stealth_async(context)
|
||||
except Exception as e:
|
||||
logger.warning("应用 playwright-stealth 失败,隐身模式未生效, err=%s", e)
|
||||
|
||||
return context
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user