增加get_eles()和filter()方法,未完成

This commit is contained in:
g1879 2024-06-17 07:25:05 +08:00
parent e9c50c2efe
commit 3669e935a2
4 changed files with 179 additions and 44 deletions

View File

@ -236,139 +236,208 @@ def raise_error(result, ignore=None):
class ElementsList(list): class ElementsList(list):
# def __init__(self, page=None, method=None, ):
# super().__init__()
def displayed(self, get_all=False): def displayed(self, get_all=False):
"""返回显示的元素,默认返回第一个 """返回显示的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_displayed', get_all=get_all) return self._any_state('is_displayed', get_all=get_all)
def hidden(self, get_all=False): def hidden(self, get_all=False):
"""返回不显示的元素,默认返回第一个 """返回不显示的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_displayed', True, get_all=get_all) return self._any_state('is_displayed', True, get_all=get_all)
def checked(self, get_all=False): def checked(self, get_all=False):
"""返回被选中的元素,默认返回第一个 """返回被选中的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_checked', get_all=get_all) return self._any_state('is_checked', get_all=get_all)
def not_checked(self, get_all=False): def not_checked(self, get_all=False):
"""返回没被选中的元素""" """返回没被选中的元素,默认返回第一个
:param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表
"""
return self._any_state('is_checked', True, get_all=get_all) return self._any_state('is_checked', True, get_all=get_all)
def selected(self, get_all=False): def selected(self, get_all=False):
"""返回被选中的列表元素,默认返回第一个 """返回被选中的列表元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_selected', get_all=get_all) return self._any_state('is_selected', get_all=get_all)
def not_selected(self, get_all=False): def not_selected(self, get_all=False):
"""返回没被选中的列表元素,默认返回第一个 """返回没被选中的列表元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_selected', True, get_all=get_all) return self._any_state('is_selected', True, get_all=get_all)
def enabled(self, get_all=False): def enabled(self, get_all=False):
"""返回有效的元素,默认返回第一个 """返回有效的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_enabled', get_all=get_all) return self._any_state('is_enabled', get_all=get_all)
def disabled(self, get_all=False): def disabled(self, get_all=False):
"""返回无效的元素,默认返回第一个 """返回无效的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_enabled', True, get_all=get_all) return self._any_state('is_enabled', True, get_all=get_all)
def clickable(self, get_all=False): def clickable(self, get_all=False):
"""返回可被点击的元素,默认返回第一个 """返回可被点击的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_clickable', get_all=get_all) return self._any_state('is_clickable', get_all=get_all)
def not_clickable(self, get_all=False): def not_clickable(self, get_all=False):
"""返回不可被点击的元素,默认返回第一个 """返回不可被点击的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('is_clickable', True, get_all=get_all) return self._any_state('is_clickable', True, get_all=get_all)
def have_rect(self, get_all=False): def have_rect(self, get_all=False):
"""返回有大小和位置的元素,默认返回第一个 """返回有大小和位置的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('has_rect', get_all=get_all) return self._any_state('has_rect', get_all=get_all)
def no_rect(self, get_all=False): def no_rect(self, get_all=False):
"""返回没有大小和位置的元素,默认返回第一个 """返回没有大小和位置的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
return self._any_state('has_rect', True, get_all=get_all) return self._any_state('has_rect', True, get_all=get_all)
def have_text(self, get_all=False): def have_text(self, get_all=False):
"""返回包含文本的元素,默认返回第一个 """返回包含文本的元素,默认返回第一个
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 元素或元素组成的列表 :return: 元素或元素组成的列表
""" """
r = ElementsList() if get_all:
r = ElementsList()
for i in self:
if i.raw_text:
r.append(i)
return r
for i in self: for i in self:
if i.raw_text: if i.raw_text:
r.append(i) return i
return r if get_all else r[0] if r else NoneElement()
return NoneElement()
def style(self, name, value, get_all=False): def style(self, name, value, get_all=False):
"""返回拥有某个style值的元素默认返回第一个 """返回拥有某个style值的元素默认返回第一个
:param name: 属性名称 :param name: 属性名称
:param value: 属性值 :param value: 属性值
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 筛选结果 :return: 筛选结果
""" """
r = ElementsList() return self._get_attr(name, value, 'style', get_all)
for i in self:
if i.style(name) == value:
r.append(i)
return r if get_all else r[0] if r else NoneElement()
def property(self, name, value, get_all=False): def property(self, name, value, get_all=False):
"""返回拥有某个property值的元素默认返回第一个 """返回拥有某个property值的元素默认返回第一个
:param name: 属性名称 :param name: 属性名称
:param value: 属性值 :param value: 属性值
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 筛选结果 :return: 筛选结果
""" """
r = ElementsList() return self._get_attr(name, value, 'property', get_all)
for i in self:
if i.property(name) == value:
r.append(i)
return r if get_all else r[0] if r else NoneElement()
def attr(self, name, value, get_all=False): def attr(self, name, value, get_all=False):
"""返回拥有某个attribute值的元素默认返回第一个 """返回拥有某个attribute值的元素默认返回第一个
:param name: 属性名称 :param name: 属性名称
:param value: 属性值 :param value: 属性值
:param get_all: 是否返回所有 :param get_all: 是否返回所有筛选到的元素
:return: 筛选结果 :return: 筛选结果
""" """
r = ElementsList() return self._get_attr(name, value, 'attr', get_all)
def filter(self, get_all=False, displayed=None, checked=None, selected=None, enabled=None, clickable=None,
have_rect=None, have_text=None):
"""与关系筛选元素
:param get_all: 是否返回所有筛选到的元素
:param displayed: 是否显示boolNone为忽略该项
:param checked: 是否被选中boolNone为忽略该项
:param selected: 是否被选择boolNone为忽略该项
:param enabled: 是否可用boolNone为忽略该项
:param clickable: 是否可点击boolNone为忽略该项
:param have_rect: 是否拥有大小和位置boolNone为忽略该项
:param have_text: 是否含有文本boolNone为忽略该项
:return:
"""
if get_all:
r = ElementsList()
for i in self:
if ((displayed is not None and (displayed is True and i.states.is_displayed) or (
displayed is False and not i.states.is_displayed))
and (checked is not None and (checked is True and i.states.is_checked) or (
checked is False and not i.states.is_checked))
and (selected is not None and (selected is True and i.states.is_selected) or (
selected is False and not i.states.is_selected))
and (enabled is not None and (enabled is True and i.states.is_enabled) or (
enabled is False and not i.states.is_enabled))
and (clickable is not None and (clickable is True and i.states.is_clickable) or (
clickable is False and not i.states.is_clickable))
and (have_rect is not None and (have_rect is True and i.states.has_rect) or (
have_rect is False and not i.states.has_rect))
and (have_text is not None and (have_text is True and i.raw_text) or (
have_text is False and not i.raw_text))):
r.append(i)
return r
for i in self: for i in self:
if i.attr(name) == value: if ((displayed is not None and (displayed is True and i.states.is_displayed) or (
r.append(i) displayed is False and not i.states.is_displayed))
return r if get_all else r[0] if r else NoneElement() and (checked is not None and (checked is True and i.states.is_checked) or (
checked is False and not i.states.is_checked))
and (selected is not None and (selected is True and i.states.is_selected) or (
selected is False and not i.states.is_selected))
and (enabled is not None and (enabled is True and i.states.is_enabled) or (
enabled is False and not i.states.is_enabled))
and (clickable is not None and (clickable is True and i.states.is_clickable) or (
clickable is False and not i.states.is_clickable))
and (have_rect is not None and (have_rect is True and i.states.has_rect) or (
have_rect is False and not i.states.has_rect))
and (have_text is not None and (have_text is True and i.raw_text) or (
have_text is False and not i.raw_text))):
return i
return NoneElement()
def _get_attr(self, name, value, method, get_all=False):
"""返回通过某个方法可获得某个值的元素,默认返回第一个
:param name: 属性名称
:param value: 属性值
:param method: 方法名称
:param get_all: 是否返回所有筛选到的元素
:return: 筛选结果
"""
if get_all:
r = ElementsList()
for i in self:
if getattr(i, method)(name) == value:
r.append(i)
return r
for i in self:
if getattr(i, method)(name) == value:
return i
return NoneElement()
def _any_state(self, name, is_not=False, get_all=False): def _any_state(self, name, is_not=False, get_all=False):
""" """
@ -376,13 +445,51 @@ class ElementsList(list):
:param is_not: 是否选择否定的 :param is_not: 是否选择否定的
:return: 选中的列表 :return: 选中的列表
""" """
r = ElementsList() if get_all:
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
if is_not: if is_not:
for i in self: for i in self:
if not getattr(i.states, name): if not getattr(i.states, name):
r.append(i) return i
else: else:
for i in self: for i in self:
if getattr(i.states, name): if getattr(i.states, name):
r.append(i) return i
return r if get_all else r[0] if r else NoneElement()
return NoneElement()
def get_eles(locators, owner, any_one=False, first_ele=True, timeout=10):
"""传入多个定位符获取多个ele
:param locators: 定位符组成的列表
:param owner: 页面或元素对象
:param any_one: 是否找到任何一个即返回
:param first_ele: 每个定位符是否只获取第一个元素
:param timeout: 超时时间
:return: 多个定位符组成的dict
"""
res = {loc: False for loc in locators}
end_time = perf_counter() + timeout
while perf_counter() <= end_time:
for loc in locators:
if res[loc] is not False:
continue
ele = owner.ele(loc, timeout=0) if first_ele else owner.eles(loc, timeout=0)
if ele:
res[loc] = ele
if any_one:
return res
if False not in res.values():
break
return res

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, List from typing import Union, Tuple, List, Optional
from .._base.base import BaseParser
from .._elements.chromium_element import ChromiumElement from .._elements.chromium_element import ChromiumElement
from .._pages.chromium_base import ChromiumBase from .._pages.chromium_base import ChromiumBase
@ -49,6 +50,13 @@ 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: ...
def get_eles(locators: Union[List[str], tuple],
owner: BaseParser,
any_one: bool = False,
first_ele: bool = True,
timeout: float = 10) -> dict: ...
class ElementsList(list): class ElementsList(list):
def displayed(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ... def displayed(self, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
@ -78,10 +86,29 @@ class ElementsList(list):
def style(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ... def style(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def property(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ... def property(self,
name: str,
value: str,
get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def attr(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ... def attr(self, name: str, value: str, get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def filter(self,
get_all: bool = False,
displayed: Optional[bool] = None,
checked: Optional[bool] = None,
selected: Optional[bool] = None,
enabled: Optional[bool] = None,
clickable: Optional[bool] = None,
have_rect: Optional[bool] = None,
have_text: Optional[bool] = None) -> Union[List[ChromiumElement], ChromiumElement]: ...
def _get_attr(self,
name: str,
value: str,
method: str,
get_all: bool = False) -> Union[List[ChromiumElement], ChromiumElement]: ...
def _any_state(self, name: str, is_not: bool = False, get_all: bool = False) -> List[ChromiumElement]: ... def _any_state(self, name: str, is_not: bool = False, get_all: bool = False) -> List[ChromiumElement]: ...
def __next__(self) -> ChromiumElement: ... def __next__(self) -> ChromiumElement: ...

View File

@ -119,9 +119,10 @@ class BaseWaiter(OriginWaiter):
locators = ((get_loc(locators)[1],) if (isinstance(locators, str) or isinstance(locators, tuple) locators = ((get_loc(locators)[1],) if (isinstance(locators, str) or isinstance(locators, tuple)
and locators[0] in by and len(locators) == 2) and locators[0] in by and len(locators) == 2)
else [get_loc(l)[1] for l in locators]) else [get_loc(l)[1] for l in locators])
method = any if any_one else all
timeout = self._driver.timeout if timeout is None else timeout timeout = self._driver.timeout if timeout is None else timeout
end_time = perf_counter() + timeout end_time = perf_counter() + timeout
method = any if any_one else all
while perf_counter() < end_time: while perf_counter() < end_time:
if method([_find(l, self._driver.driver) for l in locators]): if method([_find(l, self._driver.driver) for l in locators]):
return True return True

View File

@ -9,13 +9,13 @@ from ._elements.session_element import make_session_ele
from ._functions.by import By from ._functions.by import By
from ._functions.keys import Keys from ._functions.keys import Keys
from ._functions.settings import Settings from ._functions.settings import Settings
from ._functions.tools import wait_until, configs_to_here from ._functions.tools import wait_until, configs_to_here, get_eles
from ._functions.web import get_blob, tree from ._functions.web import get_blob, tree
from ._pages.chromium_page import ChromiumPage from ._pages.chromium_page import ChromiumPage
from ._units.actions import Actions from ._units.actions import Actions
__all__ = ['make_session_ele', 'Actions', 'Keys', 'By', 'Settings', 'wait_until', 'configs_to_here', 'get_blob', __all__ = ['make_session_ele', 'Actions', 'Keys', 'By', 'Settings', 'wait_until', 'configs_to_here', 'get_blob',
'tree', 'from_selenium', 'from_playwright'] 'tree', 'from_selenium', 'from_playwright', 'get_eles']
def from_selenium(driver): def from_selenium(driver):