From cfb0a6b8f654bd0ddc367c44513fb6d2bac08f1f Mon Sep 17 00:00:00 2001 From: g1879 Date: Wed, 7 Feb 2024 08:32:20 +0000 Subject: [PATCH 1/4] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db38f30..49cbe38 100644 --- a/README.md +++ b/README.md @@ -123,4 +123,4 @@ python 版本:3.6 及以上 如果本项目对您有所帮助,不妨请作者我喝杯咖啡 :) -![](https://gitee.com/g1879/DrissionPageDocs/raw/master/docs/imgs/code.jpg) +![](https://g1879.gitee.io/drissionpagedocs/assets/images/code-cf68de50a2f331a2aa0d39c9aebbbe2c.jpg) From 70243a1fd1ade16ec47050ab5e54b5eee131381a Mon Sep 17 00:00:00 2001 From: g1879 Date: Wed, 7 Feb 2024 20:28:13 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=EF=BC=9Bclick.for=5Fnew?= =?UTF-8?q?=5Ftab()=EF=BC=9Bset.upload=5Ffiles()=E5=92=8Cclick.to=5Fupload?= =?UTF-8?q?()=E6=94=AF=E6=8C=81Path=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_units/clicker.py | 15 +++++++++++++-- DrissionPage/_units/clicker.pyi | 5 ++++- DrissionPage/_units/setter.py | 2 ++ DrissionPage/_units/setter.pyi | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/DrissionPage/_units/clicker.py b/DrissionPage/_units/clicker.py index a8b5513..ce1a394 100644 --- a/DrissionPage/_units/clicker.py +++ b/DrissionPage/_units/clicker.py @@ -159,7 +159,7 @@ class Clicker(object): tab = self._ele.page._page if new_tab else self._ele.page - self._ele.click(by_js=by_js) + self.left(by_js=by_js) return tab.wait.download_begin() def to_upload(self, file_paths, by_js=False): @@ -169,9 +169,20 @@ class Clicker(object): :return: None """ self._ele.page.set.upload_files(file_paths) - self._ele.click(by_js=by_js) + self.left(by_js=by_js) self._ele.page.wait.upload_paths_inputted() + def for_new_tab(self, by_js=False): + """点击后等待新tab出现并返回其对象 + :param by_js: 是否使用js点击,逻辑与click()一致 + :return: 新标签页对象,如果没有等到新标签页出现则抛出异常 + """ + self.left(by_js=by_js) + tid = self._ele.page._page.wait.new_tab() + if not tid: + raise RuntimeError('没有出现新标签页。') + return self._ele.page._page.get_tab(tid) + def _click(self, client_x, client_y, button='left', count=1): """实施点击 :param client_x: 视口中的x坐标 diff --git a/DrissionPage/_units/clicker.pyi b/DrissionPage/_units/clicker.pyi index 7aa346d..ac80568 100644 --- a/DrissionPage/_units/clicker.pyi +++ b/DrissionPage/_units/clicker.pyi @@ -10,6 +10,7 @@ from typing import Union from .downloader import DownloadMission from .._elements.chromium_element import ChromiumElement +from .._pages.chromium_tab import WebPageTab, ChromiumTab class Clicker(object): @@ -39,6 +40,8 @@ class Clicker(object): new_tab: bool = False, by_js: bool = False) -> DownloadMission: ... - def to_upload(self, file_paths: Union[str, list, tuple], by_js: bool = False) -> None: ... + def to_upload(self, file_paths: Union[str, Path, list, tuple], by_js: bool = False) -> None: ... + + def for_new_tab(self, by_js:bool=False)->Union[ChromiumTab, WebPageTab]:... def _click(self, client_x: float, client_y: float, button: str = 'left', count: int = 1) -> None: ... diff --git a/DrissionPage/_units/setter.py b/DrissionPage/_units/setter.py index dd0780c..22a3423 100644 --- a/DrissionPage/_units/setter.py +++ b/DrissionPage/_units/setter.py @@ -130,6 +130,8 @@ class ChromiumBaseSetter(BasePageSetter): if isinstance(files, str): files = files.split('\n') + elif isinstance(files, Path): + files = (files, ) self._page._upload_list = [str(Path(i).absolute()) for i in files] def headers(self, headers: dict) -> None: diff --git a/DrissionPage/_units/setter.pyi b/DrissionPage/_units/setter.pyi index 542f733..8695d61 100644 --- a/DrissionPage/_units/setter.pyi +++ b/DrissionPage/_units/setter.pyi @@ -62,7 +62,7 @@ class ChromiumBaseSetter(BasePageSetter): def auto_handle_alert(self, on_off: bool = True, accept: bool = True) -> None: ... - def upload_files(self, files: Union[str, list, tuple]) -> None: ... + def upload_files(self, files: Union[str, Path, list, tuple]) -> None: ... def blocked_urls(self, urls: Union[list, tuple, str, None]) -> None: ... From 038d837dda52f5c698a10e893d0b9480a1d29f45 Mon Sep 17 00:00:00 2001 From: g1879 Date: Thu, 8 Feb 2024 10:13:14 +0800 Subject: [PATCH 3/4] =?UTF-8?q?click.to=5Fdownload()=E5=A2=9E=E5=8A=A0time?= =?UTF-8?q?out=E5=8F=82=E6=95=B0=EF=BC=9B=E5=AE=8C=E5=96=84=E6=89=BEchrome?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E9=80=BB=E8=BE=91=EF=BC=9B=E8=B0=83=E6=95=B4?= =?UTF-8?q?quit()=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_functions/browser.py | 20 +++++++++++++------- DrissionPage/_functions/tools.py | 7 ++++++- DrissionPage/_units/clicker.py | 5 +++-- DrissionPage/_units/clicker.pyi | 3 ++- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/DrissionPage/_functions/browser.py b/DrissionPage/_functions/browser.py index 2fbc5c7..5075945 100644 --- a/DrissionPage/_functions/browser.py +++ b/DrissionPage/_functions/browser.py @@ -316,14 +316,20 @@ def get_chrome_path(ini_path): return None # -----------从注册表中获取-------------- - import winreg + from winreg import OpenKey, EnumValue, CloseKey, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, KEY_READ 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) - + key = OpenKey(HKEY_CURRENT_USER, + r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe', + reserved=0, access=KEY_READ) + k = EnumValue(key, 0) + CloseKey(key) + if k[1]: + return k[1] + key = OpenKey(HKEY_LOCAL_MACHINE, + r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe', + reserved=0, access=KEY_READ) + k = EnumValue(key, 0) + CloseKey(key) return k[1] except FileNotFoundError: diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index 49b0bca..c2ec84e 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -204,7 +204,12 @@ def stop_process_on_port(port, pid=None): for conn in connections: if conn.laddr.port == int(port): try: - proc.terminate() + # proc.terminate() + parent = proc.parent() + if parent is None: + proc.kill() + elif parent.name() == 'explorer.exe': + proc.terminate() except (NoSuchProcess, AccessDenied, ZombieProcess): pass except Exception as e: diff --git a/DrissionPage/_units/clicker.py b/DrissionPage/_units/clicker.py index ce1a394..d8a9b1e 100644 --- a/DrissionPage/_units/clicker.py +++ b/DrissionPage/_units/clicker.py @@ -140,13 +140,14 @@ class Clicker(object): """ self.at(count=times) - def to_download(self, save_path=None, rename=None, suffix=None, new_tab=False, by_js=False): + def to_download(self, save_path=None, rename=None, suffix=None, new_tab=False, by_js=False, timeout=None): """点击触发下载 :param save_path: 保存路径,为None保存在原来设置的,如未设置保存到当前路径 :param rename: 重命名文件名 :param suffix: 指定文件后缀 :param new_tab: 该下载是否在新tab中触发 :param by_js: 是否用js方式点击,逻辑与click()一致 + :param timeout: 等待下载触发的超时时间,为None则使用页面对象设置 :return: DownloadMission对象 """ if save_path: @@ -160,7 +161,7 @@ class Clicker(object): tab = self._ele.page._page if new_tab else self._ele.page self.left(by_js=by_js) - return tab.wait.download_begin() + return tab.wait.download_begin(timeout=timeout) def to_upload(self, file_paths, by_js=False): """触发上传文件选择框并自动填入指定路径 diff --git a/DrissionPage/_units/clicker.pyi b/DrissionPage/_units/clicker.pyi index ac80568..e6ca30f 100644 --- a/DrissionPage/_units/clicker.pyi +++ b/DrissionPage/_units/clicker.pyi @@ -38,7 +38,8 @@ class Clicker(object): rename: str = None, suffix: str = None, new_tab: bool = False, - by_js: bool = False) -> DownloadMission: ... + by_js: bool = False, + timeout:float=None) -> DownloadMission: ... def to_upload(self, file_paths: Union[str, Path, list, tuple], by_js: bool = False) -> None: ... From 0e57938e23a2cbe398a4fc0505518c3ecbe214ea Mon Sep 17 00:00:00 2001 From: g1879 Date: Fri, 9 Feb 2024 21:46:34 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E8=B0=83=E6=95=B4quit()=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_base/browser.py | 49 ++++++++++++++++--------------- DrissionPage/_functions/tools.py | 36 ----------------------- DrissionPage/_functions/tools.pyi | 3 -- 3 files changed, 26 insertions(+), 62 deletions(-) diff --git a/DrissionPage/_base/browser.py b/DrissionPage/_base/browser.py index ce41cff..86caffe 100644 --- a/DrissionPage/_base/browser.py +++ b/DrissionPage/_base/browser.py @@ -7,12 +7,12 @@ """ from pathlib import Path from shutil import rmtree -from time import sleep, perf_counter +from time import perf_counter, sleep from websocket import WebSocketBadStatusException from .driver import BrowserDriver, Driver -from .._functions.tools import stop_process_on_port, raise_error +from .._functions.tools import raise_error from .._units.downloader import DownloadManager from ..errors import PageDisconnectedError @@ -196,38 +196,41 @@ class Browser(object): :param force: 是否立刻强制终止进程 :return: None """ + pids = [pid['id'] for pid in self.run_cdp('SystemInfo.getProcessInfo')['processInfo']] for tab in self._all_drivers.values(): for driver in tab: driver.stop() - try: - self.run_cdp('Browser.close') - except PageDisconnectedError: - self.driver.stop() - return - self.driver.stop() if force: - ip, port = self.address.split(':') - if ip not in ('127.0.0.1', 'localhost'): - return - stop_process_on_port(port, self.process_id) - return + from psutil import Process + for pid in pids: + Process(pid).kill() + else: + try: + self.run_cdp('Browser.close') + self.driver.stop() + except PageDisconnectedError: + self.driver.stop() - if self.process_id: - from os import popen - from platform import system - txt = f'tasklist | findstr {self.process_id}' if system().lower() == 'windows' \ - else f'ps -ef | grep {self.process_id}' - end_time = perf_counter() + timeout - while perf_counter() < end_time: + from os import popen + from platform import system + end_time = perf_counter() + timeout + while perf_counter() < end_time: + ok = True + for pid in pids: + txt = f'tasklist | findstr {pid}' if system().lower() == 'windows' else f'ps -ef | grep {pid}' p = popen(txt) - sleep(.1) + sleep(.05) try: - if f' {self.process_id} ' not in p.read(): - return + if f' {pid} ' in p.read(): + ok = False + break except TypeError: pass + if ok: + break + def _on_disconnect(self): self.page._on_disconnect() Browser.BROWSERS.pop(self.id, None) diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index c2ec84e..38640cf 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -12,8 +12,6 @@ from tempfile import gettempdir, TemporaryDirectory from threading import Lock from time import perf_counter -from psutil import process_iter, AccessDenied, NoSuchProcess, ZombieProcess, Process - from .._configs.options_manage import OptionsManager from ..errors import (ContextLostError, ElementLostError, CDPError, PageDisconnectedError, NoRectError, AlertExistsError, WrongURLError, StorageError, CookieFormatError, JavaScriptError) @@ -182,40 +180,6 @@ def wait_until(function, kwargs=None, timeout=10): raise TimeoutError -def stop_process_on_port(port, pid=None): - """强制关闭某个端口内的进程 - :param port: 端口号 - :param pid: 进程号 - :return: None - """ - if pid: - try: - for p in Process(pid).children(): - p.terminate() - Process(pid).terminate() - except: - pass - - for proc in process_iter(['pid', 'connections']): - try: - connections = proc.connections() - except (AccessDenied, NoSuchProcess): - continue - for conn in connections: - if conn.laddr.port == int(port): - try: - # proc.terminate() - parent = proc.parent() - if parent is None: - proc.kill() - elif parent.name() == 'explorer.exe': - proc.terminate() - except (NoSuchProcess, AccessDenied, ZombieProcess): - pass - except Exception as e: - print(f"{proc.pid} {port}: {e}") - - def configs_to_here(save_name=None): """把默认ini文件复制到当前目录 :param save_name: 指定文件名,为None则命名为'dp_configs.ini' diff --git a/DrissionPage/_functions/tools.pyi b/DrissionPage/_functions/tools.pyi index f6b55c0..86d3527 100644 --- a/DrissionPage/_functions/tools.pyi +++ b/DrissionPage/_functions/tools.pyi @@ -42,9 +42,6 @@ def get_hwnds_from_pid(pid: Union[str, int], title: str) -> list: ... def wait_until(function: callable, kwargs: dict = None, timeout: float = 10): ... -def stop_process_on_port(port: Union[int, str], pid: int = None) -> None: ... - - def configs_to_here(file_name: Union[Path, str] = None) -> None: ...