mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
ChromiumOptions和Browser增加is_headless属性;接管浏览器时如无头状态和设置不一致,会按设置重启浏览器
This commit is contained in:
parent
ac3a8ec27c
commit
61dce186c6
@ -40,13 +40,12 @@ class Browser(object):
|
||||
:param session_options: 使用双模Tab时使用的默认Session配置,为True使用ini文件配置
|
||||
"""
|
||||
opt = handle_options(addr_or_opts)
|
||||
is_exist, browser_id = run_browser(opt)
|
||||
is_headless, browser_id = run_browser(opt)
|
||||
if browser_id in cls._BROWSERS:
|
||||
r = cls._BROWSERS[browser_id]
|
||||
return r
|
||||
return cls._BROWSERS[browser_id]
|
||||
r = object.__new__(cls)
|
||||
r._chromium_options = opt
|
||||
r._is_exist = is_exist
|
||||
r.is_headless = is_headless
|
||||
r.id = browser_id
|
||||
r.address = opt.address
|
||||
cls._BROWSERS[browser_id] = r
|
||||
@ -63,7 +62,6 @@ class Browser(object):
|
||||
|
||||
self._type = 'Browser'
|
||||
self._driver = BrowserDriver(self.id, 'browser', self.address, self)
|
||||
self.version = self.run_cdp('Browser.getVersion')['product']
|
||||
|
||||
self._frames = {}
|
||||
self._drivers = {}
|
||||
@ -82,9 +80,25 @@ class Browser(object):
|
||||
self.retry_times = self._chromium_options.retry_times
|
||||
self.retry_interval = self._chromium_options.retry_interval
|
||||
|
||||
if self.is_headless != self._chromium_options.is_headless:
|
||||
self.quit(3, True)
|
||||
connect_browser(self._chromium_options)
|
||||
s = Session()
|
||||
s.trust_env = False
|
||||
ws = s.get(f'http://{self._chromium_options.address}/json/version', headers={'Connection': 'close'})
|
||||
self.id = ws.json()['webSocketDebuggerUrl'].split('/')[-1]
|
||||
self._driver = BrowserDriver(self.id, 'browser', self.address, self)
|
||||
ws.close()
|
||||
s.close()
|
||||
self._frames = {}
|
||||
self._drivers = {}
|
||||
self._all_drivers = {}
|
||||
|
||||
self.version = self._run_cdp('Browser.getVersion')['product']
|
||||
|
||||
self._process_id = None
|
||||
try:
|
||||
r = self.run_cdp('SystemInfo.getProcessInfo')
|
||||
r = self._run_cdp('SystemInfo.getProcessInfo')
|
||||
for i in r.get('processInfo', []):
|
||||
if i['type'] == 'browser':
|
||||
self._process_id = i['id']
|
||||
@ -92,7 +106,7 @@ class Browser(object):
|
||||
except:
|
||||
pass
|
||||
|
||||
self.run_cdp('Target.setDiscoverTargets', discover=True)
|
||||
self._run_cdp('Target.setDiscoverTargets', discover=True)
|
||||
self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed)
|
||||
self._driver.set_callback('Target.targetCreated', self._onTargetCreated)
|
||||
self._dl_mgr = DownloadManager(self)
|
||||
@ -137,7 +151,7 @@ class Browser(object):
|
||||
self._drivers.pop(tab_id, None)
|
||||
self._all_drivers.pop(tab_id, None)
|
||||
|
||||
def run_cdp(self, cmd, **cmd_args):
|
||||
def _run_cdp(self, cmd, **cmd_args):
|
||||
"""执行Chrome DevTools Protocol语句
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
@ -183,7 +197,7 @@ class Browser(object):
|
||||
@property
|
||||
def tabs_count(self):
|
||||
"""返回标签页数量"""
|
||||
j = self.run_cdp('Target.getTargets')['targetInfos'] # 不要改用get,避免卡死
|
||||
j = self._run_cdp('Target.getTargets')['targetInfos'] # 不要改用get,避免卡死
|
||||
return len([i for i in j if i['type'] in ('page', 'webview') and not i['url'].startswith('devtools://')])
|
||||
|
||||
@property
|
||||
@ -235,7 +249,7 @@ class Browser(object):
|
||||
"""
|
||||
tab = None
|
||||
if new_context:
|
||||
tab = self.run_cdp('Target.createBrowserContext')['browserContextId']
|
||||
tab = self._run_cdp('Target.createBrowserContext')['browserContextId']
|
||||
|
||||
kwargs = {'url': ''}
|
||||
if new_window:
|
||||
@ -245,7 +259,7 @@ class Browser(object):
|
||||
if tab:
|
||||
kwargs['browserContextId'] = tab
|
||||
|
||||
tab = self.run_cdp('Target.createTarget', **kwargs)['targetId']
|
||||
tab = self._run_cdp('Target.createTarget', **kwargs)['targetId']
|
||||
while tab not in self._drivers:
|
||||
sleep(.1)
|
||||
tab = obj(self, tab)
|
||||
@ -401,14 +415,14 @@ class Browser(object):
|
||||
:param tab_id: 标签页id
|
||||
:return: None
|
||||
"""
|
||||
self.run_cdp('Target.activateTarget', targetId=tab_id)
|
||||
self._run_cdp('Target.activateTarget', targetId=tab_id)
|
||||
|
||||
def reconnect(self):
|
||||
"""断开重连"""
|
||||
self._driver.stop()
|
||||
BrowserDriver.BROWSERS.pop(self.id)
|
||||
self._driver = BrowserDriver(self.id, 'browser', self.address, self)
|
||||
self.run_cdp('Target.setDiscoverTargets', discover=True)
|
||||
self._run_cdp('Target.setDiscoverTargets', discover=True)
|
||||
self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed)
|
||||
self._driver.set_callback('Target.targetCreated', self._onTargetCreated)
|
||||
|
||||
@ -419,7 +433,7 @@ class Browser(object):
|
||||
:return: None
|
||||
"""
|
||||
try:
|
||||
self.run_cdp('Browser.close')
|
||||
self._run_cdp('Browser.close')
|
||||
except PageDisconnectedError:
|
||||
pass
|
||||
self._driver.stop()
|
||||
@ -433,7 +447,7 @@ class Browser(object):
|
||||
return
|
||||
|
||||
try:
|
||||
pids = [pid['id'] for pid in self.run_cdp('SystemInfo.getProcessInfo')['processInfo']]
|
||||
pids = [pid['id'] for pid in self._run_cdp('SystemInfo.getProcessInfo')['processInfo']]
|
||||
except:
|
||||
return
|
||||
|
||||
@ -516,18 +530,20 @@ def handle_options(addr_or_opts):
|
||||
|
||||
def run_browser(chromium_options):
|
||||
"""连接浏览器"""
|
||||
is_exist = connect_browser(chromium_options)
|
||||
connect_browser(chromium_options)
|
||||
try:
|
||||
s = Session()
|
||||
s.trust_env = False
|
||||
ws = s.get(f'http://{chromium_options.address}/json/version', headers={'Connection': 'close'})
|
||||
if not ws:
|
||||
raise BrowserConnectError('\n浏览器连接失败,如使用全局代理,须设置不代理127.0.0.1地址。')
|
||||
browser_id = ws.json()['webSocketDebuggerUrl'].split('/')[-1]
|
||||
raise BrowserConnectError('\n浏览器连接失败,请确认浏览器是否启动。')
|
||||
json = ws.json()
|
||||
browser_id = json['webSocketDebuggerUrl'].split('/')[-1]
|
||||
is_headless = 'headless' in json['User-Agent'].lower()
|
||||
ws.close()
|
||||
s.close()
|
||||
except KeyError:
|
||||
raise BrowserConnectError('浏览器版本太旧或此浏览器不支持接管。')
|
||||
except:
|
||||
raise BrowserConnectError('\n浏览器连接失败,如使用全局代理,须设置不代理127.0.0.1地址。')
|
||||
return is_exist, browser_id
|
||||
raise BrowserConnectError('\n浏览器连接失败,请确认浏览器是否启动。')
|
||||
return is_headless, browser_id
|
||||
|
@ -24,6 +24,7 @@ class Browser(object):
|
||||
version: str = ...
|
||||
retry_times: int = ...
|
||||
retry_interval: float = ...
|
||||
is_headless:bool = ...
|
||||
|
||||
_BROWSERS: dict = ...
|
||||
_chromium_options: ChromiumOptions = ...
|
||||
@ -51,7 +52,7 @@ class Browser(object):
|
||||
|
||||
def _get_driver(self, tab_id: str, owner=None) -> Driver: ...
|
||||
|
||||
def run_cdp(self, cmd, **cmd_args) -> dict: ...
|
||||
def _run_cdp(self, cmd, **cmd_args) -> dict: ...
|
||||
|
||||
@property
|
||||
def process_id(self) -> Optional[int]: ...
|
||||
|
@ -21,7 +21,7 @@ class ChromiumOptions(object):
|
||||
self._user = 'Default'
|
||||
self._prefs_to_del = []
|
||||
self.clear_file_flags = False
|
||||
self._headless = None
|
||||
self._is_headless = False
|
||||
|
||||
if read_file is False:
|
||||
ini_path = False
|
||||
@ -47,6 +47,10 @@ class ChromiumOptions(object):
|
||||
self._load_mode = options.get('load_mode', 'normal')
|
||||
self._system_user_path = options.get('system_user_path', False)
|
||||
self._existing_only = options.get('existing_only', False)
|
||||
for i in self._arguments:
|
||||
if i.startswith('--headless'):
|
||||
self._is_headless = True
|
||||
break
|
||||
|
||||
self._proxy = om.proxies.get('http', None) or om.proxies.get('https', None)
|
||||
|
||||
@ -164,6 +168,11 @@ class ChromiumOptions(object):
|
||||
"""返回连接失败时的重试间隔(秒)"""
|
||||
return self._retry_interval
|
||||
|
||||
@property
|
||||
def is_headless(self):
|
||||
"""返回是否无头模式"""
|
||||
return self._is_headless
|
||||
|
||||
def set_retry(self, times=None, interval=None):
|
||||
"""设置连接失败时的重试操作
|
||||
:param times: 重试次数
|
||||
@ -184,11 +193,19 @@ class ChromiumOptions(object):
|
||||
"""
|
||||
self.remove_argument(arg)
|
||||
if value is not False:
|
||||
if arg == '--headless' and value is None:
|
||||
self._arguments.append('--headless=new')
|
||||
if arg == '--headless':
|
||||
if value == 'false':
|
||||
self._is_headless = False
|
||||
else:
|
||||
if value is None:
|
||||
value = 'new'
|
||||
self._arguments.append(f'--headless={value}')
|
||||
self._is_headless = True
|
||||
else:
|
||||
arg_str = arg if value is None else f'{arg}={value}'
|
||||
self._arguments.append(arg_str)
|
||||
elif arg == '--headless':
|
||||
self._is_headless = False
|
||||
return self
|
||||
|
||||
def remove_argument(self, value):
|
||||
@ -312,7 +329,7 @@ class ChromiumOptions(object):
|
||||
:param on_off: 开或关
|
||||
:return: 当前对象
|
||||
"""
|
||||
on_off = 'new' if on_off else 'false'
|
||||
on_off = 'new' if on_off else on_off
|
||||
return self.set_argument('--headless', on_off)
|
||||
|
||||
def no_imgs(self, on_off=True):
|
||||
|
@ -10,30 +10,31 @@ from typing import Union, Any, Literal, Optional, Tuple
|
||||
|
||||
|
||||
class ChromiumOptions(object):
|
||||
def __init__(self, read_file: [bool, None] = True, ini_path: Union[str, Path] = None):
|
||||
self.ini_path: str = ...
|
||||
self._driver_path: str = ...
|
||||
self._user_data_path: str = ...
|
||||
self._download_path: str = ...
|
||||
self._tmp_path: str = ...
|
||||
self._arguments: list = ...
|
||||
self._browser_path: str = ...
|
||||
self._user: str = ...
|
||||
self._load_mode: str = ...
|
||||
self._timeouts: dict = ...
|
||||
self._proxy: str = ...
|
||||
self._address: str = ...
|
||||
self._extensions: list = ...
|
||||
self._prefs: dict = ...
|
||||
self._flags: dict = ...
|
||||
self._prefs_to_del: list = ...
|
||||
self.clear_file_flags: bool = ...
|
||||
self._auto_port: bool = ...
|
||||
self._system_user_path: bool = ...
|
||||
self._existing_only: bool = ...
|
||||
self._headless: bool = ...
|
||||
self._retry_times: int = ...
|
||||
self._retry_interval: float = ...
|
||||
ini_path: Optional[str] = ...
|
||||
_driver_path: str = ...
|
||||
_user_data_path: Optional[str] = ...
|
||||
_download_path: str = ...
|
||||
_tmp_path: str = ...
|
||||
_arguments: list = ...
|
||||
_browser_path: str = ...
|
||||
_user: str = ...
|
||||
_load_mode: str = ...
|
||||
_timeouts: dict = ...
|
||||
_proxy: str = ...
|
||||
_address: str = ...
|
||||
_extensions: list = ...
|
||||
_prefs: dict = ...
|
||||
_flags: dict = ...
|
||||
_prefs_to_del: list = ...
|
||||
clear_file_flags: bool = ...
|
||||
_auto_port: bool = ...
|
||||
_system_user_path: bool = ...
|
||||
_existing_only: bool = ...
|
||||
_retry_times: int = ...
|
||||
_retry_interval: float = ...
|
||||
_is_headless: bool = ...
|
||||
|
||||
def __init__(self, read_file: [bool, None] = True, ini_path: Union[str, Path] = None): ...
|
||||
|
||||
@property
|
||||
def download_path(self) -> str: ...
|
||||
@ -89,6 +90,9 @@ class ChromiumOptions(object):
|
||||
@property
|
||||
def retry_interval(self) -> float: ...
|
||||
|
||||
@property
|
||||
def is_headless(self) -> bool: ...
|
||||
|
||||
def set_retry(self, times: int = None, interval: float = None) -> ChromiumOptions: ...
|
||||
|
||||
def set_argument(self, arg: str, value: Union[str, None, bool] = None) -> ChromiumOptions: ...
|
||||
|
@ -30,11 +30,6 @@ def connect_browser(option):
|
||||
ip, port = address.split(':')
|
||||
if ip != '127.0.0.1' or port_is_using(ip, port) or option.is_existing_only:
|
||||
test_connect(ip, port)
|
||||
option._headless = False
|
||||
for i in option.arguments:
|
||||
if i.startswith('--headless') and not i.endswith('=false'):
|
||||
option._headless = True
|
||||
break
|
||||
return True
|
||||
|
||||
# ----------创建浏览器进程----------
|
||||
@ -65,7 +60,6 @@ def get_launch_args(opt):
|
||||
# ----------处理arguments-----------
|
||||
result = set()
|
||||
has_user_path = False
|
||||
headless = None
|
||||
for i in opt.arguments:
|
||||
if i.startswith(('--load-extension=', '--remote-debugging-port=')):
|
||||
continue
|
||||
@ -73,16 +67,6 @@ def get_launch_args(opt):
|
||||
result.add(f'--user-data-dir={Path(i[16:]).absolute()}')
|
||||
has_user_path = True
|
||||
continue
|
||||
elif i.startswith('--headless'):
|
||||
if i == '--headless=false':
|
||||
headless = False
|
||||
continue
|
||||
elif i == '--headless':
|
||||
i = '--headless=new'
|
||||
headless = True
|
||||
else:
|
||||
headless = True
|
||||
|
||||
result.add(i)
|
||||
|
||||
if not has_user_path and not opt.system_user_path:
|
||||
@ -93,15 +77,7 @@ def get_launch_args(opt):
|
||||
opt.set_user_data_path(path)
|
||||
result.add(f'--user-data-dir={path}')
|
||||
|
||||
# if headless is None and system().lower() == 'linux': # 无界面Linux自动加入无头
|
||||
# from os import popen
|
||||
# r = popen('systemctl list-units | grep graphical.target')
|
||||
# if 'graphical.target' not in r.read():
|
||||
# headless = True
|
||||
# result.add('--headless=new')
|
||||
|
||||
result = list(result)
|
||||
opt._headless = headless
|
||||
|
||||
# ----------处理插件extensions-------------
|
||||
ext = [str(Path(e).absolute()) for e in opt.extensions]
|
||||
|
Loading…
x
Reference in New Issue
Block a user