From 6624c2651a592a8a37eb3622d64136338fe559ab Mon Sep 17 00:00:00 2001 From: g1879 Date: Wed, 5 Jun 2024 19:06:52 +0800 Subject: [PATCH] =?UTF-8?q?4.0.4.24=20=E6=94=AF=E6=8C=81=E5=AF=B9eles()?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E8=BF=9B=E8=A1=8C=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_elements/chromium_element.py | 19 +++-- DrissionPage/_elements/chromium_element.pyi | 5 +- DrissionPage/_elements/session_element.py | 10 ++- DrissionPage/_functions/tools.py | 91 +++++++++++++++++++++ DrissionPage/_functions/tools.pyi | 35 +++++++- DrissionPage/_pages/chromium_base.pyi | 3 +- DrissionPage/_pages/web_page.pyi | 3 +- DrissionPage/_units/states.py | 2 +- 9 files changed, 153 insertions(+), 17 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index e0efad4..3fc9db9 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.4.23' +__version__ = '4.0.4.24' diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index 0695352..386c8c1 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -19,6 +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.tools import ElementsList 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 @@ -55,6 +56,7 @@ class ChromiumElement(DrissionElement): self._tag = None self._wait = None self._type = 'ChromiumElement' + self._doc_id = None if node_id and obj_id and backend_id: self._node_id = node_id @@ -75,9 +77,6 @@ class ChromiumElement(DrissionElement): else: raise ElementLostError - doc = self.run_js('return this.ownerDocument;') - self._doc_id = doc['objectId'] if doc else None - def __repr__(self): attrs = [f"{k}='{v}'" for k, v in self.attrs.items()] return f'' @@ -1219,8 +1218,12 @@ def find_by_xpath(ele, xpath, index, timeout, relative=True): res = ele.owner.run_cdp('Runtime.getProperties', objectId=res['result']['objectId'], ownProperties=True)['result'][:-1] if index is None: - r = [make_chromium_eles(ele.owner, _ids=i['value']['objectId'], is_obj_id=True) - if i['value']['type'] == 'object' else i['value']['value'] for i in res] + r = ElementsList() + for i in res: + if i['value']['type'] == 'object': + r.append(make_chromium_eles(ele.owner, _ids=i['value']['objectId'], is_obj_id=True)) + else: + r.append(i['value']['value']) return None if False in r else r else: @@ -1244,7 +1247,7 @@ def find_by_xpath(ele, xpath, index, timeout, relative=True): if result: return result - return NoneElement(ele.owner) if index is not None else [] + return NoneElement(ele.owner) if index is not None else ElementsList() def find_by_css(ele, selector, index, timeout): @@ -1290,7 +1293,7 @@ def find_by_css(ele, selector, index, timeout): if result: return result - return NoneElement(ele.owner) if index is not None else [] + return NoneElement(ele.owner) if index is not None else ElementsList() def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=False): @@ -1322,7 +1325,7 @@ def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=False): return get_node_func(page, obj_id, ele_only) else: # 获取全部 - nodes = [] + nodes = ElementsList() for obj_id in _ids: tmp = get_node_func(page, obj_id, ele_only) if tmp is False: diff --git a/DrissionPage/_elements/chromium_element.pyi b/DrissionPage/_elements/chromium_element.pyi index e6a83a8..d44101a 100644 --- a/DrissionPage/_elements/chromium_element.pyi +++ b/DrissionPage/_elements/chromium_element.pyi @@ -10,6 +10,7 @@ from typing import Union, Tuple, List, Any, Literal, Optional from .._base.base import DrissionElement, BaseElement from .._elements.session_element import SessionElement +from .._functions.tools import ElementsList from .._pages.chromium_base import ChromiumBase from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_page import ChromiumPage @@ -188,7 +189,7 @@ class ChromiumElement(DrissionElement): def eles(self, locator: Union[Tuple[str, str], str], - timeout: float = None) -> List[ChromiumElement]: ... + timeout: float = None) -> ElementsList: ... def s_ele(self, locator: Union[Tuple[str, str], str] = None, @@ -318,7 +319,7 @@ class ShadowRoot(BaseElement): def eles(self, locator: Union[Tuple[str, str], str], - timeout: float = None) -> List[ChromiumElement]: ... + timeout: float = None) -> ElementsList: ... def s_ele(self, locator: Union[Tuple[str, str], str] = None, diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index 94525fb..358354f 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -353,8 +353,14 @@ def make_session_ele(html_or_ele, loc=None, index=1): page = html_or_ele.owner xpath = html_or_ele.xpath # ChromiumElement,兼容传入的元素在iframe内的情况 - html = html_or_ele.owner.run_cdp('DOM.getOuterHTML', objectId=html_or_ele._doc_id)['outerHTML'] \ - if html_or_ele._doc_id else html_or_ele.owner.html + if html_or_ele._doc_id is None: + doc = html_or_ele.run_js('return this.ownerDocument;') + html_or_ele._doc_id = doc['objectId'] if doc else False + + if html_or_ele._doc_id: + html = html_or_ele.owner.run_cdp('DOM.getOuterHTML', objectId=html_or_ele._doc_id)['outerHTML'] + else: + html = html_or_ele.owner.html html_or_ele = fromstring(html) html_or_ele = html_or_ele.xpath(xpath)[0] diff --git a/DrissionPage/_functions/tools.py b/DrissionPage/_functions/tools.py index 2486718..46c557d 100644 --- a/DrissionPage/_functions/tools.py +++ b/DrissionPage/_functions/tools.py @@ -232,3 +232,94 @@ def raise_error(result, ignore=None): if not ignore or not isinstance(r, ignore): raise r + + +class ElementsList(list): + def displayed(self): + """返回所有显示的元素""" + return self._any_state('is_displayed') + + def hidden(self): + """返回所有不显示的元素""" + return self._any_state('is_displayed', True) + + def checked(self): + """返回所有被选中的元素""" + return self._any_state('is_checked') + + def not_checked(self): + """返回所有没被选中的元素""" + return self._any_state('is_checked', True) + + def selected(self): + """返回所有被选中的列表元素""" + return self._any_state('is_selected') + + def not_selected(self): + """返回所有没被选中的列表元素""" + return self._any_state('is_selected', True) + + def enabled(self): + """返回所有有效的元素""" + return self._any_state('is_enabled') + + def disabled(self): + """返回所有无效的元素""" + return self._any_state('is_enabled', True) + + def clickable(self): + """返回所有可被点击的元素""" + return self._any_state('is_clickable') + + def not_clickable(self): + """返回所有不可被点击的元素""" + return self._any_state('is_clickable', True) + + def has_rect(self): + """返回所有有大小和位置的元素""" + return self._any_state('has_rect') + + def no_rect(self): + """返回所有没有大小和位置的元素""" + return self._any_state('has_rect', True) + + def style(self, name, value): + """返回所有拥有某个style值的元素 + :param name: 属性名称 + :param value: 属性值 + :return: 筛选结果 + """ + r = ElementsList() + for i in self: + if i.style(name) == value: + r.append(i) + return r + + def property(self, name, value): + """返回所有拥有某个property值的元素 + :param name: 属性名称 + :param value: 属性值 + :return: 筛选结果 + """ + r = ElementsList() + for i in self: + if i.property(name) == value: + r.append(i) + return r + + def _any_state(self, name, is_not=False): + """ + :param name: 状态名称 + :param is_not: 是否选择否定的 + :return: 选中的列表 + """ + r = ElementsList() + if is_not: + for i in self: + if not getattr(i.states, name): + r.append(i) + else: + for i in self: + if getattr(i.states, name): + r.append(i) + return r diff --git a/DrissionPage/_functions/tools.pyi b/DrissionPage/_functions/tools.pyi index a6fc535..499639f 100644 --- a/DrissionPage/_functions/tools.pyi +++ b/DrissionPage/_functions/tools.pyi @@ -8,8 +8,9 @@ from os import popen from pathlib import Path from threading import Lock -from typing import Union, Tuple +from typing import Union, Tuple, List +from .._elements.chromium_element import ChromiumElement from .._pages.chromium_base import ChromiumBase @@ -46,3 +47,35 @@ def configs_to_here(file_name: Union[Path, str] = None) -> None: ... def raise_error(result: dict, ignore=None) -> None: ... + + +class ElementsList(list): + def displayed(self) -> List[ChromiumElement]: ... + + def hidden(self) -> List[ChromiumElement]: ... + + def checked(self) -> List[ChromiumElement]: ... + + def not_checked(self) -> List[ChromiumElement]: ... + + def selected(self) -> List[ChromiumElement]: ... + + def not_selected(self) -> List[ChromiumElement]: ... + + def enabled(self) -> List[ChromiumElement]: ... + + def disabled(self) -> List[ChromiumElement]: ... + + def clickable(self) -> List[ChromiumElement]: ... + + def not_clickable(self) -> List[ChromiumElement]: ... + + def has_rect(self) -> List[ChromiumElement]: ... + + def no_rect(self) -> List[ChromiumElement]: ... + + def style(self, name: str, value: str) -> List[ChromiumElement]: ... + + def property(self, name: str, value: str) -> List[ChromiumElement]: ... + + def _any_state(self, name: str, is_not: bool = False) -> List[ChromiumElement]: ... diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index ddb89b7..1907b7d 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -14,6 +14,7 @@ from .._base.browser import Browser from .._base.driver import Driver from .._elements.chromium_element import ChromiumElement from .._elements.session_element import SessionElement +from .._functions.tools import ElementsList from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_page import ChromiumPage from .._units.actions import Actions @@ -187,7 +188,7 @@ class ChromiumBase(BasePage): def eles(self, locator: Union[Tuple[str, str], str], - timeout: float = None) -> List[ChromiumElement]: ... + timeout: float = None) -> ElementsList: ... def s_ele(self, locator: Union[Tuple[str, str], str] = None, diff --git a/DrissionPage/_pages/web_page.pyi b/DrissionPage/_pages/web_page.pyi index bc0be0b..dbd0317 100644 --- a/DrissionPage/_pages/web_page.pyi +++ b/DrissionPage/_pages/web_page.pyi @@ -19,6 +19,7 @@ from .._configs.chromium_options import ChromiumOptions from .._configs.session_options import SessionOptions from .._elements.chromium_element import ChromiumElement from .._elements.session_element import SessionElement +from .._functions.tools import ElementsList from .._units.setter import WebPageSetter @@ -108,7 +109,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def eles(self, locator: Union[Tuple[str, str], str], - timeout: float = None) -> List[Union[ChromiumElement, SessionElement]]: ... + timeout: float = None) -> Union[ElementsList, List[Union[ChromiumElement, SessionElement]]]: ... def s_ele(self, locator: Union[Tuple[str, str], str] = None, diff --git a/DrissionPage/_units/states.py b/DrissionPage/_units/states.py index 755b27b..47c55dc 100644 --- a/DrissionPage/_units/states.py +++ b/DrissionPage/_units/states.py @@ -18,7 +18,7 @@ class ElementStates(object): @property def is_selected(self): - """返回元素是否被选择""" + """返回列表元素是否被选择""" return self._ele.run_js('return this.selected;') @property