[docs]classPlaywrightFamily(BrowserFamily):""" Standard Playwright (with stealth wrapper on demand). Restarts only what has changed: PW engine when stealth changes, browser when engine/headless/launch_opts change. """def__init__(self)->None:self._pw:Any|None=Noneself._stealth_cm:Any|None=Noneself._browser:Browser|None=None# кэш использованных опцийself._engine_used:PlaywrightEngine|None=Noneself._stealth_used:bool|None=Noneself._launch_opts_used:Dict[str,Any]|None=None@property
[docs]asyncdefstart(self,cfg:DesiredConfig)->None:assertcfg.family=="playwright","wrong family for PlaywrightFamily"assertcfg.enginein("chromium","firefox","webkit")# Нужен ли перезапуск PW (stealth изменился / ещё не поднят)need_pw_restart=self._pwisNoneor(self._stealth_usedisnotNoneandself._stealth_used!=cfg.stealth)ifneed_pw_restart:awaitself._stop_pw()# мягко закрыть PW-уровеньifcfg.stealth:try:fromplaywright_stealthimportStealth# type: ignore[import-untyped]exceptException:raiseRuntimeError("stealth=True, but the 'playwright-stealth' package is not installed. ""Install it with: pip install playwright-stealth")self._stealth_cm=Stealth().use_async(async_playwright())self._pw=awaitself._stealth_cm.__aenter__()else:self._pw=awaitasync_playwright().__aenter__()# Нужен ли перелонч браузераneed_browser_relaunch=(need_pw_restartorself._browserisNoneorself._engine_used!=cfg.engineorself._launch_opts_used!=cfg.launch_opts)ifneed_browser_relaunch:ifself._browserisnotNone:awaitself._browser.close()self._browser=Noneassertself._pwisnotNonelauncher=getattr(self._pw,cfg.engine)kwargs=dict(cfg.launch_opts)self._browser=awaitlauncher.launch(**kwargs)# обновить кэшself._engine_used=cfg.engineself._stealth_used=cfg.stealthself._launch_opts_used=dict(cfg.launch_opts)
asyncdef_stop_pw(self)->None:# Сначала закрыть stealth CM (если был) — он закрывает и свой PWifself._stealth_cmisnotNone:awaitself._stealth_cm.__aexit__(None,None,None)self._stealth_cm=Noneself._pw=Noneelifself._pwisnotNone:awaitself._pw.stop()self._pw=None