From 4f12493edb882559f21e53f1d8e587bc9f6b9e7f Mon Sep 17 00:00:00 2001 From: g1879 Date: Thu, 18 Jan 2024 01:06:50 +0800 Subject: [PATCH 1/9] =?UTF-8?q?4.0.3=E5=A2=9E=E5=8A=A0DrissionPage.items?= =?UTF-8?q?=EF=BC=9B=E4=BF=AE=E5=A4=8D=E5=90=88=E5=B9=B6=E4=BA=86=E6=97=A7?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0get=5Fblob()=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/__init__.py | 2 +- DrissionPage/_configs/options_manage.py | 6 ++-- DrissionPage/_configs/options_manage.pyi | 5 --- DrissionPage/_elements/chromium_element.py | 38 +++++----------------- DrissionPage/_elements/session_element.py | 22 ++++++------- DrissionPage/_functions/tools.py | 2 ++ DrissionPage/_functions/web.py | 27 +++++++++++++++ DrissionPage/_functions/web.pyi | 3 ++ DrissionPage/_units/setter.py | 7 +++- DrissionPage/common.py | 3 +- DrissionPage/items.py | 9 +++++ setup.py | 2 +- 12 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 DrissionPage/items.py diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index 06964d5..91fc392 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.2' +__version__ = '4.0.3' diff --git a/DrissionPage/_configs/options_manage.py b/DrissionPage/_configs/options_manage.py index 703adbd..bb5d964 100644 --- a/DrissionPage/_configs/options_manage.py +++ b/DrissionPage/_configs/options_manage.py @@ -8,6 +8,7 @@ from configparser import RawConfigParser, NoSectionError, NoOptionError from pathlib import Path from pprint import pprint +from time import sleep class OptionsManager(object): @@ -28,8 +29,9 @@ class OptionsManager(object): self.ini_path = str(path) if not Path(self.ini_path).exists(): - input('\nini文件不存在。\n如果是打包使用,请查看打包注意事项\nhttps://g1879.gitee.io/drission' - 'pagedocs/advance/packaging/') + print('\nini文件不存在。\n如果是打包使用,请查看打包注意事项\n' + 'https://g1879.gitee.io/drissionpagedocs/advance/packaging/') + sleep(10) self._conf = RawConfigParser() self._conf.read(self.ini_path, encoding='utf-8') diff --git a/DrissionPage/_configs/options_manage.pyi b/DrissionPage/_configs/options_manage.pyi index 805ae92..6bb3e4f 100644 --- a/DrissionPage/_configs/options_manage.pyi +++ b/DrissionPage/_configs/options_manage.pyi @@ -12,11 +12,6 @@ from typing import Any class OptionsManager(object): ini_path: str = ... _conf: RawConfigParser = ... - paths: dict = ... - chrome_options: dict = ... - session_options: dict = ... - timeouts: dict = ... - proxies: dict = ... def __init__(self, path: str = None): ... diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index a7e49fe..90fa300 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -19,7 +19,7 @@ from .._base.base import DrissionElement, BaseElement from .._functions.keys import input_text_or_keys from .._functions.locator import get_loc from .._functions.settings import Settings -from .._functions.web import make_absolute_link, get_ele_txt, format_html, is_js_func, offset_scroll +from .._functions.web import make_absolute_link, get_ele_txt, format_html, is_js_func, offset_scroll, get_blob from .._units.clicker import Clicker from .._units.rect import ElementRect from .._units.scroller import ElementScroller @@ -495,26 +495,9 @@ class ChromiumElement(DrissionElement): end_time = perf_counter() + timeout while perf_counter() < end_time: if is_blob: - js = """ - function fetchData(url) { - return new Promise((resolve, reject) => { - var xhr = new XMLHttpRequest(); - xhr.responseType = 'blob'; - xhr.onload = function() { - var reader = new FileReader(); - reader.onloadend = function() {resolve(reader.result);} - reader.readAsDataURL(xhr.response); - }; - xhr.open('GET', url, true); - xhr.send(); - }); - } - """ - try: - result = self.page.run_js(js, src) + result = get_blob(self.page, src, base64_to_bytes) + if result: break - except: - continue else: src = self.prop('currentSrc') @@ -534,18 +517,13 @@ class ChromiumElement(DrissionElement): return None if is_blob: - if base64_to_bytes: - from base64 import b64decode - return b64decode(result.split(',', 1)[-1]) - else: - return result + return result + if result['base64Encoded'] and base64_to_bytes: + from base64 import b64decode + return b64decode(result['content']) else: - if result['base64Encoded'] and base64_to_bytes: - from base64 import b64decode - return b64decode(result['content']) - else: - return result['content'] + return result['content'] def save(self, path=None, name=None, timeout=None): """保存图片或其它有src属性的元素的资源 diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index 5ab59f3..b8b9f9d 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -40,7 +40,7 @@ class SessionElement(DrissionElement): """在内部查找元素 例:ele2 = ele1('@id=ele_id') :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 不起实际作用,用于和DriverElement对应,便于无差别调用 + :param timeout: 不起实际作用 :return: SessionElement对象或属性、文本 """ return self.ele(loc_or_str) @@ -80,12 +80,13 @@ class SessionElement(DrissionElement): """返回未格式化处理的元素内文本""" return str(self._inner_ele.text_content()) - def parent(self, level_or_loc=1): + def parent(self, level_or_loc=1, index=1): """返回上面某一级父元素,可指定层数或用查询语法定位 :param level_or_loc: 第几级父元素,或定位符 + :param index: 当level_or_loc传入定位符,使用此参数选择第几个结果 :return: 上级元素对象 """ - return super().parent(level_or_loc) + return super().parent(level_or_loc, index) def child(self, filter_loc='', index=1, timeout=None, ele_only=True): """返回当前元素的一个符合条件的直接子元素,可用查询语法筛选,可指定返回筛选结果的第几个 @@ -95,7 +96,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本 """ - return super().child(index, filter_loc, timeout, ele_only=ele_only) + return super().child(filter_loc, index, timeout, ele_only=ele_only) def prev(self, filter_loc='', index=1, timeout=None, ele_only=True): """返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 @@ -105,7 +106,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素 """ - return super().prev(index, filter_loc, timeout, ele_only=ele_only) + return super().prev(filter_loc, index, timeout, ele_only=ele_only) def next(self, filter_loc='', index=1, timeout=None, ele_only=True): """返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 @@ -115,7 +116,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素 """ - return super().next(index, filter_loc, timeout, ele_only=ele_only) + return super().next(filter_loc, index, timeout, ele_only=ele_only) def before(self, filter_loc='', index=1, timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 @@ -126,7 +127,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的某个元素或节点 """ - return super().before(index, filter_loc, timeout, ele_only=ele_only) + return super().before(filter_loc, index, timeout, ele_only=ele_only) def after(self, filter_loc='', index=1, timeout=None, ele_only=True): """返回文档中此当前元素后面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 @@ -137,7 +138,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的某个元素或节点 """ - return super().after(index, filter_loc, timeout, ele_only=ele_only) + return super().after(filter_loc, index, timeout, ele_only=ele_only) def children(self, filter_loc='', timeout=0, ele_only=True): """返回当前元素符合条件的直接子元素或节点组成的列表,可用查询语法筛选 @@ -231,7 +232,7 @@ class SessionElement(DrissionElement): def eles(self, loc_or_str, timeout=None): """返回当前元素下级所有符合条件的子元素、属性或节点文本 :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 不起实际作用,用于和DriverElement对应,便于无差别调用 + :param timeout: 不起实际作用 :return: SessionElement对象或属性、文本组成的列表 """ return self._ele(loc_or_str, index=None) @@ -327,8 +328,7 @@ def make_session_ele(html_or_ele, loc=None, index=1): loc = loc[0], loc_str - # ChromiumElement, DriverElement - elif the_type.endswith((".ChromiumElement'>", ".DriverElement'>")): + elif the_type.endswith(".ChromiumElement'>"): loc_str = loc[1] if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'): loc_str = f'.{loc[1]}' diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index b785ed1..3e7f8ff 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -215,6 +215,8 @@ def raise_error(result, ignore=None): r = CookieFormatError(f'cookie格式不正确:{result["args"]}') elif error == 'Given expression does not evaluate to a function': r = JavaScriptError(f'传入的js无法解析成函数:\n{result["args"]["functionDeclaration"]}') + elif error.endswith("' wasn't found"): + r = RuntimeError(f'你的浏览器可能太旧。\nmethod:{result["method"]}\nargs:{result["args"]}') elif result['type'] in ('call_method_error', 'timeout'): from DrissionPage import __version__ from time import process_time diff --git a/DrissionPage/_functions/web.py b/DrissionPage/_functions/web.py index 9479c05..f3a458e 100644 --- a/DrissionPage/_functions/web.py +++ b/DrissionPage/_functions/web.py @@ -328,3 +328,30 @@ def is_cookie_in_driver(page, cookie): if cookie['name'] == c['name'] and cookie['value'] == c['value']: return True return False + + +def get_blob(page, url, base64_to_bytes=True): + if not url.startswith('blob'): + return None + js = """ + function fetchData(url) { + return new Promise((resolve, reject) => { + var xhr = new XMLHttpRequest(); + xhr.responseType = 'blob'; + xhr.onload = function() { + var reader = new FileReader(); + reader.onloadend = function(){resolve(reader.result);} + reader.readAsDataURL(xhr.response); + }; + xhr.open('GET', url, true); + xhr.send(); + }); + } +""" + try: + result = page.run_js(js, url) + except: + return None + if base64_to_bytes: + from base64 import b64decode + return b64decode(result.split(',', 1)[-1]) diff --git a/DrissionPage/_functions/web.pyi b/DrissionPage/_functions/web.pyi index 240bdab..e86b124 100644 --- a/DrissionPage/_functions/web.pyi +++ b/DrissionPage/_functions/web.pyi @@ -47,3 +47,6 @@ def set_browser_cookies(page: ChromiumBase, cookies: Union[RequestsCookieJar, li def is_cookie_in_driver(page: ChromiumBase, cookie: dict) -> bool: ... + + +def get_blob(page: ChromiumBase, url: str, base64_to_bytes: bool = True) -> bytes: ... diff --git a/DrissionPage/_units/setter.py b/DrissionPage/_units/setter.py index 17e4b44..2e10d4f 100644 --- a/DrissionPage/_units/setter.py +++ b/DrissionPage/_units/setter.py @@ -6,6 +6,7 @@ @License : BSD 3-Clause. """ from pathlib import Path +from time import sleep from requests.structures import CaseInsensitiveDict @@ -608,7 +609,11 @@ class WindowSetter(object): def _get_info(self): """获取窗口位置及大小信息""" - return self._page.run_cdp('Browser.getWindowForTarget') + for _ in range(50): + try: + return self._page.run_cdp('Browser.getWindowForTarget') + except: + sleep(.1) def _perform(self, bounds): """执行改变窗口大小操作 diff --git a/DrissionPage/common.py b/DrissionPage/common.py index df2b6aa..5c1e2b8 100644 --- a/DrissionPage/common.py +++ b/DrissionPage/common.py @@ -10,6 +10,7 @@ from ._functions.by import By from ._functions.keys import Keys from ._functions.settings import Settings from ._functions.tools import wait_until, configs_to_here +from ._functions.web import get_blob from ._units.actions import Actions -__all__ = ['make_session_ele', 'Actions', 'Keys', 'By', 'Settings', 'wait_until', 'configs_to_here'] +__all__ = ['make_session_ele', 'Actions', 'Keys', 'By', 'Settings', 'wait_until', 'configs_to_here', 'get_blob'] diff --git a/DrissionPage/items.py b/DrissionPage/items.py new file mode 100644 index 0000000..fea5bb6 --- /dev/null +++ b/DrissionPage/items.py @@ -0,0 +1,9 @@ +# -*- coding:utf-8 -*- +from ._elements.chromium_element import ChromiumElement, ShadowRoot +from ._elements.none_element import NoneElement +from ._elements.session_element import SessionElement +from ._pages.chromium_frame import ChromiumFrame +from ._pages.chromium_tab import ChromiumTab, WebPageTab + +__all__ = ['ChromiumElement', 'ShadowRoot', 'NoneElement', 'SessionElement', 'ChromiumFrame', 'ChromiumTab', + 'WebPageTab'] diff --git a/setup.py b/setup.py index f228274..2a450f9 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh: setup( name="DrissionPage", - version="4.0.2", + version="4.0.3", author="g1879", author_email="g1879@qq.com", description="Python based web automation tool. It can control the browser and send and receive data packets.", From 5815474ea982cbbb9a539b17b38228c022d94270 Mon Sep 17 00:00:00 2001 From: g1879 Date: Thu, 18 Jan 2024 10:43:11 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BB=A7=E6=89=BF?= =?UTF-8?q?=E5=90=8E=E5=87=BA=E7=8E=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_base/base.py | 2 ++ DrissionPage/_base/base.pyi | 1 + DrissionPage/_elements/chromium_element.py | 2 ++ DrissionPage/_elements/session_element.py | 15 +++++++-------- DrissionPage/_pages/chromium_base.py | 13 +++++++------ DrissionPage/_pages/chromium_base.pyi | 3 ++- DrissionPage/_pages/chromium_frame.py | 6 +++--- DrissionPage/_pages/chromium_page.py | 1 + DrissionPage/_pages/chromium_tab.py | 2 ++ DrissionPage/_pages/session_page.py | 1 + DrissionPage/_pages/web_page.py | 1 + DrissionPage/_units/actions.py | 2 +- DrissionPage/_units/scroller.py | 4 ++-- 13 files changed, 32 insertions(+), 21 deletions(-) diff --git a/DrissionPage/_base/base.py b/DrissionPage/_base/base.py index a5322e4..9ecf2b1 100644 --- a/DrissionPage/_base/base.py +++ b/DrissionPage/_base/base.py @@ -53,6 +53,7 @@ class BaseElement(BaseParser): def __init__(self, page=None): self.page = page + self._type = 'BaseElement' # ----------------以下属性或方法由后代实现---------------- @property @@ -362,6 +363,7 @@ class BasePage(BaseParser): self._download_path = None self._none_ele_return_value = False self._none_ele_value = None + self._type = 'BasePage' @property def title(self): diff --git a/DrissionPage/_base/base.pyi b/DrissionPage/_base/base.pyi index 568a35e..1642529 100644 --- a/DrissionPage/_base/base.pyi +++ b/DrissionPage/_base/base.pyi @@ -14,6 +14,7 @@ from .._elements.none_element import NoneElement class BaseParser(object): + _type: str def __call__(self, loc_or_str: Union[Tuple[str, str], str], index: int = 1): ... diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index 90fa300..8a20a44 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -53,6 +53,7 @@ class ChromiumElement(DrissionElement): self._clicker = None self._tag = None self._wait = None + self._type = 'ChromiumElement' if node_id and obj_id and backend_id: self._node_id = node_id @@ -783,6 +784,7 @@ class ShadowRoot(BaseElement): self._node_id = self._get_node_id(obj_id) self._backend_id = self._get_backend_id(self._node_id) self._states = None + self._type = 'ShadowRoot' def __repr__(self): return f'' diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index b8b9f9d..7c67b63 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -305,9 +305,13 @@ def make_session_ele(html_or_ele, loc=None, index=1): raise ValueError("定位符必须为str或长度为2的tuple。") # ---------------根据传入对象类型获取页面对象和lxml元素对象--------------- - the_type = str(type(html_or_ele)) + # 直接传入html文本 + if isinstance(html_or_ele, str): + page = None + html_or_ele = fromstring(html_or_ele) + # SessionElement - if the_type.endswith(".SessionElement'>"): + elif html_or_ele._type == 'SessionElement': page = html_or_ele.page loc_str = loc[1] @@ -328,7 +332,7 @@ def make_session_ele(html_or_ele, loc=None, index=1): loc = loc[0], loc_str - elif the_type.endswith(".ChromiumElement'>"): + elif html_or_ele._type == 'ChromiumElement': loc_str = loc[1] if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'): loc_str = f'.{loc[1]}' @@ -353,11 +357,6 @@ def make_session_ele(html_or_ele, loc=None, index=1): html = sub(r'^<\?xml.*?>', '', html) html_or_ele = fromstring(html) - # 直接传入html文本 - elif isinstance(html_or_ele, str): - page = None - html_or_ele = fromstring(html_or_ele) - # ShadowRoot elif isinstance(html_or_ele, BaseElement): page = html_or_ele.page diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 9967f0f..26092eb 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -16,7 +16,7 @@ from urllib.parse import quote from DataRecorder.tools import make_valid_name from .._base.base import BasePage -from .._elements.chromium_element import ChromiumElement, run_js, make_chromium_eles +from .._elements.chromium_element import run_js, make_chromium_eles from .._elements.none_element import NoneElement from .._elements.session_element import make_session_ele from .._functions.locator import get_loc, is_loc @@ -62,6 +62,7 @@ class ChromiumBase(BasePage): self._download_path = None self._load_end_time = 0 self._init_jss = [] + self._type = 'ChromiumBase' if not hasattr(self, '_listener'): self._listener = None @@ -541,7 +542,7 @@ class ChromiumBase(BasePage): """ if isinstance(loc_or_ele, (str, tuple)): loc = get_loc(loc_or_ele)[1] - elif isinstance(loc_or_ele, ChromiumElement) or str(type(loc_or_ele)).endswith(".ChromiumFrame'>"): + elif loc_or_ele._type in ('ChromiumElement', 'ChromiumFrame'): return loc_or_ele else: raise ValueError('loc_or_str参数只能是tuple、str、ChromiumElement类型。') @@ -680,13 +681,13 @@ class ChromiumBase(BasePage): else: xpath = loc_ind_ele ele = self._ele(xpath, timeout=timeout) - if ele and not str(type(ele)).endswith(".ChromiumFrame'>"): + if ele and ele._type != 'ChromiumFrame': raise TypeError('该定位符不是指向frame元素。') r = ele elif isinstance(loc_ind_ele, tuple): ele = self._ele(loc_ind_ele, timeout=timeout) - if ele and not str(type(ele)).endswith(".ChromiumFrame'>"): + if ele and ele._type != 'ChromiumFrame': raise TypeError('该定位符不是指向frame元素。') r = ele @@ -698,7 +699,7 @@ class ChromiumBase(BasePage): xpath = f'xpath:(//*[name()="frame" or name()="iframe"])[{loc_ind_ele}]' r = self._ele(xpath, timeout=timeout) - elif str(type(loc_ind_ele)).endswith(".ChromiumFrame'>"): + elif loc_ind_ele._type == 'ChromiumFrame': r = loc_ind_ele else: @@ -717,7 +718,7 @@ class ChromiumBase(BasePage): """ loc = loc or 'xpath://*[name()="iframe" or name()="frame"]' frames = self._ele(loc, timeout=timeout, index=None, raise_err=False) - return [i for i in frames if str(type(i)).endswith(".ChromiumFrame'>")] + return [i for i in frames if i._type == 'ChromiumFrame'] def get_session_storage(self, item=None): """获取sessionStorage信息,不设置item则获取全部 diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index ae21e4f..8b10867 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -62,6 +62,7 @@ class ChromiumBase(BasePage): self._init_jss: list = ... self._ready_state: Optional[str] = ... self._rect: TabRect = ... + self._type: str = ... def _connect_browser(self, tab_id: str = None) -> None: ... @@ -190,7 +191,7 @@ class ChromiumBase(BasePage): def s_ele(self, loc_or_ele: Union[Tuple[str, str], str] = None, - index:int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> Union[SessionElement, NoneElement]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... diff --git a/DrissionPage/_pages/chromium_frame.py b/DrissionPage/_pages/chromium_frame.py index e224b23..f947823 100644 --- a/DrissionPage/_pages/chromium_frame.py +++ b/DrissionPage/_pages/chromium_frame.py @@ -27,15 +27,14 @@ class ChromiumFrame(ChromiumBase): :param ele: frame所在元素 :param info: frame所在元素信息 """ - page_type = str(type(page)) - if 'ChromiumPage' in page_type or 'WebPage' in page_type: + if page._type in ('ChromiumPage', 'WebPage'): self._page = self._target_page = self.tab = page self._browser = page.browser else: # Tab、Frame self._page = page.page self._browser = self._page.browser self._target_page = page - self.tab = page.tab if 'ChromiumFrame' in page_type else page + self.tab = page.tab if page._type == 'ChromiumFrame' else page self.address = page.address self._tab_id = page.tab_id @@ -58,6 +57,7 @@ class ChromiumFrame(ChromiumBase): self.doc_ele = ChromiumElement(self, obj_id=obj_id) self._rect = None + self._type = 'ChromiumFrame' end_time = perf_counter() + 2 while perf_counter() < end_time: if self.url not in (None, 'about:blank'): diff --git a/DrissionPage/_pages/chromium_page.py b/DrissionPage/_pages/chromium_page.py index f7d4ac5..64f83e1 100644 --- a/DrissionPage/_pages/chromium_page.py +++ b/DrissionPage/_pages/chromium_page.py @@ -56,6 +56,7 @@ class ChromiumPage(ChromiumBase): self._page = self self._run_browser() super().__init__(self.address, tab_id) + self._type = 'ChromiumPage' self.set.timeouts(base=timeout) self._page_init() diff --git a/DrissionPage/_pages/chromium_tab.py b/DrissionPage/_pages/chromium_tab.py index 9764f8d..0b11bf0 100644 --- a/DrissionPage/_pages/chromium_tab.py +++ b/DrissionPage/_pages/chromium_tab.py @@ -45,6 +45,7 @@ class ChromiumTab(ChromiumBase): self._browser = page.browser super().__init__(page.address, tab_id, page.timeout) self._rect = None + self._type = 'ChromiumTab' def _d_set_runtime_settings(self): """重写设置浏览器运行参数方法""" @@ -106,6 +107,7 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): super().__init__(session_or_options=SessionOptions(read_file=False).from_session(copy(page.session), page._headers)) super(SessionPage, self).__init__(page=page, tab_id=tab_id) + self._type = 'WebPageTab' def __call__(self, loc_or_str, index=1, timeout=None): """在内部查找元素 diff --git a/DrissionPage/_pages/session_page.py b/DrissionPage/_pages/session_page.py index bbc8e16..2065f96 100644 --- a/DrissionPage/_pages/session_page.py +++ b/DrissionPage/_pages/session_page.py @@ -35,6 +35,7 @@ class SessionPage(BasePage): self._session = None self._set = None self._encoding = None + self._type = 'SessionPage' self._s_set_start_options(session_or_options) self._s_set_runtime_settings() self._create_session() diff --git a/DrissionPage/_pages/web_page.py b/DrissionPage/_pages/web_page.py index 8727e3f..95f2154 100644 --- a/DrissionPage/_pages/web_page.py +++ b/DrissionPage/_pages/web_page.py @@ -48,6 +48,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): chromium_options = ChromiumOptions(read_file=chromium_options) chromium_options.set_timeouts(base=self._timeout).set_paths(download_path=self.download_path) super(SessionPage, self).__init__(addr_or_opts=chromium_options, timeout=timeout) + self._type = 'WebPage' self.change_mode(self._mode, go=False, copy_cookies=False) def __call__(self, loc_or_str, index=1, timeout=None): diff --git a/DrissionPage/_units/actions.py b/DrissionPage/_units/actions.py index 0a41be9..c66787c 100644 --- a/DrissionPage/_units/actions.py +++ b/DrissionPage/_units/actions.py @@ -39,7 +39,7 @@ class Actions: is_loc = True lx = ele_or_loc[0] + offset_x ly = ele_or_loc[1] + offset_y - elif isinstance(ele_or_loc, str) or 'ChromiumElement' in str(type(ele_or_loc)): + elif isinstance(ele_or_loc, str) or ele_or_loc._type == 'ChromiumElement': ele_or_loc = self.page(ele_or_loc) self.page.scroll.to_see(ele_or_loc) x, y = ele_or_loc.rect.location if offset_x or offset_y else ele_or_loc.rect.midpoint diff --git a/DrissionPage/_units/scroller.py b/DrissionPage/_units/scroller.py index 545b3f7..d59e98a 100644 --- a/DrissionPage/_units/scroller.py +++ b/DrissionPage/_units/scroller.py @@ -87,7 +87,7 @@ class Scroller(object): if not self._wait_complete: return - page = self._driver.page if 'ChromiumElement' in str(type(self._driver)) else self._driver + page = self._driver.page if self._driver._type == 'ChromiumElement' else self._driver r = page.run_cdp('Page.getLayoutMetrics') x = r['layoutViewport']['pageX'] y = r['layoutViewport']['pageY'] @@ -173,5 +173,5 @@ class FrameScroller(PageScroller): :param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中 :return: None """ - ele = loc_or_ele if 'ChromiumElement' in str(type(loc_or_ele)) else self._driver._ele(loc_or_ele) + ele = loc_or_ele if loc_or_ele._type == 'ChromiumElement' else self._driver._ele(loc_or_ele) self._to_see(ele, center) From 8ec59c32936f129fc366851e3336ba7e906c5d1b Mon Sep 17 00:00:00 2001 From: g1879 Date: Thu, 18 Jan 2024 12:01:02 +0800 Subject: [PATCH 3/9] =?UTF-8?q?4.0.3=E6=94=B9=E5=96=84get=5Fblob()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_elements/chromium_element.py | 4 ++-- DrissionPage/_functions/web.py | 4 ++-- DrissionPage/items.py | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index 8a20a44..ca373e1 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -517,10 +517,10 @@ class ChromiumElement(DrissionElement): if not result: return None - if is_blob: + elif is_blob: return result - if result['base64Encoded'] and base64_to_bytes: + elif result['base64Encoded'] and base64_to_bytes: from base64 import b64decode return b64decode(result['content']) else: diff --git a/DrissionPage/_functions/web.py b/DrissionPage/_functions/web.py index f3a458e..f731162 100644 --- a/DrissionPage/_functions/web.py +++ b/DrissionPage/_functions/web.py @@ -332,7 +332,7 @@ def is_cookie_in_driver(page, cookie): def get_blob(page, url, base64_to_bytes=True): if not url.startswith('blob'): - return None + raise TypeError('该链接非blob类型。') js = """ function fetchData(url) { return new Promise((resolve, reject) => { @@ -351,7 +351,7 @@ def get_blob(page, url, base64_to_bytes=True): try: result = page.run_js(js, url) except: - return None + raise RuntimeError('无法获取该资源。') if base64_to_bytes: from base64 import b64decode return b64decode(result.split(',', 1)[-1]) diff --git a/DrissionPage/items.py b/DrissionPage/items.py index fea5bb6..0715e91 100644 --- a/DrissionPage/items.py +++ b/DrissionPage/items.py @@ -1,4 +1,10 @@ # -*- coding:utf-8 -*- +""" +@Author : g1879 +@Contact : g1879@qq.com +@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. +@License : BSD 3-Clause. +""" from ._elements.chromium_element import ChromiumElement, ShadowRoot from ._elements.none_element import NoneElement from ._elements.session_element import SessionElement From f485cfc7a6f521a97d3d7e57d97dde3c96e7232f Mon Sep 17 00:00:00 2001 From: g1879 Date: Fri, 19 Jan 2024 00:48:16 +0800 Subject: [PATCH 4/9] =?UTF-8?q?4.0.3.1=E5=A2=9E=E5=8A=A0reconnect()?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=9B=E4=BC=98=E5=8C=96=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E9=A1=B5=E9=80=BB=E8=BE=91=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=E5=A4=8Ds=5Fele()=E5=90=8E=E5=AE=9A=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_base/browser.py | 33 ++++++++++++++++++----- DrissionPage/_base/browser.pyi | 7 +++-- DrissionPage/_elements/session_element.py | 1 + DrissionPage/_pages/chromium_base.py | 11 +++++++- DrissionPage/_pages/chromium_base.pyi | 2 ++ DrissionPage/_pages/chromium_page.py | 2 +- setup.py | 2 +- 8 files changed, 48 insertions(+), 12 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index 91fc392..78fa124 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.3' +__version__ = '4.0.3.1' diff --git a/DrissionPage/_base/browser.py b/DrissionPage/_base/browser.py index 7c6918b..42a132b 100644 --- a/DrissionPage/_base/browser.py +++ b/DrissionPage/_base/browser.py @@ -49,7 +49,7 @@ class Browser(object): self.id = browser_id self._frames = {} self._drivers = {} - # self._drivers = {t: Driver(t, 'page', address) for t in self.tabs} + self._all_drivers = {} self._connected = False self._process_id = None @@ -64,20 +64,24 @@ class Browser(object): self._driver.set_callback('Target.targetCreated', self._onTargetCreated) def _get_driver(self, tab_id, owner=None): - """获取对应tab id的Driver + """新建并返回指定tab id的Driver :param tab_id: 标签页id :param owner: 使用该驱动的对象 :return: Driver对象 """ - return self._drivers.pop(tab_id, Driver(tab_id, 'page', self.address, owner)) + d = self._drivers.pop(tab_id, Driver(tab_id, 'page', self.address, owner)) + self._all_drivers.setdefault(tab_id, set()).add(d) + return d def _onTargetCreated(self, **kwargs): """标签页创建时执行""" if (kwargs['targetInfo']['type'] in ('page', 'webview') and not kwargs['targetInfo']['url'].startswith('devtools://')): try: - self._drivers[kwargs['targetInfo']['targetId']] = Driver(kwargs['targetInfo']['targetId'], - 'page', self.address) + tab_id = kwargs['targetInfo']['targetId'] + d = Driver(tab_id, 'page', self.address) + self._drivers[tab_id] = d + self._all_drivers.setdefault(tab_id, set()).add(d) except WebSocketBadStatusException: pass @@ -88,7 +92,10 @@ class Browser(object): self._dl_mgr.clear_tab_info(tab_id) for key in [k for k, i in self._frames.items() if i == tab_id]: self._frames.pop(key, None) + for d in self._all_drivers.get(tab_id, tuple()): + d.stop() self._drivers.pop(tab_id, None) + self._all_drivers.pop(tab_id, None) def connect_to_page(self): """执行与page相关的逻辑""" @@ -153,7 +160,16 @@ class Browser(object): :param tab_id: 标签页id :return: None """ - self.run_cdp('Target.closeTarget', targetId=tab_id, _ignore=PageDisconnectedError) + self._onTargetDestroyed(targetId=tab_id) + self.driver.run('Target.closeTarget', targetId=tab_id) + + def stop_driver(self, driver): + """停止一个Driver + :param driver: Driver对象 + :return: None + """ + driver.stop() + self._all_drivers.get(driver.id, set()).discard(driver) def activate_tab(self, tab_id): """使标签页变为活动状态 @@ -175,10 +191,15 @@ class Browser(object): :param force: 是否立刻强制终止进程 :return: None """ + 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(':') diff --git a/DrissionPage/_base/browser.pyi b/DrissionPage/_base/browser.pyi index d22aaf2..af3b2c7 100644 --- a/DrissionPage/_base/browser.pyi +++ b/DrissionPage/_base/browser.pyi @@ -5,7 +5,7 @@ @Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. @License : BSD 3-Clause. """ -from typing import List, Optional, Union +from typing import List, Optional, Union, Set, Dict from .driver import BrowserDriver, Driver from .._pages.chromium_page import ChromiumPage @@ -19,7 +19,8 @@ class Browser(object): id: str = ... address: str = ... _frames: dict = ... - _drivers: dict = ... + _drivers: Dict[str, Driver] = ... + _all_drivers: Dict[str, Set[Driver]] = ... _process_id: Optional[int] = ... _dl_mgr: DownloadManager = ... _connected: bool = ... @@ -49,6 +50,8 @@ class Browser(object): def close_tab(self, tab_id: str) -> None: ... + def stop_driver(self, driver: Driver) -> None: ... + def activate_tab(self, tab_id: str) -> None: ... def get_window_bounds(self, tab_id: str = None) -> dict: ... diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index 7c67b63..761668c 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -27,6 +27,7 @@ class SessionElement(DrissionElement): """ super().__init__(page) self._inner_ele = ele + self._type = 'SessionElement' @property def inner_ele(self): diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 26092eb..49d7721 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -827,7 +827,16 @@ class ChromiumBase(BasePage): def disconnect(self): """断开与页面的连接,不关闭页面""" if self._driver: - self.driver.stop() + self.browser.stop_driver(self._driver) + + def reconnect(self, wait=0): + """断开与页面原来的页面,重新建立连接 + :param wait: 断开后等待若干秒再连接 + :return: None + """ + self.disconnect() + sleep(wait) + self._driver = self.browser._get_driver(self._target_id, self) def handle_alert(self, accept=True, send=None, timeout=None, next_one=False): r = self._handle_alert(accept=accept, send=send, timeout=timeout, next_one=next_one) diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index 8b10867..8e9223f 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -244,6 +244,8 @@ class ChromiumBase(BasePage): def disconnect(self) -> None: ... + def reconnect(self, wait: float = 0) -> None: ... + def handle_alert(self, accept: bool = True, send: str = None, timeout: float = None, next_one: bool = False) -> Union[str, False]: ... diff --git a/DrissionPage/_pages/chromium_page.py b/DrissionPage/_pages/chromium_page.py index 64f83e1..9a01ac1 100644 --- a/DrissionPage/_pages/chromium_page.py +++ b/DrissionPage/_pages/chromium_page.py @@ -203,7 +203,7 @@ class ChromiumPage(ChromiumBase): def close(self): """关闭Page管理的标签页""" - self.browser.close_tab(self.tab_id) + self.close_tabs(self.tab_id) def close_tabs(self, tabs_or_ids=None, others=False): """关闭传入的标签页,默认关闭当前页。可传入多个 diff --git a/setup.py b/setup.py index 2a450f9..2f84c94 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh: setup( name="DrissionPage", - version="4.0.3", + version="4.0.3.1", author="g1879", author_email="g1879@qq.com", description="Python based web automation tool. It can control the browser and send and receive data packets.", From aea5aace530f75bb4610019b71bebe3f177f7b7f Mon Sep 17 00:00:00 2001 From: g1879 Date: Fri, 19 Jan 2024 01:00:16 +0800 Subject: [PATCH 5/9] =?UTF-8?q?4.0.3.2=E5=A2=9E=E5=8A=A0reconnect()?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=9B=E4=BC=98=E5=8C=96=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E9=A1=B5=E9=80=BB=E8=BE=91=EF=BC=9B=E4=BF=AE?= =?UTF-8?q?=E5=A4=8Ds=5Fele()=E5=90=8E=E5=AE=9A=E4=BD=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_pages/chromium_base.py | 3 ++- setup.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index 78fa124..25f0e09 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.3.1' +__version__ = '4.0.3.2' diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 49d7721..436e731 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -834,9 +834,10 @@ class ChromiumBase(BasePage): :param wait: 断开后等待若干秒再连接 :return: None """ + t_id = self._target_id self.disconnect() sleep(wait) - self._driver = self.browser._get_driver(self._target_id, self) + self._driver = self.browser._get_driver(t_id, self) def handle_alert(self, accept=True, send=None, timeout=None, next_one=False): r = self._handle_alert(accept=accept, send=send, timeout=timeout, next_one=next_one) diff --git a/setup.py b/setup.py index 2f84c94..0317688 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh: setup( name="DrissionPage", - version="4.0.3.1", + version="4.0.3.2", author="g1879", author_email="g1879@qq.com", description="Python based web automation tool. It can control the browser and send and receive data packets.", From 4db2f71d1574254fa453a2f3fc65ccc44bf4eae7 Mon Sep 17 00:00:00 2001 From: g1879 Date: Fri, 19 Jan 2024 16:04:41 +0800 Subject: [PATCH 6/9] =?UTF-8?q?4.0.3.3(+)=20=E4=BF=AE=E5=A4=8Dset=5Fbrowse?= =?UTF-8?q?r=5Fpath()=E5=AF=BC=E8=87=B4auto=5Fport()=E5=A4=B1=E6=95=88?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=9B=20=E9=87=8D=E6=9E=84wait=5Funtil()?= =?UTF-8?q?=EF=BC=9B=20ini=E6=96=87=E4=BB=B6=E5=A2=9E=E5=8A=A0'--disable-f?= =?UTF-8?q?eatures=3DPrivacySandboxSettings4'=EF=BC=9B=20get=5Fblob()?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=94=B9=E4=B8=BAas=5Fbytes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_configs/chromium_options.py | 1 - DrissionPage/_configs/configs.ini | 2 +- DrissionPage/_functions/tools.py | 41 ++++++----------------- DrissionPage/_functions/tools.pyi | 2 +- DrissionPage/_functions/web.py | 10 ++++-- DrissionPage/_functions/web.pyi | 2 +- README.md | 2 +- 8 files changed, 24 insertions(+), 38 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index 25f0e09..ebceae1 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.3.2' +__version__ = '4.0.3.3' diff --git a/DrissionPage/_configs/chromium_options.py b/DrissionPage/_configs/chromium_options.py index 11b56f2..d9ed2d7 100644 --- a/DrissionPage/_configs/chromium_options.py +++ b/DrissionPage/_configs/chromium_options.py @@ -448,7 +448,6 @@ class ChromiumOptions(object): :return: 当前对象 """ self._browser_path = str(path) - self._auto_port = False return self def set_download_path(self, path): diff --git a/DrissionPage/_configs/configs.ini b/DrissionPage/_configs/configs.ini index 3872ad9..f2de400 100644 --- a/DrissionPage/_configs/configs.ini +++ b/DrissionPage/_configs/configs.ini @@ -5,7 +5,7 @@ tmp_path = [chromium_options] address = 127.0.0.1:9222 browser_path = chrome -arguments = ['--no-default-browser-check', '--disable-suggestions-ui', '--no-first-run', '--disable-infobars', '--disable-popup-blocking', '--hide-crash-restore-bubble'] +arguments = ['--no-default-browser-check', '--disable-suggestions-ui', '--no-first-run', '--disable-infobars', '--disable-popup-blocking', '--hide-crash-restore-bubble', '--disable-features=PrivacySandboxSettings4'] extensions = [] prefs = {'profile.default_content_settings.popups': 0, 'profile.default_content_setting_values': {'notifications': 2}} flags = {} diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index 3e7f8ff..5f6b3bf 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -122,40 +122,21 @@ def get_chrome_hwnds_from_pid(pid, title): return hwnds -def wait_until(page, condition, timeout=10, poll=0.1, raise_err=True): - """等待返回值不为False或空,直到超时 - :param page: DrissionPage对象 - :param condition: 等待条件,返回值不为False则停止等待 +def wait_until(function, kwargs=None, timeout=10): + """等待传入的方法返回值不为假 + :param function: 要执行的方法 + :param kwargs: 方法参数 :param timeout: 超时时间(秒) - :param poll: 轮询间隔 - :param raise_err: 是否抛出异常 - :return: DP Element or bool + :return: 执行结果,超时抛出TimeoutError """ + if kwargs is None: + kwargs = {} end_time = perf_counter() + timeout - if isinstance(condition, str) or isinstance(condition, tuple): - if not callable(getattr(page, 's_ele', None)): - raise AttributeError('page对象缺少s_ele方法') - condition_method = lambda page: page.s_ele(condition) - elif callable(condition): - condition_method = condition - else: - raise ValueError('condition必须是函数或者字符串或者元组') while perf_counter() < end_time: - try: - value = condition_method(page) - if value: - return value - except Exception: - pass - - sleep(poll) - if perf_counter() > end_time: - break - - if raise_err: - raise TimeoutError(f'等待超时(等待{timeout}秒)。') - else: - return False + value = function(**kwargs) + if value: + return value + raise TimeoutError def stop_process_on_port(port): diff --git a/DrissionPage/_functions/tools.pyi b/DrissionPage/_functions/tools.pyi index 057a43f..8e0ae9b 100644 --- a/DrissionPage/_functions/tools.pyi +++ b/DrissionPage/_functions/tools.pyi @@ -28,7 +28,7 @@ def get_browser_progress_id(progress: Union[popen, None], address: str) -> Union def get_chrome_hwnds_from_pid(pid: Union[str, int], title: str) -> list: ... -def wait_until(page, condition: Union[FunctionType, str, tuple], timeout: float, poll: float, raise_err: bool): ... +def wait_until(function: callable, kwargs: dict = None, timeout: float = 10): ... def stop_process_on_port(port: Union[int, str]) -> None: ... diff --git a/DrissionPage/_functions/web.py b/DrissionPage/_functions/web.py index f731162..c34c778 100644 --- a/DrissionPage/_functions/web.py +++ b/DrissionPage/_functions/web.py @@ -330,7 +330,13 @@ def is_cookie_in_driver(page, cookie): return False -def get_blob(page, url, base64_to_bytes=True): +def get_blob(page, url, as_bytes=True): + """获取知道blob资源 + :param page: 资源所在页面对象 + :param url: 资源url + :param as_bytes: 是否以字节形式返回 + :return: 资源内容 + """ if not url.startswith('blob'): raise TypeError('该链接非blob类型。') js = """ @@ -352,6 +358,6 @@ def get_blob(page, url, base64_to_bytes=True): result = page.run_js(js, url) except: raise RuntimeError('无法获取该资源。') - if base64_to_bytes: + if as_bytes: from base64 import b64decode return b64decode(result.split(',', 1)[-1]) diff --git a/DrissionPage/_functions/web.pyi b/DrissionPage/_functions/web.pyi index e86b124..7b5daef 100644 --- a/DrissionPage/_functions/web.pyi +++ b/DrissionPage/_functions/web.pyi @@ -49,4 +49,4 @@ def set_browser_cookies(page: ChromiumBase, cookies: Union[RequestsCookieJar, li def is_cookie_in_driver(page: ChromiumBase, cookie: dict) -> bool: ... -def get_blob(page: ChromiumBase, url: str, base64_to_bytes: bool = True) -> bytes: ... +def get_blob(page: ChromiumBase, url: str, as_bytes: bool = True) -> bytes: ... diff --git a/README.md b/README.md index e2533f9..db38f30 100644 --- a/README.md +++ b/README.md @@ -123,4 +123,4 @@ python 版本:3.6 及以上 如果本项目对您有所帮助,不妨请作者我喝杯咖啡 :) -![](http://g1879.gitee.io/drissionpagedocs/imgs/code.jpg) +![](https://gitee.com/g1879/DrissionPageDocs/raw/master/docs/imgs/code.jpg) From 8aae35d31b73de0f07b1f5a4a0587869b9b6daf4 Mon Sep 17 00:00:00 2001 From: g1879 Date: Sun, 21 Jan 2024 01:08:54 +0800 Subject: [PATCH 7/9] =?UTF-8?q?4.0.3.4(+)=20=E4=BF=AE=E5=A4=8D=E5=A4=9A?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E5=90=8C=E6=97=B6=E5=88=9B=E5=BB=BA=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E9=A1=B5=E9=9D=A2=E5=AF=B9=E8=B1=A1=E6=97=B6=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E9=97=AE=E9=A2=98=EF=BC=9B=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E6=80=A7=E8=83=BD=E9=97=AE=E9=A2=98=EF=BC=9B?= =?UTF-8?q?=20stop=5Floading()=E4=BF=9D=E8=AF=81=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=8F=98=E6=88=90=E5=AE=8C=E6=88=90=EF=BC=9B=20auto=5Fport()?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0scope=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_base/browser.py | 17 ++++--- DrissionPage/_configs/chromium_options.py | 53 ++-------------------- DrissionPage/_configs/chromium_options.pyi | 21 +++------ DrissionPage/_functions/browser.py | 20 +------- DrissionPage/_functions/tools.py | 45 +++++++++++++++++- DrissionPage/_functions/tools.pyi | 15 +++++- DrissionPage/_pages/chromium_base.py | 8 ++-- DrissionPage/_pages/chromium_page.py | 40 ++++++++++------ DrissionPage/_pages/chromium_page.pyi | 2 + DrissionPage/_pages/chromium_tab.py | 6 ++- DrissionPage/_pages/chromium_tab.pyi | 2 + setup.py | 3 +- 13 files changed, 123 insertions(+), 111 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index ebceae1..a038814 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.3.3' +__version__ = '4.0.3.4' diff --git a/DrissionPage/_base/browser.py b/DrissionPage/_base/browser.py index 42a132b..89fd915 100644 --- a/DrissionPage/_base/browser.py +++ b/DrissionPage/_base/browser.py @@ -53,11 +53,14 @@ class Browser(object): self._connected = False self._process_id = None - r = self.run_cdp('SystemInfo.getProcessInfo') - for i in r.get('processInfo', []): - if i['type'] == 'browser': - self._process_id = i['id'] - break + try: + r = self.run_cdp('SystemInfo.getProcessInfo') + for i in r.get('processInfo', []): + if i['type'] == 'browser': + self._process_id = i['id'] + break + except: + pass self.run_cdp('Target.setDiscoverTargets', discover=True) self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed) @@ -69,13 +72,15 @@ class Browser(object): :param owner: 使用该驱动的对象 :return: Driver对象 """ - d = self._drivers.pop(tab_id, Driver(tab_id, 'page', self.address, owner)) + d = self._drivers.pop(tab_id, Driver(tab_id, 'page', self.address)) + d.owner = owner self._all_drivers.setdefault(tab_id, set()).add(d) return d def _onTargetCreated(self, **kwargs): """标签页创建时执行""" if (kwargs['targetInfo']['type'] in ('page', 'webview') + and kwargs['targetInfo']['targetId'] not in self._all_drivers and not kwargs['targetInfo']['url'].startswith('devtools://')): try: tab_id = kwargs['targetInfo']['targetId'] diff --git a/DrissionPage/_configs/chromium_options.py b/DrissionPage/_configs/chromium_options.py index d9ed2d7..b224634 100644 --- a/DrissionPage/_configs/chromium_options.py +++ b/DrissionPage/_configs/chromium_options.py @@ -7,12 +7,8 @@ """ from pathlib import Path from re import search -from shutil import rmtree -from tempfile import gettempdir, TemporaryDirectory -from threading import Lock from .options_manage import OptionsManager -from .._functions.tools import port_is_using, clean_folder class ChromiumOptions(object): @@ -64,10 +60,6 @@ class ChromiumOptions(object): 'script': timeouts['script']} self._auto_port = options.get('auto_port', False) - if self._auto_port: - port, path = PortFinder().get_port() - self._address = f'127.0.0.1:{port}' - self.set_argument('--user-data-dir', path) others = om.others self._retry_times = others.get('retry_times', 3) @@ -170,7 +162,7 @@ class ChromiumOptions(object): @property def is_auto_port(self): - """返回是否使用自动端口和用户文件""" + """返回是否使用自动端口和用户文件,如指定范围则返回范围tuple""" return self._auto_port @property @@ -493,14 +485,15 @@ class ChromiumOptions(object): self._system_user_path = on_off return self - def auto_port(self, on_off=True, tmp_path=None): + def auto_port(self, on_off=True, tmp_path=None, scope=None): """自动获取可用端口 :param on_off: 是否开启自动获取端口号 :param tmp_path: 临时文件保存路径,为None时保存到系统临时文件夹,on_off为False时此参数无效 + :param scope: 指定端口范围,不含最后的数字,为None则使用[9600-19600) :return: 当前对象 """ if on_off: - self._auto_port = True + self._auto_port = scope if scope else True if tmp_path: self._tmp_path = str(tmp_path) else: @@ -618,41 +611,3 @@ class ChromiumOptions(object): """ on_off = None if on_off else False return self.set_argument('--mute-audio', on_off) - - -class PortFinder(object): - used_port = {} - lock = Lock() - - def __init__(self, path=None): - """ - :param path: 临时文件保存路径,为None时使用系统临时文件夹 - """ - tmp = Path(path) if path else Path(gettempdir()) / 'DrissionPage' - self.tmp_dir = tmp / 'UserTempFolder' - self.tmp_dir.mkdir(parents=True, exist_ok=True) - if not PortFinder.used_port: - clean_folder(self.tmp_dir) - - def get_port(self): - """查找一个可用端口 - :return: 可以使用的端口和用户文件夹路径组成的元组 - """ - with PortFinder.lock: - for i in range(9600, 19600): - if i in PortFinder.used_port: - continue - elif port_is_using('127.0.0.1', i): - PortFinder.used_port[i] = None - continue - path = TemporaryDirectory(dir=self.tmp_dir).name - PortFinder.used_port[i] = path - return i, path - - for i in range(9600, 19600): - if port_is_using('127.0.0.1', i): - continue - rmtree(PortFinder.used_port[i], ignore_errors=True) - return i, TemporaryDirectory(dir=self.tmp_dir).name - - raise OSError('未找到可用端口。') diff --git a/DrissionPage/_configs/chromium_options.pyi b/DrissionPage/_configs/chromium_options.pyi index ce2a748..0b7db3c 100644 --- a/DrissionPage/_configs/chromium_options.pyi +++ b/DrissionPage/_configs/chromium_options.pyi @@ -6,8 +6,7 @@ @License : BSD 3-Clause. """ from pathlib import Path -from threading import Lock -from typing import Union, Tuple, Any, Literal, Optional +from typing import Union, Any, Literal, Optional, Tuple class ChromiumOptions(object): @@ -82,7 +81,7 @@ class ChromiumOptions(object): def is_existing_only(self) -> bool: ... @property - def is_auto_port(self) -> bool: ... + def is_auto_port(self) -> Union[bool, Tuple[int, int]]: ... @property def retry_times(self) -> int: ... @@ -153,21 +152,13 @@ class ChromiumOptions(object): def use_system_user_path(self, on_off: bool = True) -> ChromiumOptions: ... - def auto_port(self, on_off: bool = True, tmp_path: Union[str, Path] = None) -> ChromiumOptions: ... + def auto_port(self, + on_off: bool = True, + tmp_path: Union[str, Path] = None, + scope: Tuple[int, int] = None) -> ChromiumOptions: ... def existing_only(self, on_off: bool = True) -> ChromiumOptions: ... def save(self, path: Union[str, Path] = None) -> str: ... def save_to_default(self) -> str: ... - - -class PortFinder(object): - used_port: dict = ... - lock: Lock = ... - tmp_dir: Path = ... - - def __init__(self, path: Union[str, Path] = None): ... - - @staticmethod - def get_port() -> Tuple[int, str]: ... diff --git a/DrissionPage/_functions/browser.py b/DrissionPage/_functions/browser.py index 113a7f9..54b1b5a 100644 --- a/DrissionPage/_functions/browser.py +++ b/DrissionPage/_functions/browser.py @@ -6,10 +6,9 @@ @License : BSD 3-Clause. """ from json import load, dump, JSONDecodeError -from os import popen +from os import environ from pathlib import Path from platform import system -from re import search from subprocess import Popen, DEVNULL from tempfile import gettempdir from time import perf_counter, sleep @@ -330,23 +329,8 @@ def get_chrome_path(): pass # -----------从系统变量中获取-------------- - try: - paths = popen('set path').read().lower() - except: - return None - r = 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(): - return str(path) - - paths = paths.split(';') - - for path in paths: + for path in environ.get('PATH', '').split(';'): path = Path(path) / 'chrome.exe' - try: if path.exists(): return str(path) diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index 5f6b3bf..4ae6f5a 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -8,7 +8,9 @@ from pathlib import Path from platform import system from shutil import rmtree -from time import perf_counter, sleep +from tempfile import gettempdir, TemporaryDirectory +from threading import Lock +from time import perf_counter from psutil import process_iter, AccessDenied, NoSuchProcess, ZombieProcess @@ -17,6 +19,47 @@ from ..errors import (ContextLostError, ElementLostError, CDPError, PageDisconne AlertExistsError, WrongURLError, StorageError, CookieFormatError, JavaScriptError) +class PortFinder(object): + used_port = {} + lock = Lock() + + def __init__(self, path=None): + """ + :param path: 临时文件保存路径,为None时使用系统临时文件夹 + """ + tmp = Path(path) if path else Path(gettempdir()) / 'DrissionPage' + self.tmp_dir = tmp / 'UserTempFolder' + self.tmp_dir.mkdir(parents=True, exist_ok=True) + if not PortFinder.used_port: + clean_folder(self.tmp_dir) + + def get_port(self, scope=None): + """查找一个可用端口 + :param scope: 指定端口范围,不含最后的数字,为None则使用[9600-19600) + :return: 可以使用的端口和用户文件夹路径组成的元组 + """ + with PortFinder.lock: + if scope in (True, None): + scope = (9600, 19600) + for i in range(scope[0], scope[1]): + if i in PortFinder.used_port: + continue + elif port_is_using('127.0.0.1', i): + PortFinder.used_port[i] = None + continue + path = TemporaryDirectory(dir=self.tmp_dir).name + PortFinder.used_port[i] = path + return i, path + + for i in range(scope[0], scope[1]): + if port_is_using('127.0.0.1', i): + continue + rmtree(PortFinder.used_port[i], ignore_errors=True) + return i, TemporaryDirectory(dir=self.tmp_dir).name + + raise OSError('未找到可用端口。') + + def port_is_using(ip, port): """检查端口是否被占用 :param ip: 浏览器地址 diff --git a/DrissionPage/_functions/tools.pyi b/DrissionPage/_functions/tools.pyi index 8e0ae9b..dd9d507 100644 --- a/DrissionPage/_functions/tools.pyi +++ b/DrissionPage/_functions/tools.pyi @@ -7,12 +7,23 @@ """ from os import popen from pathlib import Path -from typing import Union -from types import FunctionType +from threading import Lock +from typing import Union, Tuple from .._pages.chromium_page import ChromiumPage +class PortFinder(object): + used_port: dict = ... + lock: Lock = ... + tmp_dir: Path = ... + + def __init__(self, path: Union[str, Path] = None): ... + + @staticmethod + def get_port(scope: Tuple[int, int] = None) -> Tuple[int, str]: ... + + def port_is_using(ip: str, port: Union[str, int]) -> bool: ... diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 436e731..705fcf3 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -651,11 +651,13 @@ class ChromiumBase(BasePage): """页面停止加载""" try: self.run_cdp('Page.stopLoading') + end_time = perf_counter() + 5 + while self._ready_state != 'complete' and perf_counter() < end_time: + sleep(.1) except (PageDisconnectedError, CDPError): pass - end_time = perf_counter() + self.timeouts.page_load - while self._ready_state != 'complete' and perf_counter() < end_time: - sleep(.1) + finally: + self._ready_state = 'complete' def remove_ele(self, loc_or_ele): """从页面上删除一个元素 diff --git a/DrissionPage/_pages/chromium_page.py b/DrissionPage/_pages/chromium_page.py index 9a01ac1..554552d 100644 --- a/DrissionPage/_pages/chromium_page.py +++ b/DrissionPage/_pages/chromium_page.py @@ -6,13 +6,15 @@ @License : BSD 3-Clause. """ from pathlib import Path +from threading import Lock from time import sleep, perf_counter from requests import get from .._base.browser import Browser +from .._configs.chromium_options import ChromiumOptions from .._functions.browser import connect_browser -from .._configs.chromium_options import ChromiumOptions, PortFinder +from .._functions.tools import PortFinder from .._pages.chromium_base import ChromiumBase, get_mhtml, get_pdf, Timeout from .._pages.chromium_tab import ChromiumTab from .._units.setter import ChromiumPageSetter @@ -34,7 +36,10 @@ class ChromiumPage(ChromiumBase): opt = handle_options(addr_or_opts) is_exist, browser_id = run_browser(opt) if browser_id in cls.PAGES: - return cls.PAGES[browser_id] + r = cls.PAGES[browser_id] + while not hasattr(r, '_frame_id'): + sleep(.1) + return r r = object.__new__(cls) r._chromium_options = opt r._is_exist = is_exist @@ -57,6 +62,7 @@ class ChromiumPage(ChromiumBase): self._run_browser() super().__init__(self.address, tab_id) self._type = 'ChromiumPage' + self._lock = Lock() self.set.timeouts(base=timeout) self._page_init() @@ -146,16 +152,17 @@ class ChromiumPage(ChromiumBase): :param id_or_num: 要获取的标签页id或序号,为None时获取当前tab,序号从1开始,可传入负数获取倒数第几个,不是视觉排列顺序,而是激活顺序 :return: 标签页对象 """ - if isinstance(id_or_num, str): - return ChromiumTab(self, id_or_num) - elif isinstance(id_or_num, int): - return ChromiumTab(self, self.tabs[id_or_num - 1 if id_or_num > 0 else id_or_num]) - elif id_or_num is None: - return ChromiumTab(self, self.tab_id) - elif isinstance(id_or_num, ChromiumTab): - return id_or_num - else: - raise TypeError(f'id_or_num需传入tab id或序号,非{id_or_num}。') + with self._lock: + if isinstance(id_or_num, str): + return ChromiumTab(self, id_or_num) + elif isinstance(id_or_num, int): + return ChromiumTab(self, self.tabs[id_or_num - 1 if id_or_num > 0 else id_or_num]) + elif id_or_num is None: + return ChromiumTab(self, self.tab_id) + elif isinstance(id_or_num, ChromiumTab): + return id_or_num + else: + raise TypeError(f'id_or_num需传入tab id或序号,非{id_or_num}。') def find_tabs(self, title=None, url=None, tab_type=None, single=True): """查找符合条件的tab,返回它们的id组成的列表 @@ -269,13 +276,18 @@ def handle_options(addr_or_opts): """ if not addr_or_opts: _chromium_options = ChromiumOptions(addr_or_opts) + if _chromium_options.is_auto_port: + port, path = PortFinder(_chromium_options.tmp_path).get_port(_chromium_options.is_auto_port) + _chromium_options.set_address(f'127.0.0.1:{port}') + _chromium_options.set_user_data_path(path) + _chromium_options.auto_port(scope=_chromium_options.is_auto_port) elif isinstance(addr_or_opts, ChromiumOptions): if addr_or_opts.is_auto_port: - port, path = PortFinder(addr_or_opts.tmp_path).get_port() + port, path = PortFinder(addr_or_opts.tmp_path).get_port(addr_or_opts.is_auto_port) addr_or_opts.set_address(f'127.0.0.1:{port}') addr_or_opts.set_user_data_path(path) - addr_or_opts.auto_port() + addr_or_opts.auto_port(scope=addr_or_opts.is_auto_port) _chromium_options = addr_or_opts elif isinstance(addr_or_opts, str): diff --git a/DrissionPage/_pages/chromium_page.pyi b/DrissionPage/_pages/chromium_page.pyi index 171f488..7e9065f 100644 --- a/DrissionPage/_pages/chromium_page.pyi +++ b/DrissionPage/_pages/chromium_page.pyi @@ -6,6 +6,7 @@ @License : BSD 3-Clause. """ from pathlib import Path +from threading import Lock from typing import Union, Tuple, List, Optional from .._base.browser import Browser @@ -34,6 +35,7 @@ class ChromiumPage(ChromiumBase): self._browser_id: str = ... self._rect: Optional[TabRect] = ... self._is_exist: bool = ... + self._lock: Lock = ... def _handle_options(self, addr_or_opts: Union[str, ChromiumOptions]) -> str: ... diff --git a/DrissionPage/_pages/chromium_tab.py b/DrissionPage/_pages/chromium_tab.py index 0b11bf0..7e52202 100644 --- a/DrissionPage/_pages/chromium_tab.py +++ b/DrissionPage/_pages/chromium_tab.py @@ -6,6 +6,7 @@ @License : BSD 3-Clause. """ from copy import copy +from time import sleep from .._base.base import BasePage from .._configs.session_options import SessionOptions @@ -27,7 +28,10 @@ class ChromiumTab(ChromiumBase): :param tab_id: 要控制的标签页id """ if Settings.singleton_tab_obj and tab_id in cls.TABS: - return cls.TABS[tab_id] + r = cls.TABS[tab_id] + while not hasattr(r, '_frame_id'): + sleep(.1) + return r r = object.__new__(cls) cls.TABS[tab_id] = r return r diff --git a/DrissionPage/_pages/chromium_tab.pyi b/DrissionPage/_pages/chromium_tab.pyi index 952867d..a837051 100644 --- a/DrissionPage/_pages/chromium_tab.pyi +++ b/DrissionPage/_pages/chromium_tab.pyi @@ -6,6 +6,7 @@ @License : BSD 3-Clause. """ from pathlib import Path +from threading import Lock from typing import Union, Tuple, Any, List, Optional from requests import Session, Response @@ -26,6 +27,7 @@ from .._units.waiter import TabWaiter class ChromiumTab(ChromiumBase): TABS: dict = ... + LOCK: Lock = ... def __new__(cls, page: ChromiumPage, tab_id: str): ... diff --git a/setup.py b/setup.py index 0317688..bef1de3 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,13 @@ # -*- coding:utf-8 -*- from setuptools import setup, find_packages +from DrissionPage import __version__ with open("README.md", "r", encoding='utf-8') as fh: long_description = fh.read() setup( name="DrissionPage", - version="4.0.3.2", + version=__version__, author="g1879", author_email="g1879@qq.com", description="Python based web automation tool. It can control the browser and send and receive data packets.", From 9e4b39be55da27364eef726ffd5d9434bba247d3 Mon Sep 17 00:00:00 2001 From: g1879 Date: Mon, 22 Jan 2024 17:13:10 +0800 Subject: [PATCH 8/9] =?UTF-8?q?4.0.3.5=E7=BB=9F=E4=B8=80=E5=90=84locator?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=90=8D=E7=A7=B0=EF=BC=9Bselect.by=5Floc()?= =?UTF-8?q?=E6=94=B9=E6=88=90by.locator()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_base/base.py | 149 +++++++------ DrissionPage/_base/base.pyi | 47 +++-- DrissionPage/_elements/chromium_element.py | 222 ++++++++++---------- DrissionPage/_elements/chromium_element.pyi | 65 +++--- DrissionPage/_elements/session_element.py | 96 ++++----- DrissionPage/_elements/session_element.pyi | 32 +-- DrissionPage/_pages/chromium_base.py | 56 ++--- DrissionPage/_pages/chromium_base.pyi | 14 +- DrissionPage/_pages/chromium_frame.py | 66 +++--- DrissionPage/_pages/chromium_frame.pyi | 20 +- DrissionPage/_pages/chromium_tab.py | 48 ++--- DrissionPage/_pages/chromium_tab.pyi | 12 +- DrissionPage/_pages/session_page.py | 37 ++-- DrissionPage/_pages/session_page.pyi | 12 +- DrissionPage/_pages/web_page.py | 48 ++--- DrissionPage/_pages/web_page.pyi | 12 +- DrissionPage/_units/selector.py | 12 +- DrissionPage/_units/selector.pyi | 4 +- DrissionPage/_units/waiter.py | 6 +- DrissionPage/_units/waiter.pyi | 2 +- 21 files changed, 483 insertions(+), 479 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index a038814..b64e503 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.3.4' +__version__ = '4.0.3.5' diff --git a/DrissionPage/_base/base.py b/DrissionPage/_base/base.py index 9ecf2b1..0156fbd 100644 --- a/DrissionPage/_base/base.py +++ b/DrissionPage/_base/base.py @@ -20,31 +20,31 @@ from ..errors import ElementNotFoundError class BaseParser(object): """所有页面、元素类的基类""" - def __call__(self, loc_or_str): - return self.ele(loc_or_str) + def __call__(self, locator): + return self.ele(locator) - def ele(self, loc_or_ele, index=1, timeout=None): - return self._ele(loc_or_ele, timeout, index=index, method='ele()') + def ele(self, locator, index=1, timeout=None): + return self._ele(locator, timeout, index=index, method='ele()') - def eles(self, loc_or_str, timeout=None): - return self._ele(loc_or_str, timeout, index=None) + def eles(self, locator, timeout=None): + return self._ele(locator, timeout, index=None) # ----------------以下属性或方法待后代实现---------------- @property def html(self): return '' - def s_ele(self, loc_or_ele): + def s_ele(self, locator): pass - def s_eles(self, loc_or_str): + def s_eles(self, locator): pass - def _ele(self, loc_or_ele, timeout=None, index=1, raise_err=None, method=None): + def _ele(self, locator, timeout=None, index=1, raise_err=None, method=None): pass @abstractmethod - def _find_elements(self, loc_or_ele, timeout=None, index=1, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, raise_err=None): pass @@ -69,9 +69,9 @@ class BaseElement(BaseParser): def nexts(self): pass - def _ele(self, loc_or_str, timeout=None, index=1, relative=False, raise_err=None, method=None): + def _ele(self, locator, timeout=None, index=1, relative=False, raise_err=None, method=None): """调用获取元素的方法 - :param loc_or_str: 定位符 + :param locator: 定位符 :param timeout: 超时时间(秒) :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param relative: 是否相对定位 @@ -79,24 +79,23 @@ class BaseElement(BaseParser): :param method: 调用的方法名 :return: 元素对象或它们组成的列表 """ - r = self._find_elements(loc_or_str, timeout=timeout, index=index, relative=relative, raise_err=raise_err) + r = self._find_elements(locator, timeout=timeout, index=index, relative=relative, raise_err=raise_err) if r or isinstance(r, list): return r if Settings.raise_when_ele_not_found or raise_err is True: - raise ElementNotFoundError(None, method, {'loc_or_str': loc_or_str, 'index': index}) + raise ElementNotFoundError(None, method, {'locator': locator, 'index': index}) r.method = method - r.args = {'loc_or_str': loc_or_str, 'index': index} + r.args = {'locator': locator, 'index': index} return r @abstractmethod - def _find_elements(self, loc_or_str, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): pass class DrissionElement(BaseElement): - """ChromiumElement 和 SessionElement的基类 - 但不是ShadowRoot的基类""" + """ChromiumElement 和 SessionElement的基类,但不是ShadowRoot的基类""" @property def link(self): @@ -152,21 +151,21 @@ class DrissionElement(BaseElement): return self._ele(loc, timeout=0, relative=True, raise_err=False, method='parent()') - def child(self, filter_loc='', index=1, timeout=None, ele_only=True): + def child(self, locator='', index=1, timeout=None, ele_only=True): """返回直接子元素元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本组成的列表 """ - if isinstance(filter_loc, int): - index = filter_loc - filter_loc = '' - if not filter_loc: + if isinstance(locator, int): + index = locator + locator = '' + if not locator: loc = '*' if ele_only else 'node()' else: - loc = get_loc(filter_loc, True) # 把定位符转换为xpath + loc = get_loc(locator, True) # 把定位符转换为xpath if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') loc = loc[1].lstrip('./') @@ -176,62 +175,62 @@ class DrissionElement(BaseElement): return node if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 'child()', {'filter_loc': filter_loc, 'index': index, + raise ElementNotFoundError(None, 'child()', {'locator': locator, 'index': index, 'ele_only': ele_only}) else: - return NoneElement(self.page, 'child()', {'filter_loc': filter_loc, 'index': index, 'ele_only': ele_only}) + return NoneElement(self.page, 'child()', {'locator': locator, 'index': index, 'ele_only': ele_only}) - def prev(self, filter_loc='', index=1, timeout=None, ele_only=True): + def prev(self, locator='', index=1, timeout=None, ele_only=True): """返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素 """ - return self._get_relative('prev()', 'preceding', True, filter_loc, index, timeout, ele_only) + return self._get_relative('prev()', 'preceding', True, locator, index, timeout, ele_only) - def next(self, filter_loc='', index=1, timeout=None, ele_only=True): + def next(self, locator='', index=1, timeout=None, ele_only=True): """返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 后面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素 """ - return self._get_relative('next()', 'following', True, filter_loc, index, timeout, ele_only) + return self._get_relative('next()', 'following', True, locator, index, timeout, ele_only) - def before(self, filter_loc='', index=1, timeout=None, ele_only=True): + def before(self, locator='', index=1, timeout=None, ele_only=True): """返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的某个元素或节点 """ - return self._get_relative('before()', 'preceding', False, filter_loc, index, timeout, ele_only) + return self._get_relative('before()', 'preceding', False, locator, index, timeout, ele_only) - def after(self, filter_loc='', index=1, timeout=None, ele_only=True): + def after(self, locator='', index=1, timeout=None, ele_only=True): """返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 后面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的某个元素或节点 """ - return self._get_relative('after()', 'following', False, filter_loc, index, timeout, ele_only) + return self._get_relative('after()', 'following', False, locator, index, timeout, ele_only) - def children(self, filter_loc='', timeout=None, ele_only=True): + def children(self, locator='', timeout=None, ele_only=True): """返回直接子元素元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本组成的列表 """ - if not filter_loc: + if not locator: loc = '*' if ele_only else 'node()' else: - loc = get_loc(filter_loc, True) # 把定位符转换为xpath + loc = get_loc(locator, True) # 把定位符转换为xpath if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') loc = loc[1].lstrip('./') @@ -240,69 +239,69 @@ class DrissionElement(BaseElement): nodes = self._ele(loc, timeout=timeout, index=None, relative=True) return [e for e in nodes if not (isinstance(e, str) and sub('[ \n\t\r]', '', e) == '')] - def prevs(self, filter_loc='', timeout=None, ele_only=True): + def prevs(self, locator='', timeout=None, ele_only=True): """返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本组成的列表 """ - return self._get_relatives(filter_loc=filter_loc, direction='preceding', timeout=timeout, ele_only=ele_only) + return self._get_relatives(locator=locator, direction='preceding', timeout=timeout, ele_only=ele_only) - def nexts(self, filter_loc='', timeout=None, ele_only=True): + def nexts(self, locator='', timeout=None, ele_only=True): """返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本组成的列表 """ - return self._get_relatives(filter_loc=filter_loc, direction='following', timeout=timeout, ele_only=ele_only) + return self._get_relatives(locator=locator, direction='following', timeout=timeout, ele_only=ele_only) - def befores(self, filter_loc='', timeout=None, ele_only=True): + def befores(self, locator='', timeout=None, ele_only=True): """返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return self._get_relatives(filter_loc=filter_loc, direction='preceding', + return self._get_relatives(locator=locator, direction='preceding', brother=False, timeout=timeout, ele_only=ele_only) - def afters(self, filter_loc='', timeout=None, ele_only=True): + def afters(self, locator='', timeout=None, ele_only=True): """返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的元素或节点组成的列表 """ - return self._get_relatives(filter_loc=filter_loc, direction='following', + return self._get_relatives(locator=locator, direction='following', brother=False, timeout=timeout, ele_only=ele_only) - def _get_relative(self, func, direction, brother, filter_loc='', index=1, timeout=None, ele_only=True): + def _get_relative(self, func, direction, brother, locator='', index=1, timeout=None, ele_only=True): """获取一个亲戚元素或节点,可用查询语法筛选,可指定返回筛选结果的第几个 :param func: 方法名称 :param direction: 方向,'following' 或 'preceding' - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的某个元素或节点 """ - if isinstance(filter_loc, int): - index = filter_loc - filter_loc = '' - node = self._get_relatives(index, filter_loc, direction, brother, timeout, ele_only) + if isinstance(locator, int): + index = locator + locator = '' + node = self._get_relatives(index, locator, direction, brother, timeout, ele_only) if node: return node if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, func, {'filter_loc': filter_loc, 'index': index, 'ele_only': ele_only}) + raise ElementNotFoundError(None, func, {'locator': locator, 'index': index, 'ele_only': ele_only}) else: - return NoneElement(self.page, func, {'filter_loc': filter_loc, 'index': index, 'ele_only': ele_only}) + return NoneElement(self.page, func, {'locator': locator, 'index': index, 'ele_only': ele_only}) - def _get_relatives(self, index=None, filter_loc='', direction='following', brother=True, timeout=.5, ele_only=True): + def _get_relatives(self, index=None, locator='', direction='following', brother=True, timeout=.5, ele_only=True): """按要求返回兄弟元素或节点组成的列表 :param index: 获取第几个,该参数不为None时只获取该编号的元素 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param direction: 'following' 或 'preceding',查找的方向 :param brother: 查找范围,在同级查找还是整个dom前后查找 :param timeout: 查找等待时间(秒) @@ -310,11 +309,11 @@ class DrissionElement(BaseElement): """ brother = '-sibling' if brother else '' - if not filter_loc: + if not locator: loc = '*' if ele_only else 'node()' else: - loc = get_loc(filter_loc, True) # 把定位符转换为xpath + loc = get_loc(locator, True) # 把定位符转换为xpath if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') loc = loc[1].lstrip('./') @@ -424,29 +423,29 @@ class BasePage(BaseParser): def get(self, url, show_errmsg=False, retry=None, interval=None): pass - def _ele(self, loc_or_ele, timeout=None, index=1, raise_err=None, method=None): + def _ele(self, locator, timeout=None, index=1, raise_err=None, method=None): """调用获取元素的方法 - :param loc_or_ele: 定位符 + :param locator: 定位符 :param timeout: 超时时间(秒) :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param raise_err: 找不到时是否抛出异常 :param method: 调用的方法名 :return: 元素对象或它们组成的列表 """ - if not loc_or_ele: - raise ElementNotFoundError(None, method, {'loc_or_str': loc_or_ele}) + if not locator: + raise ElementNotFoundError(None, method, {'locator': locator}) - r = self._find_elements(loc_or_ele, timeout=timeout, index=index, raise_err=raise_err) + r = self._find_elements(locator, timeout=timeout, index=index, raise_err=raise_err) if r or isinstance(r, list): return r if Settings.raise_when_ele_not_found or raise_err is True: - raise ElementNotFoundError(None, method, {'loc_or_str': loc_or_ele, 'index': index}) + raise ElementNotFoundError(None, method, {'locator': locator, 'index': index}) r.method = method - r.args = {'loc_or_str': loc_or_ele, 'index': index} + r.args = {'locator': locator, 'index': index} return r @abstractmethod - def _find_elements(self, loc_or_ele, timeout=None, index=1, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, raise_err=None): pass diff --git a/DrissionPage/_base/base.pyi b/DrissionPage/_base/base.pyi index 1642529..2d4148d 100644 --- a/DrissionPage/_base/base.pyi +++ b/DrissionPage/_base/base.pyi @@ -16,25 +16,25 @@ from .._elements.none_element import NoneElement class BaseParser(object): _type: str - def __call__(self, loc_or_str: Union[Tuple[str, str], str], index: int = 1): ... + def __call__(self, locator: Union[Tuple[str, str], str], index: int = 1): ... def ele(self, - loc_or_ele: Union[Tuple[str, str], str, BaseElement], + locator: Union[Tuple[str, str], str, BaseElement], index: int = 1, timeout: float = None): ... - def eles(self, loc_or_str: Union[Tuple[str, str], str], timeout=None): ... + def eles(self, locator: Union[Tuple[str, str], str], timeout=None): ... # ----------------以下属性或方法待后代实现---------------- @property def html(self) -> str: ... - def s_ele(self, loc_or_ele: Union[Tuple[str, str], str, BaseElement], index: int = 1): ... + def s_ele(self, locator: Union[Tuple[str, str], str, BaseElement], index: int = 1): ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]): ... + def s_eles(self, locator: Union[Tuple[str, str], str]): ... def _ele(self, - loc_or_ele, + locator, timeout: float = None, index: Optional[int] = 1, raise_err: bool = None, @@ -42,7 +42,7 @@ class BaseParser(object): @abstractmethod def _find_elements(self, - loc_or_ele, + locator, timeout: float = None, index: Optional[int] = 1, raise_err: bool = None): ... @@ -58,7 +58,7 @@ class BaseElement(BaseParser): def tag(self) -> str: ... def _ele(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None, index: Optional[int] = 1, relative: bool = False, @@ -66,7 +66,8 @@ class BaseElement(BaseParser): method: str = None): ... @abstractmethod - def _find_elements(self, loc_or_str, + def _find_elements(self, + locator, timeout: float = None, index: Optional[int] = 1, relative: bool = False, @@ -108,57 +109,57 @@ class DrissionElement(BaseElement): index: int = 1) -> Union[DrissionElement, None]: ... def child(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def prev(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def next(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def before(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def after(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def children(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def prevs(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def nexts(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def befores(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def afters(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... @@ -166,14 +167,14 @@ class DrissionElement(BaseElement): func: str, direction: str, brother: bool, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> DrissionElement: ... def _get_relatives(self, index: int = None, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', direction: str = 'following', brother: bool = True, timeout: float = 0.5, @@ -245,7 +246,7 @@ class BasePage(BaseParser): def get(self, url: str, show_errmsg: bool = False, retry: int = None, interval: float = None): ... def _ele(self, - loc_or_ele, + locator, timeout: float = None, index: Optional[int] = 1, raise_err: bool = None, @@ -253,7 +254,7 @@ class BasePage(BaseParser): @abstractmethod def _find_elements(self, - loc_or_ele, + locator, timeout: float = None, index: Optional[int] = 1, raise_err: bool = None): ... diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index ca373e1..2b4e678 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -82,13 +82,13 @@ class ChromiumElement(DrissionElement): attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs] return f'' - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 超时时间(秒) :return: ChromiumElement对象或属性、文本 """ - return self.ele(loc_or_str, index=index, timeout=timeout) + return self.ele(locator, index=index, timeout=timeout) def __eq__(self, other): return self._backend_id == getattr(other, '_backend_id', None) @@ -235,104 +235,104 @@ class ChromiumElement(DrissionElement): """ return super().parent(level_or_loc, index) - def child(self, filter_loc='', index=1, timeout=None, ele_only=True): + def child(self, locator='', index=1, timeout=None, ele_only=True): """返回当前元素的一个符合条件的直接子元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本 """ - return super().child(filter_loc, index, timeout, ele_only=ele_only) + return super().child(locator, index, timeout, ele_only=ele_only) - def prev(self, filter_loc='', index=1, timeout=None, ele_only=True): + def prev(self, locator='', index=1, timeout=None, ele_only=True): """返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本 """ - return super().prev(filter_loc, index, timeout, ele_only=ele_only) + return super().prev(locator, index, timeout, ele_only=ele_only) - def next(self, filter_loc='', index=1, timeout=None, ele_only=True): + def next(self, locator='', index=1, timeout=None, ele_only=True): """返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本 """ - return super().next(filter_loc, index, timeout, ele_only=ele_only) + return super().next(locator, index, timeout, ele_only=ele_only) - def before(self, filter_loc='', index=1, timeout=None, ele_only=True): + def before(self, locator='', index=1, timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的某个元素或节点 """ - return super().before(filter_loc, index, timeout, ele_only=ele_only) + return super().before(locator, index, timeout, ele_only=ele_only) - def after(self, filter_loc='', index=1, timeout=None, ele_only=True): + def after(self, locator='', index=1, timeout=None, ele_only=True): """返回文档中此当前元素后面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的某个元素或节点 """ - return super().after(filter_loc, index, timeout, ele_only=ele_only) + return super().after(locator, index, timeout, ele_only=ele_only) - def children(self, filter_loc='', timeout=None, ele_only=True): + def children(self, locator='', timeout=None, ele_only=True): """返回当前元素符合条件的直接子元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本组成的列表 """ - return super().children(filter_loc, timeout, ele_only=ele_only) + return super().children(locator, timeout, ele_only=ele_only) - def prevs(self, filter_loc='', timeout=None, ele_only=True): + def prevs(self, locator='', timeout=None, ele_only=True): """返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本组成的列表 """ - return super().prevs(filter_loc, timeout, ele_only=ele_only) + return super().prevs(locator, timeout, ele_only=ele_only) - def nexts(self, filter_loc='', timeout=None, ele_only=True): + def nexts(self, locator='', timeout=None, ele_only=True): """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本组成的列表 """ - return super().nexts(filter_loc, timeout, ele_only=ele_only) + return super().nexts(locator, timeout, ele_only=ele_only) - def befores(self, filter_loc='', timeout=None, ele_only=True): + def befores(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return super().befores(filter_loc, timeout, ele_only=ele_only) + return super().befores(locator, timeout, ele_only=ele_only) - def afters(self, filter_loc='', timeout=None, ele_only=True): + def afters(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的元素或节点组成的列表 """ - return super().afters(filter_loc, timeout, ele_only=ele_only) + return super().afters(locator, timeout, ele_only=ele_only) def attr(self, attr): """返回一个attribute属性值 @@ -402,60 +402,60 @@ class ChromiumElement(DrissionElement): """ run_js(self, script, as_expr, 0, args) - def ele(self, loc_or_str, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """返回当前元素下级符合条件的一个元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个 :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致 :return: ChromiumElement对象或属性、文本 """ - return self._ele(loc_or_str, timeout, index=index, method='ele()') + return self._ele(locator, timeout, index=index, method='ele()') - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """返回当前元素下级所有符合条件的子元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致 :return: ChromiumElement对象或属性、文本组成的列表 """ - return self._ele(loc_or_str, timeout=timeout, index=None) + return self._ele(locator, timeout=timeout, index=None) - def s_ele(self, loc_or_str=None, index=1): + def s_ele(self, locator=None, index=1): """查找一个符合条件的元素,以SessionElement形式返回 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ if self.tag in __FRAME_ELEMENT__: - r = make_session_ele(self.inner_html, loc_or_str, index=index) + r = make_session_ele(self.inner_html, locator, index=index) else: - r = make_session_ele(self, loc_or_str, index=index) + r = make_session_ele(self, locator, index=index) if isinstance(r, NoneElement): if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 's_ele()', {'loc_or_str': loc_or_str}) + raise ElementNotFoundError(None, 's_ele()', {'locator': locator}) else: r.method = 's_ele()' - r.args = {'loc_or_str': loc_or_str} + r.args = {'locator': locator} return r - def s_eles(self, loc_or_str=None): + def s_eles(self, locator=None): """查找所有符合条件的元素,以SessionElement列表形式返回 - :param loc_or_str: 定位符 + :param locator: 定位符 :return: SessionElement或属性、文本组成的列表 """ if self.tag in __FRAME_ELEMENT__: - return make_session_ele(self.inner_html, loc_or_str, index=None) - return make_session_ele(self, loc_or_str, index=None) + return make_session_ele(self.inner_html, locator, index=None) + return make_session_ele(self, locator, index=None) - def _find_elements(self, loc_or_str, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒) :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 :return: ChromiumElement对象或文本、属性或其组成的列表 """ - return find_in_chromium_ele(self, loc_or_str, index, timeout, relative=relative) + return find_in_chromium_ele(self, locator, index, timeout, relative=relative) def style(self, style, pseudo_ele=''): """返回元素样式属性值,可获取伪元素属性值 @@ -789,15 +789,15 @@ class ShadowRoot(BaseElement): def __repr__(self): return f'' - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 例:ele2 = ele1('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 超时时间(秒) :return: 元素对象或属性、文本 """ - return self.ele(loc_or_str, index=index, timeout=timeout) + return self.ele(locator, index=index, timeout=timeout) def __eq__(self, other): return self._backend_id == getattr(other, '_backend_id', None) @@ -868,16 +868,16 @@ class ShadowRoot(BaseElement): return self.parent_ele._ele(loc, timeout=0, relative=True, raise_err=False, method='parent()') - def child(self, filter_loc='', index=1): + def child(self, locator='', index=1): """返回直接子元素元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :return: 直接子元素或节点文本组成的列表 """ - if not filter_loc: + if not locator: loc = '*' else: - loc = get_loc(filter_loc, True) # 把定位符转换为xpath + loc = get_loc(locator, True) # 把定位符转换为xpath if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') loc = loc[1].lstrip('./') @@ -888,17 +888,17 @@ class ShadowRoot(BaseElement): return ele if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 'child()', {'filter_loc': filter_loc, 'index': index}) + raise ElementNotFoundError(None, 'child()', {'locator': locator, 'index': index}) else: - return NoneElement(self.page, 'child()', {'filter_loc': filter_loc, 'index': index}) + return NoneElement(self.page, 'child()', {'locator': locator, 'index': index}) - def next(self, filter_loc='', index=1): + def next(self, locator='', index=1): """返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :return: ChromiumElement对象 """ - loc = get_loc(filter_loc, True) + loc = get_loc(locator, True) if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') @@ -909,18 +909,18 @@ class ShadowRoot(BaseElement): return ele if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 'next()', {'filter_loc': filter_loc, 'index': index}) + raise ElementNotFoundError(None, 'next()', {'locator': locator, 'index': index}) else: - return NoneElement(self.page, 'next()', {'filter_loc': filter_loc, 'index': index}) + return NoneElement(self.page, 'next()', {'locator': locator, 'index': index}) - def before(self, filter_loc='', index=1): + def before(self, locator='', index=1): """返回文档中当前元素前面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :return: 本元素前面的某个元素或节点 """ - loc = get_loc(filter_loc, True) + loc = get_loc(locator, True) if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') @@ -931,34 +931,34 @@ class ShadowRoot(BaseElement): return ele if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 'before()', {'filter_loc': filter_loc, 'index': index}) + raise ElementNotFoundError(None, 'before()', {'locator': locator, 'index': index}) else: - return NoneElement(self.page, 'before()', {'filter_loc': filter_loc, 'index': index}) + return NoneElement(self.page, 'before()', {'locator': locator, 'index': index}) - def after(self, filter_loc='', index=1): + def after(self, locator='', index=1): """返回文档中此当前元素后面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 后面第几个查询结果,1开始 :return: 本元素后面的某个元素或节点 """ - nodes = self.afters(filter_loc=filter_loc) + nodes = self.afters(locator=locator) if nodes: return nodes[index - 1] if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 'after()', {'filter_loc': filter_loc, 'index': index}) + raise ElementNotFoundError(None, 'after()', {'locator': locator, 'index': index}) else: - return NoneElement(self.page, 'after()', {'filter_loc': filter_loc, 'index': index}) + return NoneElement(self.page, 'after()', {'locator': locator, 'index': index}) - def children(self, filter_loc=''): + def children(self, locator=''): """返回当前元素符合条件的直接子元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :return: 直接子元素或节点文本组成的列表 """ - if not filter_loc: + if not locator: loc = '*' else: - loc = get_loc(filter_loc, True) # 把定位符转换为xpath + loc = get_loc(locator, True) # 把定位符转换为xpath if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') loc = loc[1].lstrip('./') @@ -966,12 +966,12 @@ class ShadowRoot(BaseElement): loc = f'xpath:./{loc}' return self._ele(loc, index=None, relative=True) - def nexts(self, filter_loc=''): + def nexts(self, locator=''): """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :return: ChromiumElement对象组成的列表 """ - loc = get_loc(filter_loc, True) + loc = get_loc(locator, True) if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') @@ -979,13 +979,13 @@ class ShadowRoot(BaseElement): xpath = f'xpath:./{loc}' return self.parent_ele._ele(xpath, index=None, relative=True) - def befores(self, filter_loc=''): + def befores(self, locator=''): """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :return: 本元素前面的元素或节点组成的列表 """ - loc = get_loc(filter_loc, True) + loc = get_loc(locator, True) if loc[0] == 'css selector': raise ValueError('此css selector语法不受支持,请换成xpath。') @@ -993,63 +993,63 @@ class ShadowRoot(BaseElement): xpath = f'xpath:./preceding::{loc}' return self.parent_ele._ele(xpath, index=None, relative=True) - def afters(self, filter_loc=''): + def afters(self, locator=''): """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :return: 本元素后面的元素或节点组成的列表 """ - eles1 = self.nexts(filter_loc) - loc = get_loc(filter_loc, True)[1].lstrip('./') + eles1 = self.nexts(locator) + loc = get_loc(locator, True)[1].lstrip('./') xpath = f'xpath:./following::{loc}' return eles1 + self.parent_ele._ele(xpath, index=None, relative=True) - def ele(self, loc_or_str, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """返回当前元素下级符合条件的一个元素 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个 :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致 :return: ChromiumElement对象 """ - return self._ele(loc_or_str, timeout, index=index, method='ele()') + return self._ele(locator, timeout, index=index, method='ele()') - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """返回当前元素下级所有符合条件的子元素 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒),默认与元素所在页面等待时间一致 :return: ChromiumElement对象组成的列表 """ - return self._ele(loc_or_str, timeout=timeout, index=None) + return self._ele(locator, timeout=timeout, index=None) - def s_ele(self, loc_or_str=None, index=1): + def s_ele(self, locator=None, index=1): """查找一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ - r = make_session_ele(self, loc_or_str, index=index) + r = make_session_ele(self, locator, index=index) if isinstance(r, NoneElement): r.method = 's_ele()' - r.args = {'loc_or_str': loc_or_str} + r.args = {'locator': locator} return r - def s_eles(self, loc_or_str): + def s_eles(self, locator): """查找所有符合条件的元素以SessionElement列表形式返回,处理复杂页面时效率很高 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :return: SessionElement对象 """ - return make_session_ele(self, loc_or_str, index=None) + return make_session_ele(self, locator, index=None) - def _find_elements(self, loc_or_str, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒) :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 :return: ChromiumElement对象或其组成的列表 """ - loc = get_loc(loc_or_str, css_mode=False) + loc = get_loc(locator, css_mode=False) if loc[0] == 'css selector' and str(loc[1]).startswith(':root'): loc = loc[0], loc[1][5:] @@ -1114,20 +1114,20 @@ class ShadowRoot(BaseElement): return r['backendNodeId'] -def find_in_chromium_ele(ele, loc, index=1, timeout=None, relative=True): +def find_in_chromium_ele(ele, locator, index=1, timeout=None, relative=True): """在chromium元素中查找 :param ele: ChromiumElement对象 - :param loc: 元素定位元组 + :param locator: 元素定位元组 :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param timeout: 查找元素超时时间(秒) :param relative: WebPage用于标记是否相对定位使用 :return: 返回ChromiumElement元素或它们组成的列表 """ # ---------------处理定位符--------------- - if isinstance(loc, (str, tuple)): - loc = get_loc(loc) + if isinstance(locator, (str, tuple)): + loc = get_loc(locator) else: - raise ValueError(f"定位符必须为str或长度为2的tuple对象。现在是:{loc}") + raise ValueError(f"定位符必须为str或长度为2的tuple对象。现在是:{locator}") loc_str = loc[1] if loc[0] == 'xpath' and loc[1].lstrip().startswith('/'): diff --git a/DrissionPage/_elements/chromium_element.pyi b/DrissionPage/_elements/chromium_element.pyi index cbddbdc..1403ae1 100644 --- a/DrissionPage/_elements/chromium_element.pyi +++ b/DrissionPage/_elements/chromium_element.pyi @@ -48,7 +48,7 @@ class ChromiumElement(DrissionElement): def __repr__(self) -> str: ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], index: int = 1, timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... @@ -103,57 +103,57 @@ class ChromiumElement(DrissionElement): index: int = 1) -> Union[ChromiumElement, NoneElement]: ... def child(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... def prev(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... def next(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... def before(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... def after(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... def children(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def prevs(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def nexts(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def befores(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def afters(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... @@ -176,22 +176,22 @@ class ChromiumElement(DrissionElement): def run_async_js(self, script: str, *args, as_expr: bool = False) -> None: ... def ele(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], index: int = 1, timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[ChromiumElement]: ... def s_ele(self, - loc_or_str: Union[Tuple[str, str], str] = None, + locator: Union[Tuple[str, str], str] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str] = None) -> List[SessionElement]: ... + def s_eles(self, locator: Union[Tuple[str, str], str] = None) -> List[SessionElement]: ... def _find_elements(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None, index: Optional[int] = 1, relative: bool = False, @@ -248,7 +248,8 @@ class ShadowRoot(BaseElement): def __repr__(self) -> str: ... - def __call__(self, loc_or_str: Union[Tuple[str, str], str], + def __call__(self, + locator: Union[Tuple[str, str], str], timeout: float = None) -> ChromiumElement: ... def __eq__(self, other: ShadowRoot) -> bool: ... @@ -271,43 +272,47 @@ class ShadowRoot(BaseElement): def parent(self, level_or_loc: Union[str, int] = 1, index: int = 1) -> ChromiumElement: ... - def child(self, filter_loc: Union[tuple, str] = '', + def child(self, + locator: Union[tuple, str] = '', index: int = 1) -> Union[ChromiumElement, NoneElement]: ... - def next(self, filter_loc: Union[tuple, str] = '', + def next(self, + locator: Union[tuple, str] = '', index: int = 1) -> Union[ChromiumElement, NoneElement]: ... - def before(self, filter_loc: Union[tuple, str] = '', + def before(self, + locator: Union[tuple, str] = '', index: int = 1) -> Union[ChromiumElement, NoneElement]: ... - def after(self, filter_loc: Union[tuple, str] = '', + def after(self, + locator: Union[tuple, str] = '', index: int = 1) -> Union[ChromiumElement, NoneElement]: ... - def children(self, filter_loc: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def children(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... - def nexts(self, filter_loc: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def nexts(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... - def befores(self, filter_loc: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def befores(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... - def afters(self, filter_loc: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def afters(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... def ele(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], index: int = 1, timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[ChromiumElement]: ... def s_ele(self, - loc_or_str: Union[Tuple[str, str], str] = None, + locator: Union[Tuple[str, str], str] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... + def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def _find_elements(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None, index: Optional[int] = 1, relative: bool = False, diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index 761668c..8b6173d 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -37,14 +37,14 @@ class SessionElement(DrissionElement): attrs = [f"{attr}='{self.attrs[attr]}'" for attr in self.attrs] return f'' - def __call__(self, loc_or_str, timeout=None): + def __call__(self, locator, timeout=None): """在内部查找元素 例:ele2 = ele1('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 不起实际作用 :return: SessionElement对象或属性、文本 """ - return self.ele(loc_or_str) + return self.ele(locator) def __eq__(self, other): return self.xpath == getattr(other, 'xpath', None) @@ -89,104 +89,104 @@ class SessionElement(DrissionElement): """ return super().parent(level_or_loc, index) - def child(self, filter_loc='', index=1, timeout=None, ele_only=True): + def child(self, locator='', index=1, timeout=None, ele_only=True): """返回当前元素的一个符合条件的直接子元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本 """ - return super().child(filter_loc, index, timeout, ele_only=ele_only) + return super().child(locator, index, timeout, ele_only=ele_only) - def prev(self, filter_loc='', index=1, timeout=None, ele_only=True): + def prev(self, locator='', index=1, timeout=None, ele_only=True): """返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素 """ - return super().prev(filter_loc, index, timeout, ele_only=ele_only) + return super().prev(locator, index, timeout, ele_only=ele_only) - def next(self, filter_loc='', index=1, timeout=None, ele_only=True): + def next(self, locator='', index=1, timeout=None, ele_only=True): """返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素 """ - return super().next(filter_loc, index, timeout, ele_only=ele_only) + return super().next(locator, index, timeout, ele_only=ele_only) - def before(self, filter_loc='', index=1, timeout=None, ele_only=True): + def before(self, locator='', index=1, timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的某个元素或节点 """ - return super().before(filter_loc, index, timeout, ele_only=ele_only) + return super().before(locator, index, timeout, ele_only=ele_only) - def after(self, filter_loc='', index=1, timeout=None, ele_only=True): + def after(self, locator='', index=1, timeout=None, ele_only=True): """返回文档中此当前元素后面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 第几个查询结果,1开始 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的某个元素或节点 """ - return super().after(filter_loc, index, timeout, ele_only=ele_only) + return super().after(locator, index, timeout, ele_only=ele_only) - def children(self, filter_loc='', timeout=0, ele_only=True): + def children(self, locator='', timeout=0, ele_only=True): """返回当前元素符合条件的直接子元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本组成的列表 """ - return super().children(filter_loc, timeout, ele_only=ele_only) + return super().children(locator, timeout, ele_only=ele_only) - def prevs(self, filter_loc='', timeout=None, ele_only=True): + def prevs(self, locator='', timeout=None, ele_only=True): """返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点文本组成的列表 """ - return super().prevs(filter_loc, timeout, ele_only=ele_only) + return super().prevs(locator, timeout, ele_only=ele_only) - def nexts(self, filter_loc='', timeout=None, ele_only=True): + def nexts(self, locator='', timeout=None, ele_only=True): """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点文本组成的列表 """ - return super().nexts(filter_loc, timeout, ele_only=ele_only) + return super().nexts(locator, timeout, ele_only=ele_only) - def befores(self, filter_loc='', timeout=None, ele_only=True): + def befores(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return super().befores(filter_loc, timeout, ele_only=ele_only) + return super().befores(locator, timeout, ele_only=ele_only) - def afters(self, filter_loc='', timeout=None, ele_only=True): + def afters(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 此参数不起实际作用 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的元素或节点组成的列表 """ - return super().afters(filter_loc, timeout, ele_only=ele_only) + return super().afters(locator, timeout, ele_only=ele_only) def attr(self, attr): """返回attribute属性值 @@ -221,48 +221,48 @@ class SessionElement(DrissionElement): else: return self.inner_ele.get(attr) - def ele(self, loc_or_str, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """返回当前元素下级符合条件的一个元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 第几个元素,从1开始,可传入负数获取倒数第几个 :param timeout: 不起实际作用 :return: SessionElement对象或属性、文本 """ - return self._ele(loc_or_str, index=index, method='ele()') + return self._ele(locator, index=index, method='ele()') - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """返回当前元素下级所有符合条件的子元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 不起实际作用 :return: SessionElement对象或属性、文本组成的列表 """ - return self._ele(loc_or_str, index=None) + return self._ele(locator, index=None) - def s_ele(self, loc_or_str=None, index=1): + def s_ele(self, locator=None, index=1): """返回当前元素下级符合条件的一个元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ - return self._ele(loc_or_str, index=index, method='s_ele()') + return self._ele(locator, index=index, method='s_ele()') - def s_eles(self, loc_or_str): + def s_eles(self, locator): """返回当前元素下级所有符合条件的子元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :return: SessionElement对象或属性、文本组成的列表 """ - return self._ele(loc_or_str, index=None) + return self._ele(locator, index=None) - def _find_elements(self, loc_or_str, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """返回当前元素下级符合条件的子元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 不起实际作用,用于和父类对应 :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 :return: SessionElement对象 """ - return make_session_ele(self, loc_or_str, index=index) + return make_session_ele(self, locator, index=index) def _get_ele_path(self, mode): """获取css路径或xpath路径 diff --git a/DrissionPage/_elements/session_element.pyi b/DrissionPage/_elements/session_element.pyi index 4e6fb8f..66d6156 100644 --- a/DrissionPage/_elements/session_element.pyi +++ b/DrissionPage/_elements/session_element.pyi @@ -29,7 +29,7 @@ class SessionElement(DrissionElement): def __repr__(self) -> str: ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], index: int = 1, timeout: float = None) -> Union[SessionElement, NoneElement]: ... @@ -58,79 +58,79 @@ class SessionElement(DrissionElement): index: int = 1) -> Union[SessionElement, NoneElement]: ... def child(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... def prev(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... def next(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... def before(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... def after(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... def children(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def prevs(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def nexts(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def befores(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def afters(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def attr(self, attr: str) -> Optional[str]: ... def ele(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], index: int = 1, timeout: float = None) -> Union[SessionElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[SessionElement]: ... def s_ele(self, - loc_or_str: Union[Tuple[str, str], str] = None, + locator: Union[Tuple[str, str], str] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... + def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def _find_elements(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None, index: Optional[int] = 1, relative: bool = False, diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 705fcf3..489c19d 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -245,15 +245,15 @@ class ChromiumBase(BasePage): self.run_cdp('Page.setInterceptFileChooserDialog', enabled=False) self._upload_list = None - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 例:ele = page('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个 :param timeout: 超时时间(秒) :return: ChromiumElement对象 """ - return self.ele(loc_or_str, index, timeout) + return self.ele(locator, index, timeout) def _wait_to_stop(self): """eager策略超时时使页面停止加载""" @@ -492,60 +492,60 @@ class ChromiumBase(BasePage): return [{'name': cookie['name'], 'value': cookie['value'], 'domain': cookie['domain']} for cookie in cookies] - def ele(self, loc_or_ele, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """获取一个符合条件的元素对象 - :param loc_or_ele: 定位符或元素对象 + :param locator: 定位符或元素对象 :param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个 :param timeout: 查找超时时间(秒) :return: ChromiumElement对象 """ - return self._ele(loc_or_ele, timeout=timeout, index=index, method='ele()') + return self._ele(locator, timeout=timeout, index=index, method='ele()') - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """获取所有符合条件的元素对象 - :param loc_or_str: 定位符或元素对象 + :param locator: 定位符或元素对象 :param timeout: 查找超时时间(秒) :return: ChromiumElement对象组成的列表 """ - return self._ele(loc_or_str, timeout=timeout, index=None) + return self._ele(locator, timeout=timeout, index=None) - def s_ele(self, loc_or_ele=None, index=1): + def s_ele(self, locator=None, index=1): """查找一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ - r = make_session_ele(self, loc_or_ele, index=index) + r = make_session_ele(self, locator, index=index) if isinstance(r, NoneElement): if Settings.raise_when_ele_not_found: - raise ElementNotFoundError(None, 's_ele()', {'loc_or_ele': loc_or_ele}) + raise ElementNotFoundError(None, 's_ele()', {'locator': locator}) else: r.method = 's_ele()' - r.args = {'loc_or_ele': loc_or_ele} + r.args = {'locator': locator} return r - def s_eles(self, loc_or_str): + def s_eles(self, locator): """查找所有符合条件的元素以SessionElement列表形式返回 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :return: SessionElement对象组成的列表 """ - return make_session_ele(self, loc_or_str, index=None) + return make_session_ele(self, locator, index=None) - def _find_elements(self, loc_or_ele, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """执行元素查找 - :param loc_or_ele: 定位符或元素对象 + :param locator: 定位符或元素对象 :param timeout: 查找超时时间(秒) :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 :return: ChromiumElement对象或元素对象组成的列表 """ - if isinstance(loc_or_ele, (str, tuple)): - loc = get_loc(loc_or_ele)[1] - elif loc_or_ele._type in ('ChromiumElement', 'ChromiumFrame'): - return loc_or_ele + if isinstance(locator, (str, tuple)): + loc = get_loc(locator)[1] + elif locator._type in ('ChromiumElement', 'ChromiumFrame'): + return locator else: - raise ValueError('loc_or_str参数只能是tuple、str、ChromiumElement类型。') + raise ValueError('locator参数只能是tuple、str、ChromiumElement类型。') self.wait.doc_loaded() timeout = timeout if timeout is not None else self.timeout @@ -712,14 +712,14 @@ class ChromiumBase(BasePage): r.args = {'loc_ind_ele': loc_ind_ele} return r - def get_frames(self, loc=None, timeout=None): + def get_frames(self, locator=None, timeout=None): """获取所有符合条件的frame对象 - :param loc: 定位符,为None时返回所有 + :param locator: 定位符,为None时返回所有 :param timeout: 查找超时时间(秒) :return: ChromiumFrame对象组成的列表 """ - loc = loc or 'xpath://*[name()="iframe" or name()="frame"]' - frames = self._ele(loc, timeout=timeout, index=None, raise_err=False) + locator = locator or 'xpath://*[name()="iframe" or name()="frame"]' + frames = self._ele(locator, timeout=timeout, index=None, raise_err=False) return [i for i in frames if i._type == 'ChromiumFrame'] def get_session_storage(self, item=None): diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index 8e9223f..dca5bc0 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -95,7 +95,7 @@ class ChromiumBase(BasePage): def _d_set_runtime_settings(self) -> None: ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str, ChromiumElement], + locator: Union[Tuple[str, str], str, ChromiumElement], index: int = 1, timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... @@ -181,22 +181,22 @@ class ChromiumBase(BasePage): all_info: bool = False) -> Union[list, dict]: ... def ele(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], + locator: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], index: int = 1, timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[ChromiumElement]: ... def s_ele(self, - loc_or_ele: Union[Tuple[str, str], str] = None, + locator: Union[Tuple[str, str], str] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... + def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def _find_elements(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], + locator: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], timeout: float = None, index: Optional[int] = 1, relative: bool = False, @@ -217,7 +217,7 @@ class ChromiumBase(BasePage): def get_frame(self, loc_ind_ele: Union[str, int, tuple, ChromiumFrame], timeout: float = None) -> ChromiumFrame: ... - def get_frames(self, loc: Union[str, tuple] = None, timeout: float = None) -> List[ChromiumFrame]: ... + def get_frames(self, locator: Union[str, tuple] = None, timeout: float = None) -> List[ChromiumFrame]: ... def run_cdp(self, cmd: str, **cmd_args) -> dict: ... diff --git a/DrissionPage/_pages/chromium_frame.py b/DrissionPage/_pages/chromium_frame.py index f947823..dd8946d 100644 --- a/DrissionPage/_pages/chromium_frame.py +++ b/DrissionPage/_pages/chromium_frame.py @@ -64,15 +64,15 @@ class ChromiumFrame(ChromiumBase): break sleep(.1) - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 例:ele2 = ele1('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 超时时间(秒) :return: ChromiumElement对象或属性、文本 """ - return self.ele(loc_or_str, index=index, timeout=timeout) + return self.ele(locator, index=index, timeout=timeout) def __eq__(self, other): return self._frame_id == getattr(other, '_frame_id', None) @@ -395,85 +395,85 @@ class ChromiumFrame(ChromiumBase): """ return self.frame_ele.parent(level_or_loc, index) - def prev(self, filter_loc='', index=1, timeout=0, ele_only=True): + def prev(self, locator='', index=1, timeout=0, ele_only=True): """返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点 """ - return self.frame_ele.prev(filter_loc, index, timeout, ele_only=ele_only) + return self.frame_ele.prev(locator, index, timeout, ele_only=ele_only) - def next(self, filter_loc='', index=1, timeout=0, ele_only=True): + def next(self, locator='', index=1, timeout=0, ele_only=True): """返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 后面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点 """ - return self.frame_ele.next(filter_loc, index, timeout, ele_only=ele_only) + return self.frame_ele.next(locator, index, timeout, ele_only=ele_only) - def before(self, filter_loc='', index=1, timeout=None, ele_only=True): + def before(self, locator='', index=1, timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 前面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的某个元素或节点 """ - return self.frame_ele.before(filter_loc, index, timeout, ele_only=ele_only) + return self.frame_ele.before(locator, index, timeout, ele_only=ele_only) - def after(self, filter_loc='', index=1, timeout=None, ele_only=True): + def after(self, locator='', index=1, timeout=None, ele_only=True): """返回文档中此当前元素后面符合条件的一个元素,可用查询语法筛选,可指定返回筛选结果的第几个 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param index: 后面第几个查询结果,1开始 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的某个元素或节点 """ - return self.frame_ele.after(filter_loc, index, timeout, ele_only=ele_only) + return self.frame_ele.after(locator, index, timeout, ele_only=ele_only) - def prevs(self, filter_loc='', timeout=0, ele_only=True): + def prevs(self, locator='', timeout=0, ele_only=True): """返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点文本组成的列表 """ - return self.frame_ele.prevs(filter_loc, timeout, ele_only=ele_only) + return self.frame_ele.prevs(locator, timeout, ele_only=ele_only) - def nexts(self, filter_loc='', timeout=0, ele_only=True): + def nexts(self, locator='', timeout=0, ele_only=True): """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间(秒) :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点文本组成的列表 """ - return self.frame_ele.nexts(filter_loc, timeout, ele_only=ele_only) + return self.frame_ele.nexts(locator, timeout, ele_only=ele_only) - def befores(self, filter_loc='', timeout=None, ele_only=True): + def befores(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return self.frame_ele.befores(filter_loc, timeout, ele_only=ele_only) + return self.frame_ele.befores(locator, timeout, ele_only=ele_only) - def afters(self, filter_loc='', timeout=None, ele_only=True): + def afters(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选 查找范围不限同级元素,而是整个DOM文档 - :param filter_loc: 用于筛选的查询语法 + :param locator: 用于筛选的查询语法 :param timeout: 查找节点的超时时间 :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return self.frame_ele.afters(filter_loc, timeout, ele_only=ele_only) + return self.frame_ele.afters(locator, timeout, ele_only=ele_only) def get_screenshot(self, path=None, name=None, as_bytes=None, as_base64=None): """对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持 @@ -562,20 +562,20 @@ class ChromiumFrame(ChromiumBase): self.tab.remove_ele(new_ele) return r - def _find_elements(self, loc_or_ele, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """在frame内查找单个元素 - :param loc_or_ele: 定位符或元素对象 + :param locator: 定位符或元素对象 :param timeout: 查找超时时间 :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 :return: ChromiumElement对象 """ - if isinstance(loc_or_ele, ChromiumElement): - return loc_or_ele + if isinstance(locator, ChromiumElement): + return locator self.wait.doc_loaded() - return self.doc_ele._ele(loc_or_ele, index=index, timeout=timeout, - raise_err=raise_err) if index is not None else self.doc_ele.eles(loc_or_ele, timeout) + return self.doc_ele._ele(locator, index=index, timeout=timeout, + raise_err=raise_err) if index is not None else self.doc_ele.eles(locator, timeout) def _is_inner_frame(self): """返回当前frame是否同域""" diff --git a/DrissionPage/_pages/chromium_frame.pyi b/DrissionPage/_pages/chromium_frame.pyi index f18f4ac..15eaa6c 100644 --- a/DrissionPage/_pages/chromium_frame.pyi +++ b/DrissionPage/_pages/chromium_frame.pyi @@ -43,7 +43,7 @@ class ChromiumFrame(ChromiumBase): self._listener: FrameListener = ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], index: int = 1, timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... @@ -148,46 +148,46 @@ class ChromiumFrame(ChromiumBase): index: int = 1) -> Union[ChromiumElement, NoneElement]: ... def prev(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = 0, ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... def next(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = 0, ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... def before(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... def after(self, - filter_loc: Union[tuple, str, int] = '', + locator: Union[tuple, str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... def prevs(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = 0, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def nexts(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = 0, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def befores(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def afters(self, - filter_loc: Union[tuple, str] = '', + locator: Union[tuple, str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... @@ -208,7 +208,7 @@ class ChromiumFrame(ChromiumBase): ele: ChromiumElement = None) -> Union[str, bytes]: ... def _find_elements(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], + locator: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], timeout: float = None, index: Optional[int] = 1, relative: bool = False, diff --git a/DrissionPage/_pages/chromium_tab.py b/DrissionPage/_pages/chromium_tab.py index 7e52202..25d0ec1 100644 --- a/DrissionPage/_pages/chromium_tab.py +++ b/DrissionPage/_pages/chromium_tab.py @@ -113,18 +113,18 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): super(SessionPage, self).__init__(page=page, tab_id=tab_id) self._type = 'WebPageTab' - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 例:ele = page('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 超时时间(秒) :return: 子元素对象 """ if self._mode == 'd': - return super(SessionPage, self).__call__(loc_or_str, index=index, timeout=timeout) + return super(SessionPage, self).__call__(locator, index=index, timeout=timeout) elif self._mode == 's': - return super().__call__(loc_or_str, index=index) + return super().__call__(locator, index=index) @property def set(self): @@ -258,49 +258,49 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): return self.response return super().post(url, show_errmsg, retry, interval, **kwargs) - def ele(self, loc_or_ele, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """返回第一个符合条件的元素、属性或节点文本 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: 元素对象或属性、文本节点文本 """ if self._mode == 's': - return super().ele(loc_or_ele, index=index) + return super().ele(locator, index=index) elif self._mode == 'd': - return super(SessionPage, self).ele(loc_or_ele, index=index, timeout=timeout) + return super(SessionPage, self).ele(locator, index=index, timeout=timeout) - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """返回页面中所有符合条件的元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: 元素对象或属性、文本组成的列表 """ if self._mode == 's': - return super().eles(loc_or_str) + return super().eles(locator) elif self._mode == 'd': - return super(SessionPage, self).eles(loc_or_str, timeout=timeout) + return super(SessionPage, self).eles(locator, timeout=timeout) - def s_ele(self, loc_or_ele=None, index=1): + def s_ele(self, locator=None, index=1): """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ if self._mode == 's': - return super().s_ele(loc_or_ele, index=index) + return super().s_ele(locator, index=index) elif self._mode == 'd': - return super(SessionPage, self).s_ele(loc_or_ele, index=index) + return super(SessionPage, self).s_ele(locator, index=index) - def s_eles(self, loc_or_str): + def s_eles(self, locator): """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :return: SessionElement对象或属性、文本组成的列表 """ if self._mode == 's': - return super().s_eles(loc_or_str) + return super().s_eles(locator) elif self._mode == 'd': - return super(SessionPage, self).s_eles(loc_or_str) + return super(SessionPage, self).s_eles(locator) def change_mode(self, mode=None, go=True, copy_cookies=True): """切换模式,接收's'或'd',除此以外的字符串会切换为 d 模式 @@ -384,9 +384,9 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): if self._response is not None: self._response.close() - def _find_elements(self, loc_or_ele, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒),d模式专用 :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 @@ -394,9 +394,9 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): :return: 元素对象或属性、文本节点文本 """ if self._mode == 's': - return super()._find_elements(loc_or_ele, index=index) + return super()._find_elements(locator, index=index) elif self._mode == 'd': - return super(SessionPage, self)._find_elements(loc_or_ele, timeout=timeout, index=index, relative=relative) + return super(SessionPage, self)._find_elements(locator, timeout=timeout, index=index, relative=relative) def __repr__(self): return f'' diff --git a/DrissionPage/_pages/chromium_tab.pyi b/DrissionPage/_pages/chromium_tab.pyi index a837051..e4b55b8 100644 --- a/DrissionPage/_pages/chromium_tab.pyi +++ b/DrissionPage/_pages/chromium_tab.pyi @@ -80,7 +80,7 @@ class WebPageTab(SessionPage, ChromiumTab): self._has_session = ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... @@ -150,19 +150,19 @@ class WebPageTab(SessionPage, ChromiumTab): cert: Any | None = ...) -> Union[bool, None]: ... def ele(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[Union[ChromiumElement, SessionElement]]: ... def s_ele(self, - loc_or_ele: Union[Tuple[str, str], str] = None, + locator: Union[Tuple[str, str], str] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... + def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def change_mode(self, mode: str = None, go: bool = True, copy_cookies: bool = True) -> None: ... @@ -200,7 +200,7 @@ class WebPageTab(SessionPage, ChromiumTab): def set(self) -> WebPageTabSetter: ... def _find_elements(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], timeout: float = None, index: Optional[int] = 1, relative: bool = False, diff --git a/DrissionPage/_pages/session_page.py b/DrissionPage/_pages/session_page.py index 2065f96..38177b4 100644 --- a/DrissionPage/_pages/session_page.py +++ b/DrissionPage/_pages/session_page.py @@ -69,15 +69,15 @@ class SessionPage(BasePage): if not self._session: self._session, self._headers = self._session_options.make_session() - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 例:ele2 = ele1('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 :return: SessionElement对象或属性文本 """ - return self.ele(loc_or_str, index=index) + return self.ele(locator, index=index) # -----------------共有属性和方法------------------- @property @@ -176,48 +176,47 @@ class SessionPage(BasePage): """ return self._s_connect(url, 'post', show_errmsg, retry, interval, **kwargs) - def ele(self, loc_or_ele, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """返回页面中符合条件的一个元素、属性或节点文本 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 :return: SessionElement对象或属性、文本 """ - return self._ele(loc_or_ele, index=index, method='ele()') + return self._ele(locator, index=index, method='ele()') - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """返回页面中所有符合条件的元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 :return: SessionElement对象或属性、文本组成的列表 """ - return self._ele(loc_or_str, index=None) + return self._ele(locator, index=None) - def s_ele(self, loc_or_ele=None, index=1): + def s_ele(self, locator=None, index=1): """返回页面中符合条件的一个元素、属性或节点文本 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ - return make_session_ele(self.html) if loc_or_ele is None else self._ele(loc_or_ele, - index=index, method='s_ele()') + return make_session_ele(self.html) if locator is None else self._ele(locator, index=index, method='s_ele()') - def s_eles(self, loc_or_str): + def s_eles(self, locator): """返回页面中符合条件的所有元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :return: SessionElement对象或属性、文本 """ - return self._ele(loc_or_str, index=None) + return self._ele(locator, index=None) - def _find_elements(self, loc_or_ele, timeout=None, index=1, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, raise_err=None): """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param timeout: 不起实际作用,用于和父类对应 :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 :return: SessionElement对象 """ - return loc_or_ele if isinstance(loc_or_ele, SessionElement) else make_session_ele(self, loc_or_ele, index=index) + return locator if isinstance(locator, SessionElement) else make_session_ele(self, locator, index=index) def get_cookies(self, as_dict=False, all_domains=False, all_info=False): """返回cookies diff --git a/DrissionPage/_pages/session_page.pyi b/DrissionPage/_pages/session_page.pyi index c134a85..15f9b24 100644 --- a/DrissionPage/_pages/session_page.pyi +++ b/DrissionPage/_pages/session_page.pyi @@ -41,7 +41,7 @@ class SessionPage(BasePage): def _create_session(self) -> None: ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str, SessionElement], + locator: Union[Tuple[str, str], str, SessionElement], index: int = 1, timeout: float = None) -> Union[SessionElement, NoneElement]: ... @@ -91,22 +91,22 @@ class SessionPage(BasePage): cert: Any | None = ...) -> bool: ... def ele(self, - loc_or_ele: Union[Tuple[str, str], str, SessionElement], + locator: Union[Tuple[str, str], str, SessionElement], index: int = 1, timeout: float = None) -> Union[SessionElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[SessionElement]: ... def s_ele(self, - loc_or_ele: Union[Tuple[str, str], str, SessionElement] = None, + locator: Union[Tuple[str, str], str, SessionElement] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... + def s_eles(self, loc: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def _find_elements(self, - loc_or_ele: Union[Tuple[str, str], str, SessionElement], + locator: Union[Tuple[str, str], str, SessionElement], timeout: float = None, index: Optional[int] = 1, raise_err: bool = None) \ diff --git a/DrissionPage/_pages/web_page.py b/DrissionPage/_pages/web_page.py index 95f2154..8fa0b15 100644 --- a/DrissionPage/_pages/web_page.py +++ b/DrissionPage/_pages/web_page.py @@ -51,18 +51,18 @@ class WebPage(SessionPage, ChromiumPage, BasePage): self._type = 'WebPage' self.change_mode(self._mode, go=False, copy_cookies=False) - def __call__(self, loc_or_str, index=1, timeout=None): + def __call__(self, locator, index=1, timeout=None): """在内部查找元素 例:ele = page('@id=ele_id') - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 超时时间(秒) :return: 子元素对象 """ if self._mode == 'd': - return super(SessionPage, self).__call__(loc_or_str, index=index, timeout=timeout) + return super(SessionPage, self).__call__(locator, index=index, timeout=timeout) elif self._mode == 's': - return super().__call__(loc_or_str, index=index) + return super().__call__(locator, index=index) @property def set(self): @@ -196,49 +196,49 @@ class WebPage(SessionPage, ChromiumPage, BasePage): return self.response return super().post(url, show_errmsg, retry, interval, **kwargs) - def ele(self, loc_or_ele, index=1, timeout=None): + def ele(self, locator, index=1, timeout=None): """返回第一个符合条件的元素、属性或节点文本 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: 元素对象或属性、文本节点文本 """ if self._mode == 's': - return super().ele(loc_or_ele, index=index) + return super().ele(locator, index=index) elif self._mode == 'd': - return super(SessionPage, self).ele(loc_or_ele, index=index, timeout=timeout) + return super(SessionPage, self).ele(locator, index=index, timeout=timeout) - def eles(self, loc_or_str, timeout=None): + def eles(self, locator, timeout=None): """返回页面中所有符合条件的元素、属性或节点文本 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: 元素对象或属性、文本组成的列表 """ if self._mode == 's': - return super().eles(loc_or_str) + return super().eles(locator) elif self._mode == 'd': - return super(SessionPage, self).eles(loc_or_str, timeout=timeout) + return super(SessionPage, self).eles(locator, timeout=timeout) - def s_ele(self, loc_or_ele=None, index=1): + def s_ele(self, locator=None, index=1): """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 :return: SessionElement对象或属性、文本 """ if self._mode == 's': - return super().s_ele(loc_or_ele, index=index) + return super().s_ele(locator, index=index) elif self._mode == 'd': - return super(SessionPage, self).s_ele(loc_or_ele, index=index) + return super(SessionPage, self).s_ele(locator, index=index) - def s_eles(self, loc_or_str): + def s_eles(self, locator): """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :return: SessionElement对象或属性、文本组成的列表 """ if self._mode == 's': - return super().s_eles(loc_or_str) + return super().s_eles(locator) elif self._mode == 'd': - return super(SessionPage, self).s_eles(loc_or_str) + return super(SessionPage, self).s_eles(locator) def change_mode(self, mode=None, go=True, copy_cookies=True): """切换模式,接收's'或'd',除此以外的字符串会切换为 d 模式 @@ -376,9 +376,9 @@ class WebPage(SessionPage, ChromiumPage, BasePage): if self._response is not None: self._response.close() - def _find_elements(self, loc_or_ele, timeout=None, index=1, relative=False, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 - :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param timeout: 查找元素超时时间,d模式专用 :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 :param relative: WebPage用的表示是否相对定位的参数 @@ -386,9 +386,9 @@ class WebPage(SessionPage, ChromiumPage, BasePage): :return: 元素对象或属性、文本节点文本 """ if self._mode == 's': - return super()._find_elements(loc_or_ele, index=index) + return super()._find_elements(locator, index=index) elif self._mode == 'd': - return super(SessionPage, self)._find_elements(loc_or_ele, timeout=timeout, index=index, relative=relative) + return super(SessionPage, self)._find_elements(locator, timeout=timeout, index=index, relative=relative) def quit(self, timeout=5, force=True): """关闭浏览器和Session diff --git a/DrissionPage/_pages/web_page.pyi b/DrissionPage/_pages/web_page.pyi index 607d130..517dfd3 100644 --- a/DrissionPage/_pages/web_page.pyi +++ b/DrissionPage/_pages/web_page.pyi @@ -37,7 +37,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): self._chromium_options: Union[ChromiumOptions, None] = ... def __call__(self, - loc_or_str: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... @@ -105,19 +105,19 @@ class WebPage(SessionPage, ChromiumPage, BasePage): cert: Any | None = ...) -> Union[bool, None]: ... def ele(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... def eles(self, - loc_or_str: Union[Tuple[str, str], str], + locator: Union[Tuple[str, str], str], timeout: float = None) -> List[Union[ChromiumElement, SessionElement]]: ... def s_ele(self, - loc_or_ele: Union[Tuple[str, str], str] = None, + locator: Union[Tuple[str, str], str] = None, index: int = 1) -> Union[SessionElement, NoneElement]: ... - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: ... + def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... def change_mode(self, mode: str = None, go: bool = True, copy_cookies: bool = True) -> None: ... @@ -169,7 +169,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def set(self) -> WebPageSetter: ... def _find_elements(self, - loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], timeout: float = None, index: Optional[int] = 1, relative: bool = False, diff --git a/DrissionPage/_units/selector.py b/DrissionPage/_units/selector.py index 9e7f721..3f9b08e 100644 --- a/DrissionPage/_units/selector.py +++ b/DrissionPage/_units/selector.py @@ -103,13 +103,13 @@ class SelectElement(object): """ return self._select(index, 'index', False, timeout) - def by_loc(self, loc, timeout=None): + def by_locator(self, locator, timeout=None): """用定位符选择指定的项 - :param loc: 定位符 + :param locator: 定位符 :param timeout: 超时时间 :return: 是否选择成功 """ - return self._by_loc(loc, timeout) + return self._by_loc(locator, timeout) def by_option(self, option): """选中单个或多个option元素 @@ -142,13 +142,13 @@ class SelectElement(object): """ return self._select(index, 'index', True, timeout) - def cancel_by_loc(self, loc, timeout=None): + def cancel_by_locator(self, locator, timeout=None): """用定位符取消选择指定的项 - :param loc: 定位符 + :param locator: 定位符 :param timeout: 超时时间 :return: 是否选择成功 """ - return self._by_loc(loc, timeout, True) + return self._by_loc(locator, timeout, True) def cancel_by_option(self, option): """取消选中单个或多个option元素 diff --git a/DrissionPage/_units/selector.pyi b/DrissionPage/_units/selector.pyi index 8e74554..06f0553 100644 --- a/DrissionPage/_units/selector.pyi +++ b/DrissionPage/_units/selector.pyi @@ -38,7 +38,7 @@ class SelectElement(object): def by_index(self, index: Union[int, list, tuple], timeout: float = None) -> bool: ... - def by_loc(self, loc: Union[str, Tuple[str, str]], timeout: float = None) -> bool: ... + def by_locator(self, locator: Union[str, Tuple[str, str]], timeout: float = None) -> bool: ... def by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None: ... @@ -48,7 +48,7 @@ class SelectElement(object): def cancel_by_index(self, index: Union[int, list, tuple], timeout: float = None) -> bool: ... - def cancel_by_loc(self, loc: Union[str, Tuple[str, str]], timeout: float = None) -> bool: ... + def cancel_by_locator(self, locator: Union[str, Tuple[str, str]], timeout: float = None) -> bool: ... def cancel_by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None: ... diff --git a/DrissionPage/_units/waiter.py b/DrissionPage/_units/waiter.py index 52ff58c..09867c9 100644 --- a/DrissionPage/_units/waiter.py +++ b/DrissionPage/_units/waiter.py @@ -73,14 +73,14 @@ class BaseWaiter(object): return False return ele.wait.hidden(timeout, raise_err=raise_err) - def ele_loaded(self, loc, timeout=None, raise_err=None): + def ele_loaded(self, locator, timeout=None, raise_err=None): """等待元素加载到DOM - :param loc: 要等待的元素,输入定位符 + :param locator: 要等待的元素,输入定位符 :param timeout: 超时时间,默认读取页面超时时间 :param raise_err: 等待失败时是否报错,为None时根据Settings设置 :return: 成功返回元素对象,失败返回False """ - ele = self._driver._ele(loc, raise_err=False, timeout=timeout) + ele = self._driver._ele(locator, raise_err=False, timeout=timeout) if ele: return ele if raise_err is True or Settings.raise_when_wait_failed is True: diff --git a/DrissionPage/_units/waiter.pyi b/DrissionPage/_units/waiter.pyi index a04dd9a..c5eb2a9 100644 --- a/DrissionPage/_units/waiter.pyi +++ b/DrissionPage/_units/waiter.pyi @@ -34,7 +34,7 @@ class BaseWaiter(object): raise_err: bool = None) -> bool: ... def ele_loaded(self, - loc: Union[str, tuple], + locator: Union[str, tuple], timeout: float = None, raise_err: bool = None) -> Union[bool, ChromiumElement]: ... From c07d90195d6a4930752adab8885b7909d525f66b Mon Sep 17 00:00:00 2001 From: g1879 Date: Sat, 27 Jan 2024 14:40:11 +0800 Subject: [PATCH 9/9] =?UTF-8?q?4.0.4(+)=20prop()=E6=94=B9=E6=88=90property?= =?UTF-8?q?()=EF=BC=8C=E5=8F=82=E6=95=B0=E6=94=B9=E4=B8=BAname=EF=BC=9B=20?= =?UTF-8?q?get=5Fsrc()=E6=94=B9=E4=B8=BAsrc()=EF=BC=9B=20get=5Fcookies()?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E6=94=B9=E6=88=90cookies()=EF=BC=9B=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4cookies=E5=B1=9E=E6=80=A7=EF=BC=9B=20get=5Fse?= =?UTF-8?q?ssion=5Fstorage()=E3=80=81get=5Flocal=5Fstorage()=E6=94=B9?= =?UTF-8?q?=E6=88=90session=5Fstorage()=E3=80=81local=5Fstorage()=EF=BC=9B?= =?UTF-8?q?=20pageLoad=E6=94=B9=E6=88=90page=5Fload=EF=BC=9B=20set=5Fa=5Fh?= =?UTF-8?q?eader()=E3=80=81remove=5Fa=5Fheader()=E3=80=81set.header()?= =?UTF-8?q?=E3=80=81set.attr()=E7=9A=84=E5=8F=82=E6=95=B0=E6=94=B9?= =?UTF-8?q?=E4=B8=BAname=EF=BC=9B=20=E5=85=83=E7=B4=A0=E5=A2=9E=E5=8A=A0va?= =?UTF-8?q?lue=E5=B1=9E=E6=80=A7=E5=92=8Cset.value()=E6=96=B9=E6=B3=95?= =?UTF-8?q?=EF=BC=9B=20loc=5For=5Fele=E3=80=81loc=5For=5Fstr=E7=AD=89?= =?UTF-8?q?=E6=94=B9=E4=B8=BAlocator=EF=BC=9B=20=E6=8F=90=E9=AB=98?= =?UTF-8?q?=E6=88=AA=E5=9B=BEjpg=E6=A0=BC=E5=BC=8F=E7=94=BB=E8=B4=A8?= =?UTF-8?q?=EF=BC=9B=20=E4=BF=AE=E5=A4=8Ds=E6=A8=A1=E5=BC=8Ftimeout?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98=EF=BC=9B?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8Dwait.has=5Frect()=E7=AD=89=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=89=BE=E4=B8=8D=E5=88=B0=E6=B5=8F=E8=A7=88=E5=99=A8?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E6=97=B6=E6=8A=A5ini=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_base/base.py | 23 ++--- DrissionPage/_base/base.pyi | 52 ++++------- DrissionPage/_base/driver.py | 3 +- DrissionPage/_configs/chromium_options.py | 16 ++-- DrissionPage/_configs/chromium_options.pyi | 4 +- DrissionPage/_configs/session_options.py | 13 ++- DrissionPage/_configs/session_options.pyi | 4 +- DrissionPage/_elements/chromium_element.py | 69 +++++++------- DrissionPage/_elements/chromium_element.pyi | 92 +++++++++---------- DrissionPage/_elements/none_element.py | 3 +- DrissionPage/_elements/session_element.py | 20 ++--- DrissionPage/_elements/session_element.pyi | 45 +++++----- DrissionPage/_functions/browser.py | 21 ++--- DrissionPage/_functions/browser.pyi | 2 +- DrissionPage/_functions/tools.py | 8 +- DrissionPage/_functions/tools.pyi | 2 +- DrissionPage/_functions/web.py | 6 +- DrissionPage/_pages/chromium_base.py | 43 ++++++--- DrissionPage/_pages/chromium_base.pyi | 16 ++-- DrissionPage/_pages/chromium_frame.py | 99 +++++++++------------ DrissionPage/_pages/chromium_frame.pyi | 41 +++++---- DrissionPage/_pages/chromium_page.py | 12 +-- DrissionPage/_pages/chromium_page.pyi | 5 +- DrissionPage/_pages/chromium_tab.py | 29 +++--- DrissionPage/_pages/chromium_tab.pyi | 20 ++--- DrissionPage/_pages/session_page.py | 19 ++-- DrissionPage/_pages/session_page.pyi | 12 +-- DrissionPage/_pages/web_page.py | 23 ++--- DrissionPage/_pages/web_page.pyi | 21 ++--- DrissionPage/_units/clicker.pyi | 2 +- DrissionPage/_units/listener.py | 3 + DrissionPage/_units/rect.pyi | 2 +- DrissionPage/_units/selector.pyi | 4 +- DrissionPage/_units/setter.py | 33 ++++--- DrissionPage/_units/setter.pyi | 10 ++- DrissionPage/_units/states.py | 5 +- DrissionPage/_units/waiter.py | 9 +- DrissionPage/_units/waiter.pyi | 4 +- 39 files changed, 399 insertions(+), 398 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index b64e503..6de9f07 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions from ._configs.session_options import SessionOptions __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] -__version__ = '4.0.3.5' +__version__ = '4.0.4' diff --git a/DrissionPage/_base/base.py b/DrissionPage/_base/base.py index 0156fbd..0339ef1 100644 --- a/DrissionPage/_base/base.py +++ b/DrissionPage/_base/base.py @@ -43,8 +43,7 @@ class BaseParser(object): def _ele(self, locator, timeout=None, index=1, raise_err=None, method=None): pass - @abstractmethod - def _find_elements(self, locator, timeout=None, index=1, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): pass @@ -89,10 +88,6 @@ class BaseElement(BaseParser): r.args = {'locator': locator, 'index': index} return r - @abstractmethod - def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): - pass - class DrissionElement(BaseElement): """ChromiumElement 和 SessionElement的基类,但不是ShadowRoot的基类""" @@ -341,12 +336,15 @@ class DrissionElement(BaseElement): return @abstractmethod - def attr(self, attr: str): + def attr(self, name: str): return '' def _get_ele_path(self, mode): return '' + def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): + pass + class BasePage(BaseParser): """页面类的基类""" @@ -380,11 +378,6 @@ class BasePage(BaseParser): """设置查找元素时等待的秒数""" self._timeout = second - @property - def cookies(self): - """返回cookies""" - return self.get_cookies(True) - @property def url_available(self): """返回当前访问的url有效性""" @@ -416,7 +409,7 @@ class BasePage(BaseParser): return @abstractmethod - def get_cookies(self, as_dict=False, all_info=False): + def cookies(self, as_dict=False, all_info=False): return {} @abstractmethod @@ -445,7 +438,3 @@ class BasePage(BaseParser): r.method = method r.args = {'locator': locator, 'index': index} return r - - @abstractmethod - def _find_elements(self, locator, timeout=None, index=1, raise_err=None): - pass diff --git a/DrissionPage/_base/base.pyi b/DrissionPage/_base/base.pyi index 2d4148d..6d7a54b 100644 --- a/DrissionPage/_base/base.pyi +++ b/DrissionPage/_base/base.pyi @@ -34,17 +34,17 @@ class BaseParser(object): def s_eles(self, locator: Union[Tuple[str, str], str]): ... def _ele(self, - locator, + locator: Union[Tuple[str, str], str], timeout: float = None, index: Optional[int] = 1, raise_err: bool = None, method: str = None): ... - @abstractmethod def _find_elements(self, - locator, + locator: Union[Tuple[str, str], str], timeout: float = None, index: Optional[int] = 1, + relative: bool = False, raise_err: bool = None): ... @@ -65,14 +65,6 @@ class BaseElement(BaseParser): raise_err: bool = None, method: str = None): ... - @abstractmethod - def _find_elements(self, - locator, - timeout: float = None, - index: Optional[int] = 1, - relative: bool = False, - raise_err: bool = None): ... - def parent(self, level_or_loc: Union[tuple, str, int] = 1): ... def prev(self, index: int = 1) -> None: ... @@ -109,57 +101,57 @@ class DrissionElement(BaseElement): index: int = 1) -> Union[DrissionElement, None]: ... def child(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def prev(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def next(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def before(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def after(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> Union[DrissionElement, str, NoneElement]: ... def children(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def prevs(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def nexts(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def befores(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... def afters(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[DrissionElement, str]]: ... @@ -167,14 +159,14 @@ class DrissionElement(BaseElement): func: str, direction: str, brother: bool, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', index: int = 1, timeout: float = None, ele_only: bool = True) -> DrissionElement: ... def _get_relatives(self, index: int = None, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', direction: str = 'following', brother: bool = True, timeout: float = 0.5, @@ -191,7 +183,7 @@ class DrissionElement(BaseElement): def raw_text(self) -> str: ... @abstractmethod - def attr(self, attr: str) -> str: ... + def attr(self, name: str) -> str: ... def _get_ele_path(self, mode) -> str: ... @@ -217,9 +209,6 @@ class BasePage(BaseParser): @timeout.setter def timeout(self, second: float) -> None: ... - @property - def cookies(self) -> dict: ... - @property def url_available(self) -> bool: ... @@ -240,7 +229,7 @@ class BasePage(BaseParser): def user_agent(self) -> str: ... @abstractmethod - def get_cookies(self, as_dict: bool = False, all_info: bool = False) -> Union[list, dict]: ... + def cookies(self, as_dict: bool = False, all_info: bool = False) -> Union[list, dict]: ... @abstractmethod def get(self, url: str, show_errmsg: bool = False, retry: int = None, interval: float = None): ... @@ -251,10 +240,3 @@ class BasePage(BaseParser): index: Optional[int] = 1, raise_err: bool = None, method: str = None): ... - - @abstractmethod - def _find_elements(self, - locator, - timeout: float = None, - index: Optional[int] = 1, - raise_err: bool = None): ... diff --git a/DrissionPage/_base/driver.py b/DrissionPage/_base/driver.py index feb7e18..b442109 100644 --- a/DrissionPage/_base/driver.py +++ b/DrissionPage/_base/driver.py @@ -189,8 +189,9 @@ class Driver(object): timeout = kwargs.pop('_timeout', 30) result = self._send({'method': _method, 'params': kwargs}, timeout=timeout) if 'result' not in result and 'error' in result: + kwargs['_timeout'] = timeout return {'error': result['error']['message'], 'type': result.get('type', 'call_method_error'), - 'method': _method, 'args': kwargs, 'timeout': timeout} + 'method': _method, 'args': kwargs} else: return result['result'] diff --git a/DrissionPage/_configs/chromium_options.py b/DrissionPage/_configs/chromium_options.py index b224634..c5054af 100644 --- a/DrissionPage/_configs/chromium_options.py +++ b/DrissionPage/_configs/chromium_options.py @@ -26,7 +26,7 @@ class ChromiumOptions(object): if read_file is not False: ini_path = str(ini_path) if ini_path else None om = OptionsManager(ini_path) - self.ini_path = om.ini_path + self.ini_path = str(Path(om.ini_path).absolute()) options = om.chromium_options self._download_path = om.paths.get('download_path', None) or None @@ -56,7 +56,7 @@ class ChromiumOptions(object): timeouts = om.timeouts self._timeouts = {'base': timeouts['base'], - 'pageLoad': timeouts['page_load'], + 'page_load': timeouts['page_load'], 'script': timeouts['script']} self._auto_port = options.get('auto_port', False) @@ -75,7 +75,7 @@ class ChromiumOptions(object): self._extensions = [] self._prefs = {} self._flags = {} - self._timeouts = {'base': 10, 'pageLoad': 30, 'script': 30} + self._timeouts = {'base': 10, 'page_load': 30, 'script': 30} self._address = '127.0.0.1:9222' self._load_mode = 'normal' self._proxy = None @@ -278,18 +278,18 @@ class ChromiumOptions(object): self.clear_file_flags = True return self - def set_timeouts(self, base=None, pageLoad=None, script=None, implicit=None): + def set_timeouts(self, base=None, page_load=None, script=None, implicit=None): """设置超时时间,单位为秒 :param base: 默认超时时间 - :param pageLoad: 页面加载超时时间 + :param page_load: 页面加载超时时间 :param script: 脚本运行超时时间 :return: 当前对象 """ base = base if base is not None else implicit if base is not None: self._timeouts['base'] = base - if pageLoad is not None: - self._timeouts['pageLoad'] = pageLoad + if page_load is not None: + self._timeouts['page_load'] = page_load if script is not None: self._timeouts['script'] = script @@ -545,7 +545,7 @@ class ChromiumOptions(object): om.set_item('paths', 'tmp_path', self._tmp_path or '') # 设置timeout om.set_item('timeouts', 'base', self._timeouts['base']) - om.set_item('timeouts', 'page_load', self._timeouts['pageLoad']) + om.set_item('timeouts', 'page_load', self._timeouts['page_load']) om.set_item('timeouts', 'script', self._timeouts['script']) # 设置重试 om.set_item('others', 'retry_times', self.retry_times) diff --git a/DrissionPage/_configs/chromium_options.pyi b/DrissionPage/_configs/chromium_options.pyi index 0b7db3c..8dd05b2 100644 --- a/DrissionPage/_configs/chromium_options.pyi +++ b/DrissionPage/_configs/chromium_options.pyi @@ -109,7 +109,9 @@ class ChromiumOptions(object): def clear_flags_in_file(self) -> ChromiumOptions: ... - def set_timeouts(self, base: float = None, pageLoad: float = None, + def set_timeouts(self, + base: float = None, + page_load: float = None, script: float = None) -> ChromiumOptions: ... def set_user(self, user: str = 'Default') -> ChromiumOptions: ... diff --git a/DrissionPage/_configs/session_options.py b/DrissionPage/_configs/session_options.py index 532098a..135210a 100644 --- a/DrissionPage/_configs/session_options.py +++ b/DrissionPage/_configs/session_options.py @@ -171,28 +171,27 @@ class SessionOptions(object): self._headers = {key.lower(): headers[key] for key in headers} return self - def set_a_header(self, attr, value): + def set_a_header(self, name, value): """设置headers中一个项 - :param attr: 设置名称 + :param name: 设置名称 :param value: 设置值 :return: 返回当前对象 """ if self._headers is None: self._headers = {} - self._headers[attr.lower()] = value + self._headers[name.lower()] = value return self - def remove_a_header(self, attr): + def remove_a_header(self, name): """从headers中删除一个设置 - :param attr: 要删除的设置 + :param name: 要删除的设置 :return: 返回当前对象 """ if self._headers is None: return self - attr = attr.lower() - self._headers.pop(attr, None) + self._headers.pop(name.lower(), None) return self diff --git a/DrissionPage/_configs/session_options.pyi b/DrissionPage/_configs/session_options.pyi index cc1b4e9..532dd06 100644 --- a/DrissionPage/_configs/session_options.pyi +++ b/DrissionPage/_configs/session_options.pyi @@ -51,9 +51,9 @@ class SessionOptions(object): def set_headers(self, headers: Union[dict, None]) -> SessionOptions: ... - def set_a_header(self, attr: str, value: str) -> SessionOptions: ... + def set_a_header(self, name: str, value: str) -> SessionOptions: ... - def remove_a_header(self, attr: str) -> SessionOptions: ... + def remove_a_header(self, name: str) -> SessionOptions: ... @property def cookies(self) -> list: ... diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index 2b4e678..a50566b 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -78,8 +78,7 @@ class ChromiumElement(DrissionElement): self._doc_id = doc['objectId'] if doc else None def __repr__(self): - attrs = self.attrs - attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs] + attrs = [f"{k}='{v}'" for k, v in self.attrs.items()] return f'' def __call__(self, locator, index=1, timeout=None): @@ -128,10 +127,9 @@ class ChromiumElement(DrissionElement): @property def raw_text(self): """返回未格式化处理的元素内文本""" - return self.prop('innerText') + return self.property('innerText') # -----------------d模式独有属性------------------- - @property def set(self): """返回用于设置元素属性的对象""" @@ -206,6 +204,29 @@ class ChromiumElement(DrissionElement): return self._select + @property + def value(self): + return self.property('value') + + # -----即将废弃开始-------- + @property + def location(self): + """返回元素左上角的绝对坐标""" + return self.rect.location + + @property + def size(self): + """返回元素宽和高组成的元组""" + return self.rect.size + + def prop(self, prop): + return self.property(prop) + + def get_src(self, timeout=None, base64_to_bytes=True): + return self.src(timeout=timeout, base64_to_bytes=base64_to_bytes) + + # -----即将废弃结束-------- + def check(self, uncheck=False, by_js=False): """选中或取消选中当前元素 :param uncheck: 是否取消选中 @@ -345,10 +366,10 @@ class ChromiumElement(DrissionElement): if not link or link.lower().startswith(('javascript:', 'mailto:')): return link else: - return make_absolute_link(link, self.prop('baseURI')) + return make_absolute_link(link, self.property('baseURI')) elif attr == 'src': - return make_absolute_link(attrs.get('src', None), self.prop('baseURI')) + return make_absolute_link(attrs.get('src', None), self.property('baseURI')) elif attr == 'text': return self.text @@ -365,20 +386,20 @@ class ChromiumElement(DrissionElement): else: return attrs.get(attr, None) - def remove_attr(self, attr): + def remove_attr(self, name): """删除元素一个attribute属性 - :param attr: 属性名 + :param name: 属性名 :return: None """ - self.run_js(f'this.removeAttribute("{attr}");') + self.run_js(f'this.removeAttribute("{name}");') - def prop(self, prop): + def property(self, name): """获取一个property属性值 - :param prop: 属性名 + :param name: 属性名 :return: 属性值文本 """ try: - value = self.run_js(f'return this.{prop};') + value = self.run_js(f'return this.{name};') return format_html(value) if isinstance(value, str) else value except: return None @@ -467,7 +488,7 @@ class ChromiumElement(DrissionElement): pseudo_ele = f', "{pseudo_ele}"' if pseudo_ele.startswith(':') else f', "::{pseudo_ele}"' return self.run_js(f'return window.getComputedStyle(this{pseudo_ele}).getPropertyValue("{style}");') - def get_src(self, timeout=None, base64_to_bytes=True): + def src(self, timeout=None, base64_to_bytes=True): """返回元素src资源,base64的可转为bytes返回,其它返回str :param timeout: 等待资源加载的超时时间(秒) :param base64_to_bytes: 为True时,如果是base64数据,转换为bytes格式 @@ -501,7 +522,7 @@ class ChromiumElement(DrissionElement): break else: - src = self.prop('currentSrc') + src = self.property('currentSrc') if not src: continue @@ -533,7 +554,7 @@ class ChromiumElement(DrissionElement): :param timeout: 等待资源加载的超时时间(秒) :return: 返回保存路径 """ - data = self.get_src(timeout=timeout) + data = self.src(timeout=timeout) if not data: raise NoResourceError @@ -543,7 +564,7 @@ class ChromiumElement(DrissionElement): if src.lower().startswith('data:image'): r = search(r'data:image/(.*?);base64,', src) name = f'img.{r.group(1)}' if r else None - name = name or basename(self.prop('currentSrc')) + name = name or basename(self.property('currentSrc')) path = get_usable_path(f'{path}{sep}{name}').absolute() write_type = 'wb' if isinstance(data, bytes) else 'w' @@ -595,7 +616,7 @@ class ChromiumElement(DrissionElement): self.clear(True) if isinstance(vals, (list, tuple)): vals = ''.join([str(i) for i in vals]) - self.set.prop('value', str(vals)) + self.set.property('value', str(vals)) self.run_js('this.dispatchEvent(new Event("change", {bubbles: true}));') return @@ -751,18 +772,6 @@ class ChromiumElement(DrissionElement): files = [str(Path(i).absolute()) for i in files] self.page.run_cdp('DOM.setFileInputFiles', files=files, backendNodeId=self._backend_id) - # -------------即将废弃------------- - - @property - def location(self): - """返回元素左上角的绝对坐标""" - return self.rect.location - - @property - def size(self): - """返回元素宽和高组成的元组""" - return self.rect.size - class ShadowRoot(BaseElement): """ShadowRoot是用于处理ShadowRoot的类,使用方法和ChromiumElement基本一致""" @@ -1421,7 +1430,7 @@ def run_js(page_or_ele, script, as_expr, timeout, args=None): else: raise ElementLostError('原来获取到的元素对象已不在页面内。') - if res is None and page.states.has_alert: # 存在alert的情况 + if res is None and page.states.has_alert: return None exceptionDetails = res.get('exceptionDetails') diff --git a/DrissionPage/_elements/chromium_element.pyi b/DrissionPage/_elements/chromium_element.pyi index 1403ae1..69f7bb4 100644 --- a/DrissionPage/_elements/chromium_element.pyi +++ b/DrissionPage/_elements/chromium_element.pyi @@ -8,7 +8,6 @@ from pathlib import Path from typing import Union, Tuple, List, Any, Literal, Optional -from .none_element import NoneElement from .._base.base import DrissionElement, BaseElement from .._elements.session_element import SessionElement from .._pages.chromium_base import ChromiumBase @@ -50,7 +49,7 @@ class ChromiumElement(DrissionElement): def __call__(self, locator: Union[Tuple[str, str], str], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... + timeout: float = None) -> ChromiumElement: ... def __eq__(self, other: ChromiumElement) -> bool: ... @@ -73,7 +72,6 @@ class ChromiumElement(DrissionElement): def raw_text(self) -> str: ... # -----------------d模式独有属性------------------- - @property def set(self) -> ChromiumElementSetter: ... @@ -100,60 +98,60 @@ class ChromiumElement(DrissionElement): def parent(self, level_or_loc: Union[tuple, str, int] = 1, - index: int = 1) -> Union[ChromiumElement, NoneElement]: ... + index: int = 1) -> ChromiumElement: ... def child(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def prev(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def next(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def before(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def after(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def children(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def prevs(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def nexts(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def befores(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def afters(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... @@ -163,13 +161,16 @@ class ChromiumElement(DrissionElement): @property def select(self) -> SelectElement: ... + @property + def value(self) -> None: ... + def check(self, uncheck: bool = False, by_js: bool = False) -> None: ... - def attr(self, attr: str) -> Union[str, None]: ... + def attr(self, name: str) -> Union[str, None]: ... - def remove_attr(self, attr: str) -> None: ... + def remove_attr(self, name: str) -> None: ... - def prop(self, prop: str) -> Union[str, int, None]: ... + def property(self, name: str) -> Union[str, int, None]: ... def run_js(self, script: str, *args, as_expr: bool = False, timeout: float = None) -> Any: ... @@ -178,7 +179,7 @@ class ChromiumElement(DrissionElement): def ele(self, locator: Union[Tuple[str, str], str], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... + timeout: float = None) -> ChromiumElement: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -186,7 +187,7 @@ class ChromiumElement(DrissionElement): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, locator: Union[Tuple[str, str], str] = None) -> List[SessionElement]: ... @@ -195,12 +196,12 @@ class ChromiumElement(DrissionElement): timeout: float = None, index: Optional[int] = 1, relative: bool = False, - raise_err: bool = False) -> Union[ChromiumElement, ChromiumFrame, NoneElement, + raise_err: bool = False) -> Union[ChromiumElement, ChromiumFrame, List[Union[ChromiumElement, ChromiumFrame]]]: ... def style(self, style: str, pseudo_ele: str = '') -> str: ... - def get_src(self, timeout: float = None, base64_to_bytes: bool = True) -> Union[bytes, str, None]: ... + def src(self, timeout: float = None, base64_to_bytes: bool = True) -> Union[bytes, str, None]: ... def save(self, path: [str, bool] = None, name: str = None, timeout: float = None) -> str: ... @@ -273,33 +274,33 @@ class ShadowRoot(BaseElement): def parent(self, level_or_loc: Union[str, int] = 1, index: int = 1) -> ChromiumElement: ... def child(self, - locator: Union[tuple, str] = '', - index: int = 1) -> Union[ChromiumElement, NoneElement]: ... + locator: Union[Tuple[str, str], str] = '', + index: int = 1) -> ChromiumElement: ... def next(self, - locator: Union[tuple, str] = '', - index: int = 1) -> Union[ChromiumElement, NoneElement]: ... + locator: Union[Tuple[str, str], str] = '', + index: int = 1) -> ChromiumElement: ... def before(self, - locator: Union[tuple, str] = '', - index: int = 1) -> Union[ChromiumElement, NoneElement]: ... + locator: Union[Tuple[str, str], str] = '', + index: int = 1) -> ChromiumElement: ... def after(self, - locator: Union[tuple, str] = '', - index: int = 1) -> Union[ChromiumElement, NoneElement]: ... + locator: Union[Tuple[str, str], str] = '', + index: int = 1) -> ChromiumElement: ... - def children(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def children(self, locator: Union[Tuple[str, str], str] = '') -> List[ChromiumElement]: ... - def nexts(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def nexts(self, locator: Union[Tuple[str, str], str] = '') -> List[ChromiumElement]: ... - def befores(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def befores(self, locator: Union[Tuple[str, str], str] = '') -> List[ChromiumElement]: ... - def afters(self, locator: Union[tuple, str] = '') -> List[ChromiumElement]: ... + def afters(self, locator: Union[Tuple[str, str], str] = '') -> List[ChromiumElement]: ... def ele(self, locator: Union[Tuple[str, str], str], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... + timeout: float = None) -> ChromiumElement: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -307,7 +308,7 @@ class ShadowRoot(BaseElement): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... @@ -316,7 +317,7 @@ class ShadowRoot(BaseElement): timeout: float = None, index: Optional[int] = 1, relative: bool = False, - raise_err: bool = None) -> Union[ChromiumElement, ChromiumFrame, NoneElement, str, + raise_err: bool = None) -> Union[ChromiumElement, ChromiumFrame, str, List[Union[ChromiumElement, ChromiumFrame, str]]]: ... def _get_node_id(self, obj_id: str) -> int: ... @@ -330,28 +331,27 @@ def find_in_chromium_ele(ele: ChromiumElement, loc: Union[str, Tuple[str, str]], index: Optional[int] = 1, timeout: float = None, - relative: bool = True) -> Union[ChromiumElement, NoneElement, List[ChromiumElement]]: ... + relative: bool = True) -> Union[ChromiumElement, List[ChromiumElement]]: ... def find_by_xpath(ele: ChromiumElement, xpath: str, index: Optional[int], timeout: float, - relative: bool = True) -> Union[ChromiumElement, List[ChromiumElement], NoneElement]: ... + relative: bool = True) -> Union[ChromiumElement, List[ChromiumElement]]: ... def find_by_css(ele: ChromiumElement, selector: str, index: Optional[int], - timeout: float) -> Union[ChromiumElement, List[ChromiumElement], NoneElement]: ... + timeout: float) -> Union[ChromiumElement, List[ChromiumElement],]: ... def make_chromium_eles(page: Union[ChromiumBase, ChromiumPage, WebPage, ChromiumTab, ChromiumFrame], _ids: Union[tuple, list, str, int], index: Optional[int] = 1, is_obj_id: bool = True - ) -> Union[ChromiumElement, ChromiumFrame, NoneElement, -List[Union[ChromiumElement, ChromiumFrame]]]: ... + ) -> Union[ChromiumElement, ChromiumFrame, List[Union[ChromiumElement, ChromiumFrame]]]: ... def make_js_for_find_ele_by_xpath(xpath: str, type_txt: str, node_txt: str) -> str: ... diff --git a/DrissionPage/_elements/none_element.py b/DrissionPage/_elements/none_element.py index fac5415..15502f3 100644 --- a/DrissionPage/_elements/none_element.py +++ b/DrissionPage/_elements/none_element.py @@ -18,6 +18,7 @@ class NoneElement(object): self._none_ele_return_value = False self.method = method self.args = args + self._get = None def __call__(self, *args, **kwargs): if not self._none_ele_return_value: @@ -33,7 +34,7 @@ class NoneElement(object): return self else: if item in ('size', 'link', 'css_path', 'xpath', 'comments', 'texts', 'tag', 'html', 'inner_html', - 'attrs', 'text', 'raw_text'): + 'attrs', 'text', 'raw_text', 'value', 'attr', 'style', 'src', 'property'): return self._none_ele_value else: raise ElementNotFoundError(None, self.method, self.args) diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index 8b6173d..208c8e4 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -34,7 +34,7 @@ class SessionElement(DrissionElement): return self._inner_ele def __repr__(self): - attrs = [f"{attr}='{self.attrs[attr]}'" for attr in self.attrs] + attrs = [f"{k}='{v}'" for k, v in self.attrs.items()] return f'' def __call__(self, locator, timeout=None): @@ -188,13 +188,13 @@ class SessionElement(DrissionElement): """ return super().afters(locator, timeout, ele_only=ele_only) - def attr(self, attr): + def attr(self, name): """返回attribute属性值 - :param attr: 属性名 + :param name: 属性名 :return: 属性值文本,没有该属性返回None """ # 获取href属性时返回绝对url - if attr == 'href': + if name == 'href': link = self.inner_ele.get('href') # 若为链接为None、js或邮件,直接返回 if not link or link.lower().startswith(('javascript:', 'mailto:')): @@ -203,23 +203,23 @@ class SessionElement(DrissionElement): else: # 其它情况直接返回绝对url return make_absolute_link(link, self.page.url) - elif attr == 'src': + elif name == 'src': return make_absolute_link(self.inner_ele.get('src'), self.page.url) - elif attr == 'text': + elif name == 'text': return self.text - elif attr == 'innerText': + elif name == 'innerText': return self.raw_text - elif attr in ('html', 'outerHTML'): + elif name in ('html', 'outerHTML'): return self.html - elif attr == 'innerHTML': + elif name == 'innerHTML': return self.inner_html else: - return self.inner_ele.get(attr) + return self.inner_ele.get(name) def ele(self, locator, index=1, timeout=None): """返回当前元素下级符合条件的一个元素、属性或节点文本 diff --git a/DrissionPage/_elements/session_element.pyi b/DrissionPage/_elements/session_element.pyi index 66d6156..563beae 100644 --- a/DrissionPage/_elements/session_element.pyi +++ b/DrissionPage/_elements/session_element.pyi @@ -9,7 +9,6 @@ from typing import Union, List, Tuple, Optional from lxml.html import HtmlElement -from .none_element import NoneElement from .._base.base import DrissionElement, BaseElement from .._elements.chromium_element import ChromiumElement from .._pages.chromium_base import ChromiumBase @@ -31,7 +30,7 @@ class SessionElement(DrissionElement): def __call__(self, locator: Union[Tuple[str, str], str], index: int = 1, - timeout: float = None) -> Union[SessionElement, NoneElement]: ... + timeout: float = None) -> SessionElement: ... def __eq__(self, other: SessionElement) -> bool: ... @@ -55,69 +54,69 @@ class SessionElement(DrissionElement): def parent(self, level_or_loc: Union[tuple, str, int] = 1, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def child(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[SessionElement, str]: ... def prev(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[SessionElement, str]: ... def next(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[SessionElement, str]: ... def before(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[SessionElement, str]: ... def after(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[SessionElement, str, NoneElement]: ... + ele_only: bool = True) -> Union[SessionElement, str]: ... def children(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def prevs(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def nexts(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def befores(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... def afters(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[SessionElement, str]]: ... - def attr(self, attr: str) -> Optional[str]: ... + def attr(self, name: str) -> Optional[str]: ... def ele(self, locator: Union[Tuple[str, str], str], index: int = 1, - timeout: float = None) -> Union[SessionElement, NoneElement]: ... + timeout: float = None) -> SessionElement: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -125,7 +124,7 @@ class SessionElement(DrissionElement): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... @@ -134,7 +133,7 @@ class SessionElement(DrissionElement): timeout: float = None, index: Optional[int] = 1, relative: bool = False, - raise_err: bool = None) -> Union[SessionElement, NoneElement, List[SessionElement]]: ... + raise_err: bool = None) -> Union[SessionElement, List[SessionElement]]: ... def _get_ele_path(self, mode: str) -> str: ... @@ -142,4 +141,4 @@ class SessionElement(DrissionElement): def make_session_ele(html_or_ele: Union[str, SessionElement, SessionPage, ChromiumElement, BaseElement, ChromiumFrame, ChromiumBase], loc: Union[str, Tuple[str, str]] = None, - index: Optional[int] = 1) -> Union[SessionElement, NoneElement, List[SessionElement]]: ... + index: Optional[int] = 1) -> Union[SessionElement, List[SessionElement]]: ... diff --git a/DrissionPage/_functions/browser.py b/DrissionPage/_functions/browser.py index 54b1b5a..ad8803e 100644 --- a/DrissionPage/_functions/browser.py +++ b/DrissionPage/_functions/browser.py @@ -26,7 +26,7 @@ def connect_browser(option): :return: 返回是否接管的浏览器 """ address = option.address.replace('localhost', '127.0.0.1').lstrip('http://').lstrip('https://') - chrome_path = option.browser_path + browser_path = option.browser_path ip, port = address.split(':') if ip != '127.0.0.1' or port_is_using(ip, port) or option.is_existing_only: @@ -43,16 +43,16 @@ def connect_browser(option): set_prefs(option) set_flags(option) try: - _run_browser(port, chrome_path, args) + _run_browser(port, browser_path, args) # 传入的路径找不到,主动在ini文件、注册表、系统变量中找 except FileNotFoundError: - chrome_path = get_chrome_path() + browser_path = get_chrome_path(option.ini_path) - if not chrome_path: + if not browser_path: raise FileNotFoundError('无法找到浏览器可执行文件路径,请手动配置。') - _run_browser(port, chrome_path, args) + _run_browser(port, browser_path, args) test_connect(ip, port) return False @@ -219,7 +219,7 @@ def test_connect(ip, port, timeout=30): def _run_browser(port, path: str, args) -> Popen: - """创建chrome进程 + """创建浏览器进程 :param port: 端口号 :param path: 浏览器路径 :param args: 启动参数 @@ -282,12 +282,13 @@ def _remove_arg_from_dict(target_dict: dict, arg: str) -> None: pass -def get_chrome_path(): +def get_chrome_path(ini_path): """从ini文件或系统变量中获取chrome可执行文件的路径""" # -----------从ini文件中获取-------------- - path = OptionsManager().chromium_options.get('browser_path', None) - if path and Path(path).is_file(): - return str(path) + if ini_path: + path = OptionsManager(ini_path).chromium_options.get('browser_path', None) + if path and Path(path).is_file(): + return str(path) # -----------使用which获取----------- from shutil import which diff --git a/DrissionPage/_functions/browser.pyi b/DrissionPage/_functions/browser.pyi index 6285a34..8815ab4 100644 --- a/DrissionPage/_functions/browser.pyi +++ b/DrissionPage/_functions/browser.pyi @@ -25,4 +25,4 @@ def set_flags(opt: ChromiumOptions) -> None: ... def test_connect(ip: str, port: Union[int, str], timeout: float = 30) -> None: ... -def get_chrome_path() -> Union[str, None]: ... +def get_chrome_path(ini_path: str) -> Union[str, None]: ... diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index 4ae6f5a..ee4ba25 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -112,7 +112,7 @@ def show_or_hide_browser(page, hide=True): pid = page.process_id if not pid: return None - hds = get_chrome_hwnds_from_pid(pid, page.title) + hds = get_hwnds_from_pid(pid, page.title) sw = SW_HIDE if hide else SW_SHOW for hd in hds: ShowWindow(hd, sw) @@ -141,7 +141,7 @@ def get_browser_progress_id(progress, address): return txt.split(' ')[-1] -def get_chrome_hwnds_from_pid(pid, title): +def get_hwnds_from_pid(pid, title): """通过PID查询句柄ID :param pid: 进程id :param title: 窗口标题 @@ -240,11 +240,11 @@ def raise_error(result, ignore=None): elif error == 'Given expression does not evaluate to a function': r = JavaScriptError(f'传入的js无法解析成函数:\n{result["args"]["functionDeclaration"]}') elif error.endswith("' wasn't found"): - r = RuntimeError(f'你的浏览器可能太旧。\nmethod:{result["method"]}\nargs:{result["args"]}') + r = RuntimeError(f'你的浏览器可能太旧。\n方法:{result["method"]}\n参数:{result["args"]}') elif result['type'] in ('call_method_error', 'timeout'): from DrissionPage import __version__ from time import process_time - txt = f'\n错误:{result["error"]}\nmethod:{result["method"]}\nargs:{result["args"]}\n' \ + txt = f'\n错误:{result["error"]}\n方法:{result["method"]}\n参数:{result["args"]}\n' \ f'版本:{__version__}\n运行时间:{process_time()}\n出现这个错误可能意味着程序有bug,请把错误信息和重现方法' \ '告知作者,谢谢。\n报告网站:https://gitee.com/g1879/DrissionPage/issues' r = TimeoutError(txt) if result['type'] == 'timeout' else CDPError(txt) diff --git a/DrissionPage/_functions/tools.pyi b/DrissionPage/_functions/tools.pyi index dd9d507..f6e13f5 100644 --- a/DrissionPage/_functions/tools.pyi +++ b/DrissionPage/_functions/tools.pyi @@ -36,7 +36,7 @@ def show_or_hide_browser(page: ChromiumPage, hide: bool = True) -> None: ... def get_browser_progress_id(progress: Union[popen, None], address: str) -> Union[str, None]: ... -def get_chrome_hwnds_from_pid(pid: Union[str, int], title: str) -> list: ... +def get_hwnds_from_pid(pid: Union[str, int], title: str) -> list: ... def wait_until(function: callable, kwargs: dict = None, timeout: float = 10): ... diff --git a/DrissionPage/_functions/web.py b/DrissionPage/_functions/web.py index c34c778..fcc5baa 100644 --- a/DrissionPage/_functions/web.py +++ b/DrissionPage/_functions/web.py @@ -161,8 +161,8 @@ def is_js_func(func): func = func.strip() if (func.startswith('function') or func.startswith('async ')) and func.endswith('}'): return True - elif '=>' in func: - return True + # elif '=>' in func: + # return True return False @@ -361,3 +361,5 @@ def get_blob(page, url, as_bytes=True): if as_bytes: from base64 import b64decode return b64decode(result.split(',', 1)[-1]) + else: + return result diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 489c19d..eb0aa96 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -474,8 +474,8 @@ class ChromiumBase(BasePage): show_errmsg=show_errmsg, timeout=timeout) return self._url_available - def get_cookies(self, as_dict=False, all_domains=False, all_info=False): - """获取cookies信息 + def cookies(self, as_dict=False, all_domains=False, all_info=False): + """返回cookies信息 :param as_dict: 为True时返回由{name: value}键值对组成的dict,为True时返回list且all_info无效 :param all_domains: 是否返回所有域的cookies :param all_info: 是否返回所有信息,为False时只返回name、value、domain @@ -722,8 +722,8 @@ class ChromiumBase(BasePage): frames = self._ele(locator, timeout=timeout, index=None, raise_err=False) return [i for i in frames if i._type == 'ChromiumFrame'] - def get_session_storage(self, item=None): - """获取sessionStorage信息,不设置item则获取全部 + def session_storage(self, item=None): + """返回sessionStorage信息,不设置item则获取全部 :param item: 要获取的项,不设置则返回全部 :return: sessionStorage一个或所有项内容 """ @@ -743,8 +743,8 @@ class ChromiumBase(BasePage): ''' return {i['key']: i['val'] for i in self.run_js_loaded(js)} - def get_local_storage(self, item=None): - """获取localStorage信息,不设置item则获取全部 + def local_storage(self, item=None): + """返回localStorage信息,不设置item则获取全部 :param item: 要获取的项目,不设置则返回全部 :return: localStorage一个或所有项内容 """ @@ -930,7 +930,11 @@ class ChromiumBase(BasePage): :param interval: 重试间隔 :return: 重试次数和间隔组成的tuple """ - self._url = quote(url, safe='-_.~!*\'"();:@&=+$,/\\?#[]%') or 'chrome://newtab/' + p = Path(url) + if p.exists(): + self._url = str(p.absolute()) + else: + self._url = quote(url, safe='-_.~!*\'"();:@&=+$,/\\?#[]%') or 'chrome://newtab/' retry = retry if retry is not None else self.retry_times interval = interval if interval is not None else self.retry_interval return retry, interval @@ -1033,11 +1037,12 @@ class ChromiumBase(BasePage): pic_type = path.suffix.lower() pic_type = 'jpeg' if pic_type == '.jpg' else pic_type[1:] - width, height = self.rect.size if full_page: + width, height = self.rect.size + if width == 0 or height == 0: + raise RuntimeError('页面大小为0,请尝试等待页面加载完成。') vp = {'x': 0, 'y': 0, 'width': width, 'height': height, 'scale': 1} - png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type, - captureBeyondViewport=True, clip=vp)['data'] + args = {'format': pic_type, 'captureBeyondViewport': True, 'clip': vp} else: if left_top and right_bottom: x, y = left_top @@ -1051,11 +1056,14 @@ class ChromiumBase(BasePage): x += 10 vp = {'x': x, 'y': y, 'width': w, 'height': h, 'scale': 1} - png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type, - captureBeyondViewport=v, clip=vp)['data'] + args = {'format': pic_type, 'captureBeyondViewport': v, 'clip': vp} else: - png = self.run_cdp_loaded('Page.captureScreenshot', format=pic_type)['data'] + args = {'format': pic_type} + + if pic_type == 'jpeg': + args['quality'] = 100 + png = self.run_cdp_loaded('Page.captureScreenshot', **args)['data'] if as_base64: return png @@ -1095,6 +1103,15 @@ class ChromiumBase(BasePage): """返回页面总宽高,格式:(宽, 高)""" return self.rect.size + def get_session_storage(self, item=None): + return self.session_storage(item) + + def get_local_storage(self, item=None): + return self.local_storage(item) + + def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + return self.cookies(as_dict=as_dict, all_domains=all_domains, all_info=all_info) + class Timeout(object): """用于保存d模式timeout信息的类""" diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index dca5bc0..0b51500 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -13,7 +13,6 @@ from .._base.base import BasePage from .._base.browser import Browser from .._base.driver import Driver from .._elements.chromium_element import ChromiumElement -from .._elements.none_element import NoneElement from .._elements.session_element import SessionElement from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_page import ChromiumPage @@ -97,7 +96,7 @@ class ChromiumBase(BasePage): def __call__(self, locator: Union[Tuple[str, str], str, ChromiumElement], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... + timeout: float = None) -> ChromiumElement: ... @property def _js_ready_state(self) -> str: ... @@ -177,13 +176,12 @@ class ChromiumBase(BasePage): def get(self, url: str, show_errmsg: bool = False, retry: int = None, interval: float = None, timeout: float = None) -> Union[None, bool]: ... - def get_cookies(self, as_dict: bool = False, all_domains: bool = False, - all_info: bool = False) -> Union[list, dict]: ... + def cookies(self, as_dict: bool = False, all_domains: bool = False, all_info: bool = False) -> Union[list, dict]: ... def ele(self, locator: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... + timeout: float = None) -> ChromiumElement: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -191,7 +189,7 @@ class ChromiumBase(BasePage): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... @@ -201,7 +199,7 @@ class ChromiumBase(BasePage): index: Optional[int] = 1, relative: bool = False, raise_err: bool = None) \ - -> Union[ChromiumElement, ChromiumFrame, NoneElement, List[Union[ChromiumElement, ChromiumFrame]]]: ... + -> Union[ChromiumElement, ChromiumFrame, List[Union[ChromiumElement, ChromiumFrame]]]: ... def refresh(self, ignore_cache: bool = False) -> None: ... @@ -223,9 +221,9 @@ class ChromiumBase(BasePage): def run_cdp_loaded(self, cmd: str, **cmd_args) -> dict: ... - def get_session_storage(self, item: str = None) -> Union[str, dict, None]: ... + def session_storage(self, item: str = None) -> Union[str, dict, None]: ... - def get_local_storage(self, item: str = None) -> Union[str, dict, None]: ... + def local_storage(self, item: str = None) -> Union[str, dict, None]: ... def add_init_js(self, script: str) -> str: ... diff --git a/DrissionPage/_pages/chromium_frame.py b/DrissionPage/_pages/chromium_frame.py index dd8946d..5544fe4 100644 --- a/DrissionPage/_pages/chromium_frame.py +++ b/DrissionPage/_pages/chromium_frame.py @@ -78,8 +78,7 @@ class ChromiumFrame(ChromiumBase): return self._frame_id == getattr(other, '_frame_id', None) def __repr__(self): - attrs = self._frame_ele.attrs - attrs = [f"{attr}='{attrs[attr]}'" for attr in attrs] + attrs = [f"{k}='{v}'" for k, v in self._frame_ele.attrs.items()] return f'' def _d_set_runtime_settings(self): @@ -146,19 +145,6 @@ class ChromiumFrame(ChromiumBase): if timeout <= 0: timeout = .5 self._wait_loaded(timeout) - # while perf_counter() < end_time: - # try: - # obj_id = super().run_js('document;', as_expr=True)['objectId'] - # self.doc_ele = ChromiumElement(self, obj_id=obj_id) - # break - # except Exception as e: - # sleep(.1) - # if self._debug: - # print(f'获取doc失败,重试 {e}') - # else: - # raise GetDocumentError - - # self.driver._debug = d_debug self._is_loading = False self._reloading = False @@ -208,7 +194,6 @@ class ChromiumFrame(ChromiumBase): self._reload() # ----------挂件---------- - @property def scroll(self): """返回用于滚动的对象""" @@ -252,7 +237,7 @@ class ChromiumFrame(ChromiumBase): self._listener = FrameListener(self) return self._listener - # ----------挂件---------- + # ----------挂件结束---------- @property def _obj_id(self): @@ -305,11 +290,6 @@ class ChromiumFrame(ChromiumBase): r = self._ele('t:title', raise_err=False) return r.text if r else None - @property - def cookies(self): - """以dict格式返回cookies""" - return super().cookies if self._is_diff_domain else self.doc_ele.run_js('return this.cookie;') - @property def attrs(self): """返回frame元素所有attribute属性""" @@ -356,23 +336,57 @@ class ChromiumFrame(ChromiumBase): except: return None + # ----------------即将废弃----------------- + @property + def is_alive(self): + """返回是否仍可用""" + return self.states.is_alive + + @property + def page_size(self): + """返回frame内页面尺寸,格式:(宽,, 高)""" + return self.rect.size + + @property + def size(self): + """返回frame元素大小""" + return self.frame_ele.rect.size + + @property + def location(self): + """返回frame元素左上角的绝对坐标""" + return self.frame_ele.rect.location + + @property + def locations(self): + """返回用于获取元素位置的对象""" + return self.frame_ele.rect + # ----------------即将废弃结束----------------- + def refresh(self): """刷新frame页面""" self.doc_ele.run_js('this.location.reload();') - def attr(self, attr): - """返回frame元素attribute属性值 - :param attr: 属性名 + def property(self, name): + """返回frame元素一个property属性值 + :param name: 属性名 :return: 属性值文本,没有该属性返回None """ - return self.frame_ele.attr(attr) + return self.frame_ele.property(name) - def remove_attr(self, attr): + def attr(self, name): + """返回frame元素一个attribute属性值 + :param name: 属性名 + :return: 属性值文本,没有该属性返回None + """ + return self.frame_ele.attr(name) + + def remove_attr(self, name): """删除frame元素attribute属性 - :param attr: 属性名 + :param name: 属性名 :return: None """ - self.frame_ele.remove_attr(attr) + self.frame_ele.remove_attr(name) def run_js(self, script, *args, as_expr=False, timeout=None): """运行javascript代码 @@ -580,30 +594,3 @@ class ChromiumFrame(ChromiumBase): def _is_inner_frame(self): """返回当前frame是否同域""" return self._frame_id in str(self._target_page.run_cdp('Page.getFrameTree')['frameTree']) - - # ----------------即将废弃----------------- - - @property - def is_alive(self): - """返回是否仍可用""" - return self.states.is_alive - - @property - def page_size(self): - """返回frame内页面尺寸,格式:(宽,, 高)""" - return self.rect.size - - @property - def size(self): - """返回frame元素大小""" - return self.frame_ele.rect.size - - @property - def location(self): - """返回frame元素左上角的绝对坐标""" - return self.frame_ele.rect.location - - @property - def locations(self): - """返回用于获取元素位置的对象""" - return self.frame_ele.rect diff --git a/DrissionPage/_pages/chromium_frame.pyi b/DrissionPage/_pages/chromium_frame.pyi index 15eaa6c..a98db83 100644 --- a/DrissionPage/_pages/chromium_frame.pyi +++ b/DrissionPage/_pages/chromium_frame.pyi @@ -13,7 +13,6 @@ from .chromium_page import ChromiumPage from .chromium_tab import ChromiumTab from .web_page import WebPage from .._elements.chromium_element import ChromiumElement -from .._elements.none_element import NoneElement from .._units.listener import FrameListener from .._units.rect import FrameRect from .._units.scroller import FrameScroller @@ -32,6 +31,7 @@ class ChromiumFrame(ChromiumBase): self._target_page: ChromiumBase = ... self.tab: ChromiumTab = ... self._tab_id: str = ... + self._set: ChromiumFrameSetter = ... self._frame_ele: ChromiumElement = ... self._backend_id: int = ... self._doc_ele: ChromiumElement = ... @@ -45,7 +45,7 @@ class ChromiumFrame(ChromiumBase): def __call__(self, locator: Union[Tuple[str, str], str], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, NoneElement]: ... + timeout: float = None) -> ChromiumElement: ... def __eq__(self, other: ChromiumFrame) -> bool: ... @@ -86,9 +86,6 @@ class ChromiumFrame(ChromiumBase): @property def title(self) -> str: ... - @property - def cookies(self) -> dict: ... - @property def attrs(self) -> dict: ... @@ -133,9 +130,11 @@ class ChromiumFrame(ChromiumBase): def refresh(self) -> None: ... - def attr(self, attr: str) -> Union[str, None]: ... + def property(self, name: str) -> Union[str, None]: ... - def remove_attr(self, attr: str) -> None: ... + def attr(self, name: str) -> Union[str, None]: ... + + def remove_attr(self, name: str) -> None: ... def run_js(self, script: str, @@ -144,50 +143,50 @@ class ChromiumFrame(ChromiumBase): timeout: float = None) -> Any: ... def parent(self, - level_or_loc: Union[tuple, str, int] = 1, - index: int = 1) -> Union[ChromiumElement, NoneElement]: ... + level_or_loc: Union[Tuple[str, str], str, int] = 1, + index: int = 1) -> ChromiumElement: ... def prev(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = 0, - ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def next(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = 0, - ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def before(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def after(self, - locator: Union[tuple, str, int] = '', + locator: Union[Tuple[str, str], str, int] = '', index: int = 1, timeout: float = None, - ele_only: bool = True) -> Union[ChromiumElement, NoneElement, str]: ... + ele_only: bool = True) -> Union[ChromiumElement, str]: ... def prevs(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = 0, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def nexts(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = 0, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def befores(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... def afters(self, - locator: Union[tuple, str] = '', + locator: Union[Tuple[str, str], str] = '', timeout: float = None, ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... diff --git a/DrissionPage/_pages/chromium_page.py b/DrissionPage/_pages/chromium_page.py index 554552d..a57f531 100644 --- a/DrissionPage/_pages/chromium_page.py +++ b/DrissionPage/_pages/chromium_page.py @@ -24,7 +24,7 @@ from ..errors import BrowserConnectError class ChromiumPage(ChromiumBase): """用于管理浏览器的类""" - PAGES = {} + _PAGES = {} def __new__(cls, addr_or_opts=None, tab_id=None, timeout=None, addr_driver_opts=None): """ @@ -35,8 +35,8 @@ class ChromiumPage(ChromiumBase): addr_or_opts = addr_or_opts or addr_driver_opts opt = handle_options(addr_or_opts) is_exist, browser_id = run_browser(opt) - if browser_id in cls.PAGES: - r = cls.PAGES[browser_id] + if browser_id in cls._PAGES: + r = cls._PAGES[browser_id] while not hasattr(r, '_frame_id'): sleep(.1) return r @@ -45,7 +45,7 @@ class ChromiumPage(ChromiumBase): r._is_exist = is_exist r._browser_id = browser_id r.address = opt.address - cls.PAGES[browser_id] = r + cls._PAGES[browser_id] = r return r def __init__(self, addr_or_opts=None, tab_id=None, timeout=None, addr_driver_opts=None): @@ -79,7 +79,7 @@ class ChromiumPage(ChromiumBase): def _d_set_runtime_settings(self): """设置运行时用到的属性""" - self._timeouts = Timeout(self, page_load=self._chromium_options.timeouts['pageLoad'], + self._timeouts = Timeout(self, page_load=self._chromium_options.timeouts['page_load'], script=self._chromium_options.timeouts['script'], base=self._chromium_options.timeouts['base']) if self._chromium_options.timeouts['base'] is not None: @@ -255,7 +255,7 @@ class ChromiumPage(ChromiumBase): def _on_disconnect(self): """浏览器退出时执行""" - ChromiumPage.PAGES.pop(self._browser_id, None) + ChromiumPage._PAGES.pop(self._browser_id, None) def __repr__(self): return f'' diff --git a/DrissionPage/_pages/chromium_page.pyi b/DrissionPage/_pages/chromium_page.pyi index 7e9065f..8b74035 100644 --- a/DrissionPage/_pages/chromium_page.pyi +++ b/DrissionPage/_pages/chromium_page.pyi @@ -19,7 +19,7 @@ from .._units.waiter import PageWaiter class ChromiumPage(ChromiumBase): - PAGES: dict = ... + _PAGES: dict = ... def __new__(cls, addr_or_opts: Union[str, int, ChromiumOptions] = None, @@ -55,9 +55,6 @@ class ChromiumPage(ChromiumBase): @property def wait(self) -> PageWaiter: ... - @property - def main_tab(self) -> str: ... - @property def latest_tab(self) -> str: ... diff --git a/DrissionPage/_pages/chromium_tab.py b/DrissionPage/_pages/chromium_tab.py index 25d0ec1..6baeb61 100644 --- a/DrissionPage/_pages/chromium_tab.py +++ b/DrissionPage/_pages/chromium_tab.py @@ -20,20 +20,20 @@ from .._units.waiter import TabWaiter class ChromiumTab(ChromiumBase): """实现浏览器标签页的类""" - TABS = {} + _TABS = {} def __new__(cls, page, tab_id): """ :param page: ChromiumPage对象 :param tab_id: 要控制的标签页id """ - if Settings.singleton_tab_obj and tab_id in cls.TABS: - r = cls.TABS[tab_id] + if Settings.singleton_tab_obj and tab_id in cls._TABS: + r = cls._TABS[tab_id] while not hasattr(r, '_frame_id'): sleep(.1) return r r = object.__new__(cls) - cls.TABS[tab_id] = r + cls._TABS[tab_id] = r return r def __init__(self, page, tab_id): @@ -96,7 +96,7 @@ class ChromiumTab(ChromiumBase): return f'' def _on_disconnect(self): - ChromiumTab.TABS.pop(self.tab_id, None) + ChromiumTab._TABS.pop(self.tab_id, None) class WebPageTab(SessionPage, ChromiumTab, BasePage): @@ -188,11 +188,6 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): """返回当前模式,'s'或'd' """ return self._mode - @property - def cookies(self): - """以dict方式返回cookies""" - return super().cookies - @property def user_agent(self): """返回user agent""" @@ -357,15 +352,15 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): user_agent = self.run_cdp('Runtime.evaluate', expression='navigator.userAgent;')['result']['value'] self._headers.update({"User-Agent": user_agent}) - set_session_cookies(self.session, super(SessionPage, self).get_cookies()) + set_session_cookies(self.session, super(SessionPage, self).cookies()) def cookies_to_browser(self): """把session对象的cookies复制到浏览器""" if not self._has_driver: return - set_browser_cookies(self, super().get_cookies()) + set_browser_cookies(self, super().cookies()) - def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + def cookies(self, as_dict=False, all_domains=False, all_info=False): """返回cookies :param as_dict: 是否以字典方式返回 :param all_domains: 是否返回所有域的cookies @@ -373,9 +368,9 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): :return: cookies信息 """ if self._mode == 's': - return super().get_cookies(as_dict, all_domains, all_info) + return super().cookies(as_dict, all_domains, all_info) elif self._mode == 'd': - return super(SessionPage, self).get_cookies(as_dict, all_domains, all_info) + return super(SessionPage, self).cookies(as_dict, all_domains, all_info) def close(self): """关闭当前标签页""" @@ -400,3 +395,7 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage): def __repr__(self): return f'' + + # --------即将废弃------- + def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + return self.cookies(as_dict=as_dict, all_domains=all_domains, all_info=all_info) \ No newline at end of file diff --git a/DrissionPage/_pages/chromium_tab.pyi b/DrissionPage/_pages/chromium_tab.pyi index e4b55b8..2a5f6a5 100644 --- a/DrissionPage/_pages/chromium_tab.pyi +++ b/DrissionPage/_pages/chromium_tab.pyi @@ -6,7 +6,6 @@ @License : BSD 3-Clause. """ from pathlib import Path -from threading import Lock from typing import Union, Tuple, Any, List, Optional from requests import Session, Response @@ -18,7 +17,6 @@ from .session_page import SessionPage from .web_page import WebPage from .._base.browser import Browser from .._elements.chromium_element import ChromiumElement -from .._elements.none_element import NoneElement from .._elements.session_element import SessionElement from .._units.rect import TabRect from .._units.setter import TabSetter, WebPageTabSetter @@ -26,8 +24,7 @@ from .._units.waiter import TabWaiter class ChromiumTab(ChromiumBase): - TABS: dict = ... - LOCK: Lock = ... + _TABS: dict = ... def __new__(cls, page: ChromiumPage, tab_id: str): ... @@ -82,7 +79,7 @@ class WebPageTab(SessionPage, ChromiumTab): def __call__(self, locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... + timeout: float = None) -> Union[ChromiumElement, SessionElement]: ... @property def page(self) -> WebPage: ... @@ -111,9 +108,6 @@ class WebPageTab(SessionPage, ChromiumTab): @property def mode(self) -> str: ... - @property - def cookies(self) -> dict: ... - @property def user_agent(self) -> str: ... @@ -152,7 +146,7 @@ class WebPageTab(SessionPage, ChromiumTab): def ele(self, locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... + timeout: float = None) -> Union[ChromiumElement, SessionElement]: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -160,7 +154,7 @@ class WebPageTab(SessionPage, ChromiumTab): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... @@ -170,8 +164,8 @@ class WebPageTab(SessionPage, ChromiumTab): def cookies_to_browser(self) -> None: ... - def get_cookies(self, as_dict: bool = False, all_domains: bool = False, - all_info: bool = False) -> Union[dict, list]: ... + def cookies(self, as_dict: bool = False, all_domains: bool = False, + all_info: bool = False) -> Union[dict, list]: ... def close(self) -> None: ... @@ -205,5 +199,5 @@ class WebPageTab(SessionPage, ChromiumTab): index: Optional[int] = 1, relative: bool = False, raise_err: bool = None) \ - -> Union[ChromiumElement, SessionElement, ChromiumFrame, NoneElement, List[SessionElement], List[ + -> Union[ChromiumElement, SessionElement, ChromiumFrame, List[SessionElement], List[ Union[ChromiumElement, ChromiumFrame]]]: ... diff --git a/DrissionPage/_pages/session_page.py b/DrissionPage/_pages/session_page.py index 38177b4..7c13ad2 100644 --- a/DrissionPage/_pages/session_page.py +++ b/DrissionPage/_pages/session_page.py @@ -47,8 +47,11 @@ class SessionPage(BasePage): :param session_or_options: Session、SessionOptions对象 :return: None """ - if not session_or_options or isinstance(session_or_options, SessionOptions): - self._session_options = session_or_options or SessionOptions(session_or_options) + if not session_or_options: + self._session_options = SessionOptions(session_or_options) + + elif isinstance(session_or_options, SessionOptions): + self._session_options = session_or_options elif isinstance(session_or_options, Session): self._session_options = SessionOptions() @@ -208,7 +211,7 @@ class SessionPage(BasePage): """ return self._ele(locator, index=None) - def _find_elements(self, locator, timeout=None, index=1, raise_err=None): + def _find_elements(self, locator, timeout=None, index=1, relative=True, raise_err=None): """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 :param timeout: 不起实际作用,用于和父类对应 @@ -218,7 +221,7 @@ class SessionPage(BasePage): """ return locator if isinstance(locator, SessionElement) else make_session_ele(self, locator, index=index) - def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + def cookies(self, as_dict=False, all_domains=False, all_info=False): """返回cookies :param as_dict: 是否以字典方式返回,False则以list返回 :param all_domains: 是否返回所有域的cookies @@ -310,7 +313,7 @@ class SessionPage(BasePage): parsed_url = urlparse(url) hostname = parsed_url.hostname scheme = parsed_url.scheme - if not check_headers(kwargs, self._headers, 'Referer'): + if not check_headers(kwargs['headers'], self._headers, 'Referer'): kwargs['headers']['Referer'] = self.url if self.url else f'{scheme}://{hostname}' if 'Host' not in kwargs['headers']: kwargs['headers']['Host'] = hostname @@ -364,10 +367,14 @@ class SessionPage(BasePage): def __repr__(self): return f'' + # ---------即将废弃--------- + def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + return self.cookies(as_dict=as_dict, all_domains=all_domains, all_info=all_info) + def check_headers(kwargs, headers, arg): """检查kwargs或headers中是否有arg所示属性""" - return arg in kwargs['headers'] or arg in headers + return arg in kwargs or arg in headers def set_charset(response): diff --git a/DrissionPage/_pages/session_page.pyi b/DrissionPage/_pages/session_page.pyi index 15f9b24..90673e2 100644 --- a/DrissionPage/_pages/session_page.pyi +++ b/DrissionPage/_pages/session_page.pyi @@ -13,7 +13,6 @@ from requests.structures import CaseInsensitiveDict from .._base.base import BasePage from .._configs.session_options import SessionOptions -from .._elements.none_element import NoneElement from .._elements.session_element import SessionElement from .._units.setter import SessionPageSetter @@ -43,7 +42,7 @@ class SessionPage(BasePage): def __call__(self, locator: Union[Tuple[str, str], str, SessionElement], index: int = 1, - timeout: float = None) -> Union[SessionElement, NoneElement]: ... + timeout: float = None) -> SessionElement: ... # -----------------共有属性和方法------------------- @property @@ -93,7 +92,7 @@ class SessionPage(BasePage): def ele(self, locator: Union[Tuple[str, str], str, SessionElement], index: int = 1, - timeout: float = None) -> Union[SessionElement, NoneElement]: ... + timeout: float = None) -> SessionElement: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -101,7 +100,7 @@ class SessionPage(BasePage): def s_ele(self, locator: Union[Tuple[str, str], str, SessionElement] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, loc: Union[Tuple[str, str], str]) -> List[SessionElement]: ... @@ -109,10 +108,11 @@ class SessionPage(BasePage): locator: Union[Tuple[str, str], str, SessionElement], timeout: float = None, index: Optional[int] = 1, + relative: bool = True, raise_err: bool = None) \ - -> Union[SessionElement, NoneElement, List[SessionElement]]: ... + -> Union[SessionElement, List[SessionElement]]: ... - def get_cookies(self, + def cookies(self, as_dict: bool = False, all_domains: bool = False, all_info: bool = False) -> Union[dict, list]: ... diff --git a/DrissionPage/_pages/web_page.py b/DrissionPage/_pages/web_page.py index 8fa0b15..dd0b843 100644 --- a/DrissionPage/_pages/web_page.py +++ b/DrissionPage/_pages/web_page.py @@ -126,11 +126,6 @@ class WebPage(SessionPage, ChromiumPage, BasePage): """返回当前模式,'s'或'd' """ return self._mode - @property - def cookies(self): - """以dict方式返回cookies""" - return super().cookies - @property def user_agent(self): """返回user agent""" @@ -281,7 +276,9 @@ class WebPage(SessionPage, ChromiumPage, BasePage): if go: url = super(SessionPage, self).url if url.startswith('http'): - self.get(url) + r = self.get(url) + if not r: + raise ConnectionError('s模式访问失败,请设置go=False,自行构造连接参数进行访问。') def cookies_to_session(self, copy_user_agent=True): """把driver对象的cookies复制到session对象 @@ -295,15 +292,15 @@ class WebPage(SessionPage, ChromiumPage, BasePage): user_agent = self.run_cdp('Runtime.evaluate', expression='navigator.userAgent;')['result']['value'] self._headers.update({"User-Agent": user_agent}) - set_session_cookies(self.session, super(SessionPage, self).get_cookies()) + set_session_cookies(self.session, super(SessionPage, self).cookies()) def cookies_to_browser(self): """把session对象的cookies复制到浏览器""" if not self._has_driver: return - set_browser_cookies(self, super().get_cookies()) + set_browser_cookies(self, super().cookies()) - def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + def cookies(self, as_dict=False, all_domains=False, all_info=False): """返回cookies :param as_dict: 是否以字典方式返回,False以list形式返回 :param all_domains: 是否返回所有域的cookies @@ -311,9 +308,9 @@ class WebPage(SessionPage, ChromiumPage, BasePage): :return: cookies信息 """ if self._mode == 's': - return super().get_cookies(as_dict, all_domains, all_info) + return super().cookies(as_dict, all_domains, all_info) elif self._mode == 'd': - return super(SessionPage, self).get_cookies(as_dict, all_domains, all_info) + return super(SessionPage, self).cookies(as_dict, all_domains, all_info) def get_tab(self, id_or_num=None): """获取一个标签页对象 @@ -408,3 +405,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def __repr__(self): return f'' + + # -------即将废弃-------- + def get_cookies(self, as_dict=False, all_domains=False, all_info=False): + return self.cookies(as_dict=as_dict, all_domains=all_domains, all_info=all_info) diff --git a/DrissionPage/_pages/web_page.pyi b/DrissionPage/_pages/web_page.pyi index 517dfd3..0f11253 100644 --- a/DrissionPage/_pages/web_page.pyi +++ b/DrissionPage/_pages/web_page.pyi @@ -18,7 +18,6 @@ from .._base.driver import Driver from .._configs.chromium_options import ChromiumOptions from .._configs.session_options import SessionOptions from .._elements.chromium_element import ChromiumElement -from .._elements.none_element import NoneElement from .._elements.session_element import SessionElement from .._units.setter import WebPageSetter @@ -31,6 +30,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): chromium_options: Union[ChromiumOptions, bool] = None, session_or_options: Union[Session, SessionOptions, bool] = None) -> None: self._mode: str = ... + self._set: WebPageSetter = ... self._has_driver: bool = ... self._has_session: bool = ... self._session_options: Union[SessionOptions, None] = ... @@ -39,7 +39,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def __call__(self, locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... + timeout: float = None) -> Union[ChromiumElement, SessionElement]: ... # -----------------共有属性和方法------------------- @property @@ -66,9 +66,6 @@ class WebPage(SessionPage, ChromiumPage, BasePage): @property def mode(self) -> str: ... - @property - def cookies(self) -> dict: ... - @property def user_agent(self) -> str: ... @@ -107,7 +104,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def ele(self, locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, SessionElement, NoneElement]: ... + timeout: float = None) -> Union[ChromiumElement, SessionElement]: ... def eles(self, locator: Union[Tuple[str, str], str], @@ -115,7 +112,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> Union[SessionElement, NoneElement]: ... + index: int = 1) -> SessionElement: ... def s_eles(self, locator: Union[Tuple[str, str], str]) -> List[SessionElement]: ... @@ -125,10 +122,10 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def cookies_to_browser(self) -> None: ... - def get_cookies(self, - as_dict: bool = False, - all_domains: bool = False, - all_info: bool = False) -> Union[dict, list]: ... + def cookies(self, + as_dict: bool = False, + all_domains: bool = False, + all_info: bool = False) -> Union[dict, list]: ... def get_tab(self, id_or_num: Union[str, WebPageTab, int] = None) -> WebPageTab: ... @@ -174,7 +171,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): index: Optional[int] = 1, relative: bool = False, raise_err: bool = None) \ - -> Union[ChromiumElement, SessionElement, ChromiumFrame, NoneElement, List[SessionElement], + -> Union[ChromiumElement, SessionElement, ChromiumFrame, List[SessionElement], List[Union[ChromiumElement, ChromiumFrame]]]: ... def _set_start_options(self, diff --git a/DrissionPage/_units/clicker.pyi b/DrissionPage/_units/clicker.pyi index 895f762..5ac0a16 100644 --- a/DrissionPage/_units/clicker.pyi +++ b/DrissionPage/_units/clicker.pyi @@ -5,7 +5,7 @@ @Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. @License : BSD 3-Clause. """ -from typing import Union, Optional +from typing import Optional from .._elements.chromium_element import ChromiumElement diff --git a/DrissionPage/_units/listener.py b/DrissionPage/_units/listener.py index 80ee15a..80ebe03 100644 --- a/DrissionPage/_units/listener.py +++ b/DrissionPage/_units/listener.py @@ -100,6 +100,9 @@ class Listener(object): Manifest, SignedExchange, Ping, CSPViolationReport, Preflight, Other :return: None """ + if targets is not None: + if is_regex is None: + is_regex = False if targets or is_regex is not None or method or res_type: self.set_targets(targets, is_regex, method, res_type) self.clear() diff --git a/DrissionPage/_units/rect.pyi b/DrissionPage/_units/rect.pyi index 2e442ce..62fadc1 100644 --- a/DrissionPage/_units/rect.pyi +++ b/DrissionPage/_units/rect.pyi @@ -6,7 +6,7 @@ @License : BSD 3-Clause. """ -from typing import Tuple, Union, List +from typing import Tuple, Union from .._elements.chromium_element import ChromiumElement from .._pages.chromium_base import ChromiumBase diff --git a/DrissionPage/_units/selector.pyi b/DrissionPage/_units/selector.pyi index 06f0553..87877ad 100644 --- a/DrissionPage/_units/selector.pyi +++ b/DrissionPage/_units/selector.pyi @@ -38,7 +38,7 @@ class SelectElement(object): def by_index(self, index: Union[int, list, tuple], timeout: float = None) -> bool: ... - def by_locator(self, locator: Union[str, Tuple[str, str]], timeout: float = None) -> bool: ... + def by_locator(self, locator: Union[Tuple[str, str], str], timeout: float = None) -> bool: ... def by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None: ... @@ -48,7 +48,7 @@ class SelectElement(object): def cancel_by_index(self, index: Union[int, list, tuple], timeout: float = None) -> bool: ... - def cancel_by_locator(self, locator: Union[str, Tuple[str, str]], timeout: float = None) -> bool: ... + def cancel_by_locator(self, locator: Union[Tuple[str, str], str], timeout: float = None) -> bool: ... def cancel_by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None: ... diff --git a/DrissionPage/_units/setter.py b/DrissionPage/_units/setter.py index 2e10d4f..48301c3 100644 --- a/DrissionPage/_units/setter.py +++ b/DrissionPage/_units/setter.py @@ -293,13 +293,13 @@ class SessionPageSetter(BasePageSetter): """ self._page._headers = CaseInsensitiveDict(headers) - def header(self, attr, value): + def header(self, name, value): """设置headers中一个项 - :param attr: 设置名称 + :param name: 设置名称 :param value: 设置值 :return: None """ - self._page._headers[attr] = value + self._page._headers[name] = value def user_agent(self, ua): """设置user agent @@ -450,39 +450,46 @@ class ChromiumElementSetter(object): """ self._ele = ele - def attr(self, attr, value): + def attr(self, name, value): """设置元素attribute属性 - :param attr: 属性名 + :param name: 属性名 :param value: 属性值 :return: None """ - self._ele.page.run_cdp('DOM.setAttributeValue', nodeId=self._ele._node_id, name=attr, value=str(value)) + self._ele.page.run_cdp('DOM.setAttributeValue', nodeId=self._ele._node_id, name=name, value=str(value)) - def prop(self, prop, value): + def property(self, name, value): """设置元素property属性 - :param prop: 属性名 + :param name: 属性名 :param value: 属性值 :return: None """ value = value.replace('"', r'\"') - self._ele.run_js(f'this.{prop}="{value}";') + self._ele.run_js(f'this.{name}="{value}";') def innerHTML(self, html): """设置元素innerHTML :param html: html文本 :return: None """ - self.prop('innerHTML', html) + self.property('innerHTML', html) + + def value(self, value): + """设置元素value值 + :param value: value值 + :return: None + """ + self.property('value', value) class ChromiumFrameSetter(ChromiumBaseSetter): - def attr(self, attr, value): + def attr(self, name, value): """设置frame元素attribute属性 - :param attr: 属性名 + :param name: 属性名 :param value: 属性值 :return: None """ - self._page.frame_ele.set.attr(attr, value) + self._page.frame_ele.set.attr(name, value) class LoadMode(object): diff --git a/DrissionPage/_units/setter.pyi b/DrissionPage/_units/setter.pyi index a5ece0b..901e084 100644 --- a/DrissionPage/_units/setter.pyi +++ b/DrissionPage/_units/setter.pyi @@ -113,7 +113,7 @@ class SessionPageSetter(BasePageSetter): def headers(self, headers: dict) -> None: ... - def header(self, attr: str, value: str) -> None: ... + def header(self, name: str, value: str) -> None: ... def user_agent(self, ua: str) -> None: ... @@ -168,17 +168,19 @@ class ChromiumElementSetter(object): def __init__(self, ele: ChromiumElement): self._ele: ChromiumElement = ... - def attr(self, attr: str, value: str) -> None: ... + def attr(self, name: str, value: str) -> None: ... - def prop(self, prop: str, value: str) -> None: ... + def property(self, name: str, value: str) -> None: ... def innerHTML(self, html: str) -> None: ... + def value(self, value: str) -> None: ... + class ChromiumFrameSetter(ChromiumBaseSetter): _page: ChromiumFrame = ... - def attr(self, attr: str, value: str) -> None: ... + def attr(self, name: str, value: str) -> None: ... class LoadMode(object): diff --git a/DrissionPage/_units/states.py b/DrissionPage/_units/states.py index bdf99cc..e6bc267 100644 --- a/DrissionPage/_units/states.py +++ b/DrissionPage/_units/states.py @@ -29,8 +29,9 @@ class ElementStates(object): @property def is_displayed(self): """返回元素是否显示""" - return not (self._ele.style('visibility') == 'hidden' or self._ele.run_js('return this.offsetParent === null;') - or self._ele.style('display') == 'none' or self._ele.prop('hidden')) + return not (self._ele.style('visibility') == 'hidden' or + self._ele.run_js('return this.offsetParent === null;') + or self._ele.style('display') == 'none' or self._ele.property('hidden')) @property def is_enabled(self): diff --git a/DrissionPage/_units/waiter.py b/DrissionPage/_units/waiter.py index 09867c9..5398a1b 100644 --- a/DrissionPage/_units/waiter.py +++ b/DrissionPage/_units/waiter.py @@ -119,6 +119,8 @@ class BaseWaiter(object): :param cancel_it: 是否取消该任务 :return: 成功返回任务对象,失败返回False """ + if not self._driver.browser._dl_mgr._running: + raise RuntimeError('使用下载管理功能前需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。') self._driver.browser._dl_mgr.set_flag(self._driver.tab_id, False if cancel_it else True) if timeout is None: timeout = self._driver.timeout @@ -232,6 +234,8 @@ class TabWaiter(BaseWaiter): :param cancel_if_timeout: 超时时是否取消剩余任务 :return: 是否等待成功 """ + if not self._driver.browser._dl_mgr._running: + raise RuntimeError('使用下载管理功能前需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。') if not timeout: while self._driver.browser._dl_mgr.get_tab_missions(self._driver.tab_id): sleep(.5) @@ -290,6 +294,8 @@ class PageWaiter(TabWaiter): :param cancel_if_timeout: 超时时是否取消剩余任务 :return: 是否等待成功 """ + if not self._driver.browser._dl_mgr._running: + raise RuntimeError('使用下载管理功能前需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。') if not timeout: while self._driver.browser._dl_mgr._missions: sleep(.5) @@ -458,7 +464,8 @@ class ElementWaiter(object): timeout = self._page.timeout end_time = perf_counter() + timeout while perf_counter() < end_time: - if self._ele.states.__getattribute__(attr) == mode: + a = self._ele.states.__getattribute__(attr) + if (a and mode) or (not a and not mode): return True sleep(.05) diff --git a/DrissionPage/_units/waiter.pyi b/DrissionPage/_units/waiter.pyi index c5eb2a9..92ed44b 100644 --- a/DrissionPage/_units/waiter.pyi +++ b/DrissionPage/_units/waiter.pyi @@ -5,7 +5,7 @@ @Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. @License : BSD 3-Clause. """ -from typing import Union +from typing import Union, Tuple from .downloader import DownloadMission from .._elements.chromium_element import ChromiumElement @@ -34,7 +34,7 @@ class BaseWaiter(object): raise_err: bool = None) -> bool: ... def ele_loaded(self, - locator: Union[str, tuple], + locator: Union[Tuple[str, str], str], timeout: float = None, raise_err: bool = None) -> Union[bool, ChromiumElement]: ...