4.0.4.24 支持对eles()结果进行筛选

This commit is contained in:
g1879 2024-06-05 19:06:52 +08:00
parent a13177f86e
commit 6624c2651a
9 changed files with 153 additions and 17 deletions

View File

@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions
from ._configs.session_options import SessionOptions from ._configs.session_options import SessionOptions
__all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__'] __all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__']
__version__ = '4.0.4.23' __version__ = '4.0.4.24'

View File

@ -19,6 +19,7 @@ from .._base.base import DrissionElement, BaseElement
from .._functions.keys import input_text_or_keys from .._functions.keys import input_text_or_keys
from .._functions.locator import get_loc from .._functions.locator import get_loc
from .._functions.settings import Settings 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 .._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.clicker import Clicker
from .._units.rect import ElementRect from .._units.rect import ElementRect
@ -55,6 +56,7 @@ class ChromiumElement(DrissionElement):
self._tag = None self._tag = None
self._wait = None self._wait = None
self._type = 'ChromiumElement' self._type = 'ChromiumElement'
self._doc_id = None
if node_id and obj_id and backend_id: if node_id and obj_id and backend_id:
self._node_id = node_id self._node_id = node_id
@ -75,9 +77,6 @@ class ChromiumElement(DrissionElement):
else: else:
raise ElementLostError raise ElementLostError
doc = self.run_js('return this.ownerDocument;')
self._doc_id = doc['objectId'] if doc else None
def __repr__(self): def __repr__(self):
attrs = [f"{k}='{v}'" for k, v in self.attrs.items()] attrs = [f"{k}='{v}'" for k, v in self.attrs.items()]
return f'<ChromiumElement {self.tag} {" ".join(attrs)}>' return f'<ChromiumElement {self.tag} {" ".join(attrs)}>'
@ -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'], res = ele.owner.run_cdp('Runtime.getProperties', objectId=res['result']['objectId'],
ownProperties=True)['result'][:-1] ownProperties=True)['result'][:-1]
if index is None: if index is None:
r = [make_chromium_eles(ele.owner, _ids=i['value']['objectId'], is_obj_id=True) r = ElementsList()
if i['value']['type'] == 'object' else i['value']['value'] for i in res] 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 return None if False in r else r
else: else:
@ -1244,7 +1247,7 @@ def find_by_xpath(ele, xpath, index, timeout, relative=True):
if result: if result:
return 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): def find_by_css(ele, selector, index, timeout):
@ -1290,7 +1293,7 @@ def find_by_css(ele, selector, index, timeout):
if result: if result:
return 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): 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) return get_node_func(page, obj_id, ele_only)
else: # 获取全部 else: # 获取全部
nodes = [] nodes = ElementsList()
for obj_id in _ids: for obj_id in _ids:
tmp = get_node_func(page, obj_id, ele_only) tmp = get_node_func(page, obj_id, ele_only)
if tmp is False: if tmp is False:

View File

@ -10,6 +10,7 @@ from typing import Union, Tuple, List, Any, Literal, Optional
from .._base.base import DrissionElement, BaseElement from .._base.base import DrissionElement, BaseElement
from .._elements.session_element import SessionElement from .._elements.session_element import SessionElement
from .._functions.tools import ElementsList
from .._pages.chromium_base import ChromiumBase from .._pages.chromium_base import ChromiumBase
from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_frame import ChromiumFrame
from .._pages.chromium_page import ChromiumPage from .._pages.chromium_page import ChromiumPage
@ -188,7 +189,7 @@ class ChromiumElement(DrissionElement):
def eles(self, def eles(self,
locator: Union[Tuple[str, str], str], locator: Union[Tuple[str, str], str],
timeout: float = None) -> List[ChromiumElement]: ... timeout: float = None) -> ElementsList: ...
def s_ele(self, def s_ele(self,
locator: Union[Tuple[str, str], str] = None, locator: Union[Tuple[str, str], str] = None,
@ -318,7 +319,7 @@ class ShadowRoot(BaseElement):
def eles(self, def eles(self,
locator: Union[Tuple[str, str], str], locator: Union[Tuple[str, str], str],
timeout: float = None) -> List[ChromiumElement]: ... timeout: float = None) -> ElementsList: ...
def s_ele(self, def s_ele(self,
locator: Union[Tuple[str, str], str] = None, locator: Union[Tuple[str, str], str] = None,

View File

@ -353,8 +353,14 @@ def make_session_ele(html_or_ele, loc=None, index=1):
page = html_or_ele.owner page = html_or_ele.owner
xpath = html_or_ele.xpath xpath = html_or_ele.xpath
# ChromiumElement兼容传入的元素在iframe内的情况 # ChromiumElement兼容传入的元素在iframe内的情况
html = html_or_ele.owner.run_cdp('DOM.getOuterHTML', objectId=html_or_ele._doc_id)['outerHTML'] \ if html_or_ele._doc_id is None:
if html_or_ele._doc_id else html_or_ele.owner.html 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 = fromstring(html)
html_or_ele = html_or_ele.xpath(xpath)[0] html_or_ele = html_or_ele.xpath(xpath)[0]

View File

@ -232,3 +232,94 @@ def raise_error(result, ignore=None):
if not ignore or not isinstance(r, ignore): if not ignore or not isinstance(r, ignore):
raise r 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

View File

@ -8,8 +8,9 @@
from os import popen from os import popen
from pathlib import Path from pathlib import Path
from threading import Lock 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 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: ... 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]: ...

View File

@ -14,6 +14,7 @@ from .._base.browser import Browser
from .._base.driver import Driver from .._base.driver import Driver
from .._elements.chromium_element import ChromiumElement from .._elements.chromium_element import ChromiumElement
from .._elements.session_element import SessionElement from .._elements.session_element import SessionElement
from .._functions.tools import ElementsList
from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_frame import ChromiumFrame
from .._pages.chromium_page import ChromiumPage from .._pages.chromium_page import ChromiumPage
from .._units.actions import Actions from .._units.actions import Actions
@ -187,7 +188,7 @@ class ChromiumBase(BasePage):
def eles(self, def eles(self,
locator: Union[Tuple[str, str], str], locator: Union[Tuple[str, str], str],
timeout: float = None) -> List[ChromiumElement]: ... timeout: float = None) -> ElementsList: ...
def s_ele(self, def s_ele(self,
locator: Union[Tuple[str, str], str] = None, locator: Union[Tuple[str, str], str] = None,

View File

@ -19,6 +19,7 @@ from .._configs.chromium_options import ChromiumOptions
from .._configs.session_options import SessionOptions from .._configs.session_options import SessionOptions
from .._elements.chromium_element import ChromiumElement from .._elements.chromium_element import ChromiumElement
from .._elements.session_element import SessionElement from .._elements.session_element import SessionElement
from .._functions.tools import ElementsList
from .._units.setter import WebPageSetter from .._units.setter import WebPageSetter
@ -108,7 +109,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
def eles(self, def eles(self,
locator: Union[Tuple[str, str], str], 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, def s_ele(self,
locator: Union[Tuple[str, str], str] = None, locator: Union[Tuple[str, str], str] = None,

View File

@ -18,7 +18,7 @@ class ElementStates(object):
@property @property
def is_selected(self): def is_selected(self):
"""返回元素是否被选择""" """返回列表元素是否被选择"""
return self._ele.run_js('return this.selected;') return self._ele.run_js('return this.selected;')
@property @property