From 6482dfec517efd71650498052a6053cff3af5f9a Mon Sep 17 00:00:00 2001 From: g1879 Date: Mon, 15 Mar 2021 17:45:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8=E6=B5=8F?= =?UTF-8?q?=E8=A7=88=E5=99=A8=E5=92=8C=E8=8E=B7=E5=8F=96=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/common.py | 22 +++++++++++ DrissionPage/drission.py | 42 +++++++++++++++++---- DrissionPage/easy_set.py | 80 +++++++++++++++++++++------------------- 3 files changed, 99 insertions(+), 45 deletions(-) diff --git a/DrissionPage/common.py b/DrissionPage/common.py index 11e6d9d..d0e950c 100644 --- a/DrissionPage/common.py +++ b/DrissionPage/common.py @@ -317,3 +317,25 @@ def unzip(zip_path: str, to_path: str) -> Union[list, None]: with ZipFile(zip_path, 'r') as f: return [f.extract(f.namelist()[0], path=to_path)] + + +def get_exe_path_from_port(port: Union[str, int]) -> Union[str, None]: + """获取端口号第一条进程的可执行文件路径 \n + :param port: 端口号 + :return: 可执行文件的绝对路径 + """ + from os import popen + from time import perf_counter + process = popen(f'netstat -ano |findstr {port}').read().split('\n')[0] + t = perf_counter() + + while not process and perf_counter() - t < 10: + process = popen(f'netstat -ano |findstr {port}').read().split('\n')[0] + + processid = process[process.rfind(' ') + 1:] + + if not processid: + return + else: + file_lst = popen(f'wmic process where processid={processid} get executablepath').read().split('\n') + return file_lst[2].strip() if len(file_lst) > 2 else None diff --git a/DrissionPage/drission.py b/DrissionPage/drission.py index 0006a66..6a51c2f 100644 --- a/DrissionPage/drission.py +++ b/DrissionPage/drission.py @@ -35,6 +35,7 @@ class Drission(object): """ self._session = None self._driver = None + self._debugger = None self._proxy = proxy om = OptionsManager(ini_path) if session_or_options is None or driver_or_options is None else None @@ -94,41 +95,61 @@ class Drission(object): driver_path = self._driver_options.get('driver_path', None) or 'chromedriver' chrome_path = self._driver_options.get('binary_location', None) or 'chrome.exe' + # -----------若指定debug端口且该端口未在使用中,则先启动浏览器进程----------- if options.debugger_address and _check_port(options.debugger_address) is False: from subprocess import Popen port = options.debugger_address[options.debugger_address.rfind(':') + 1:] try: - Popen(f'{chrome_path} --remote-debugging-port={port}', shell=False) + self._debugger = Popen(f'{chrome_path} --remote-debugging-port={port}', shell=False) + if chrome_path == 'chrome.exe': + from common import get_exe_path_from_port + chrome_path = get_exe_path_from_port(port) + + # 启动不了进程,主动找浏览器执行文件启动 except FileNotFoundError: from DrissionPage.easy_set import _get_chrome_path - chrome_path = _get_chrome_path(show_msg=False) if not chrome_path: raise FileNotFoundError('无法找到chrome.exe路径,请手动配置。') - Popen(f'"{chrome_path}" --remote-debugging-port={port}', shell=False) - options.binary_location = chrome_path + self._debugger = Popen(f'"{chrome_path}" --remote-debugging-port={port}', shell=False) + # -----------创建WebDriver对象----------- try: self._driver = webdriver.Chrome(driver_path, options=options) + # 若版本不对,获取对应chromedriver再试 except (WebDriverException, SessionNotCreatedException): from .easy_set import get_match_driver - - print('自动下载chromedriver...') chrome_path = None if chrome_path == 'chrome.exe' else chrome_path - driver_path = get_match_driver(chrome_path=chrome_path, check_version=False) + driver_path = get_match_driver(chrome_path=chrome_path, check_version=False, show_msg=False) if driver_path: try: self._driver = webdriver.Chrome(driver_path, options=options) - print('下载完成。') except: print('无法启动,请检查chromedriver版本与Chrome是否匹配,并手动设置。') exit(0) + + # 当找不到driver且chrome_path为None时,说明安装的版本过高,改在系统路径中查找 + elif chrome_path is None and driver_path is None: + from DrissionPage.easy_set import _get_chrome_path + chrome_path = _get_chrome_path(show_msg=False, from_ini=False, from_regedit=False) + driver_path = get_match_driver(chrome_path=chrome_path, check_version=False, show_msg=False) + + if driver_path: + options.binary_location = chrome_path + try: + self._driver = webdriver.Chrome(driver_path, options=options) + except: + print('无法启动,请检查chromedriver版本与Chrome是否匹配,并手动设置。') + exit(0) + else: + print('无法启动,请检查chromedriver版本与Chrome是否匹配,并手动设置。') + exit(0) else: print('无法启动,请检查chromedriver版本与Chrome是否匹配,并手动设置。') exit(0) @@ -145,6 +166,11 @@ class Drission(object): return self._driver + @property + def debugger_progress(self): + """调试浏览器进程""" + return self._debugger + @property def driver_options(self) -> dict: """返回driver配置信息""" diff --git a/DrissionPage/easy_set.py b/DrissionPage/easy_set.py index d3f0330..edc4417 100644 --- a/DrissionPage/easy_set.py +++ b/DrissionPage/easy_set.py @@ -242,13 +242,17 @@ def get_match_driver(ini_path: Union[str, None] = 'default', return driver_path -def _get_chrome_path(ini_path: str = None, show_msg: bool = True) -> Union[str, None]: +def _get_chrome_path(ini_path: str = None, + show_msg: bool = True, + from_ini: bool = True, + from_regedit: bool = True, + from_system_path: bool = True, ) -> Union[str, None]: """从ini文件或系统变量中获取chrome.exe的路径 \n :param ini_path: ini文件路径 :return: chrome.exe路径 """ # -----------从ini文件中获取-------------- - if ini_path: + if ini_path and from_ini: try: path = OptionsManager(ini_path).chrome_options['binary_location'] except KeyError: @@ -261,46 +265,48 @@ def _get_chrome_path(ini_path: str = None, show_msg: bool = True) -> Union[str, return str(path) # -----------从注册表中获取-------------- - import winreg - try: - key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, - r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe', - reserved=0, access=winreg.KEY_READ) - k = winreg.EnumValue(key, 0) - winreg.CloseKey(key) - - if show_msg: - print('注册表中', end='') - - return k[1] - - except FileNotFoundError: - pass - - # -----------从系统路径中获取-------------- - paths = popen('set path').read().lower() - r = RE_SEARCH(r'[^;]*chrome[^;]*', paths) - - if r: - path = Path(r.group(0)) if 'chrome.exe' in r.group(0) else Path(r.group(0)) / 'chrome.exe' - - if path.exists(): - if show_msg: - print('系统中', end='') - return str(path) - - paths = paths.split(';') - - for path in paths: - path = Path(path) / 'chrome.exe' - + if from_regedit: + import winreg try: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, + r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe', + reserved=0, access=winreg.KEY_READ) + k = winreg.EnumValue(key, 0) + winreg.CloseKey(key) + + if show_msg: + print('注册表中', end='') + + return k[1] + + except FileNotFoundError: + pass + + # -----------从系统变量中获取-------------- + if from_system_path: + paths = popen('set path').read().lower() + r = RE_SEARCH(r'[^;]*chrome[^;]*', paths) + + if r: + path = Path(r.group(0)) if 'chrome.exe' in r.group(0) else Path(r.group(0)) / 'chrome.exe' + if path.exists(): if show_msg: print('系统变量中', end='') return str(path) - except OSError: - pass + + paths = paths.split(';') + + for path in paths: + path = Path(path) / 'chrome.exe' + + try: + if path.exists(): + if show_msg: + print('系统变量中', end='') + return str(path) + except OSError: + pass def _get_chrome_version(path: str) -> Union[str, None]: