diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index fb27d74..12a2080 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -91,14 +91,6 @@ class ChromiumElement(DrissionElement): def __eq__(self, other): return self._backend_id == getattr(other, '_backend_id', None) - def __getattr__(self, item): - """获取元素属性 - :param item: 属性名 - :return: 属性值 - """ - a = self.attr(item) - return a if a is not None else self.property(item) - @property def tag(self): """返回元素tag""" @@ -307,7 +299,7 @@ class ChromiumElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本组成的列表 """ - return super().children(locator, timeout, ele_only=ele_only) + return ChromiumElementsList(self.owner, super().children(locator, timeout, ele_only=ele_only)) def prevs(self, locator='', timeout=None, ele_only=True): """返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选 @@ -316,7 +308,7 @@ class ChromiumElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本组成的列表 """ - return super().prevs(locator, timeout, ele_only=ele_only) + return ChromiumElementsList(self.owner, super().prevs(locator, timeout, ele_only=ele_only)) def nexts(self, locator='', timeout=None, ele_only=True): """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选 @@ -325,7 +317,7 @@ class ChromiumElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 兄弟元素或节点文本组成的列表 """ - return super().nexts(locator, timeout, ele_only=ele_only) + return ChromiumElementsList(self.owner, super().nexts(locator, timeout, ele_only=ele_only)) def befores(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选 @@ -335,7 +327,7 @@ class ChromiumElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return super().befores(locator, timeout, ele_only=ele_only) + return ChromiumElementsList(self.owner, super().befores(locator, timeout, ele_only=ele_only)) def afters(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选 @@ -345,7 +337,7 @@ class ChromiumElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的元素或节点组成的列表 """ - return super().afters(locator, timeout, ele_only=ele_only) + return ChromiumElementsList(self.owner, super().afters(locator, timeout, ele_only=ele_only)) def on(self, timeout=None): """获取覆盖在本元素上最上层的元素 @@ -1199,7 +1191,7 @@ 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 = ChromiumElementsList(ele.owner) + r = ChromiumElementsList(page=ele.owner) for i in res: if i['value']['type'] == 'object': r.append(make_chromium_eles(ele.owner, _ids=i['value']['objectId'], is_obj_id=True)) @@ -1228,7 +1220,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 ChromiumElementsList(ele.owner) + return NoneElement(ele.owner) if index is not None else ChromiumElementsList(page=ele.owner) def find_by_css(ele, selector, index, timeout): @@ -1274,7 +1266,7 @@ def find_by_css(ele, selector, index, timeout): if result: return result - return NoneElement(ele.owner) if index is not None else ChromiumElementsList(ele.owner) + return NoneElement(ele.owner) if index is not None else ChromiumElementsList(page=ele.owner) def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=False): @@ -1306,7 +1298,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 = ChromiumElementsList() + nodes = ChromiumElementsList(page=page) 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 65a5756..d483018 100644 --- a/DrissionPage/_elements/chromium_element.pyi +++ b/DrissionPage/_elements/chromium_element.pyi @@ -57,8 +57,6 @@ class ChromiumElement(DrissionElement): def __eq__(self, other: ChromiumElement) -> bool: ... - def __getattr__(self, item: str) -> str: ... - @property def tag(self) -> str: ... @@ -139,27 +137,27 @@ class ChromiumElement(DrissionElement): def children(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... + ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]: ... def prevs(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... + ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]: ... def nexts(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... + ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]: ... def befores(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... + ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]: ... def afters(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ... + ele_only: bool = True) -> Union[ChromiumElementsList, List[Union[ChromiumElement, str]]]: ... def on(self, timeout: float = None) -> ChromiumElement: ... @@ -343,8 +341,7 @@ class ShadowRoot(BaseElement): timeout: float = None, index: Optional[int] = 1, relative: bool = False, - raise_err: bool = None) -> Union[ChromiumElement, ChromiumFrame, str, - List[Union[ChromiumElement, ChromiumFrame, str]]]: ... + raise_err: bool = None) -> Union[ChromiumElement, ChromiumFrame, str, ChromiumElementsList]: ... def _get_node_id(self, obj_id: str) -> int: ... diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index 36c4178..888269a 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -51,13 +51,6 @@ class SessionElement(DrissionElement): def __eq__(self, other): return self.xpath == getattr(other, 'xpath', None) - def __getattr__(self, item): - """获取元素属性 - :param item: 属性名 - :return: 属性值 - """ - return self.attr(item) - @property def tag(self): """返回元素类型""" @@ -157,7 +150,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 直接子元素或节点文本组成的列表 """ - return super().children(locator, timeout, ele_only=ele_only) + return SessionElementsList(self.owner, super().children(locator, timeout, ele_only=ele_only)) def prevs(self, locator='', timeout=None, ele_only=True): """返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选 @@ -166,7 +159,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点文本组成的列表 """ - return super().prevs(locator, timeout, ele_only=ele_only) + return SessionElementsList(self.owner, super().prevs(locator, timeout, ele_only=ele_only)) def nexts(self, locator='', timeout=None, ele_only=True): """返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选 @@ -175,7 +168,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 同级元素或节点文本组成的列表 """ - return super().nexts(locator, timeout, ele_only=ele_only) + return SessionElementsList(self.owner, super().nexts(locator, timeout, ele_only=ele_only)) def befores(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选 @@ -185,7 +178,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素前面的元素或节点组成的列表 """ - return super().befores(locator, timeout, ele_only=ele_only) + return SessionElementsList(self.owner, super().befores(locator, timeout, ele_only=ele_only)) def afters(self, locator='', timeout=None, ele_only=True): """返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选 @@ -195,7 +188,7 @@ class SessionElement(DrissionElement): :param ele_only: 是否只获取元素,为False时把文本、注释节点也纳入 :return: 本元素后面的元素或节点组成的列表 """ - return super().afters(locator, timeout, ele_only=ele_only) + return SessionElementsList(self.owner, super().afters(locator, timeout, ele_only=ele_only)) def attr(self, name): """返回attribute属性值 @@ -402,7 +395,7 @@ def make_session_ele(html_or_ele, loc=None, index=1, method=None): # 把lxml元素对象包装成SessionElement对象并按需要返回一个或全部 if index is None: - r = SessionElementsList(page) + r = SessionElementsList(page=page) for e in eles: if e != '\n': r.append(SessionElement(e, page) if isinstance(e, HtmlElement) else e) diff --git a/DrissionPage/_elements/session_element.pyi b/DrissionPage/_elements/session_element.pyi index 9422d20..18eef9d 100644 --- a/DrissionPage/_elements/session_element.pyi +++ b/DrissionPage/_elements/session_element.pyi @@ -36,8 +36,6 @@ class SessionElement(DrissionElement): def __eq__(self, other: SessionElement) -> bool: ... - def __getattr__(self, item: str) -> str: ... - @property def tag(self) -> str: ... @@ -93,27 +91,27 @@ class SessionElement(DrissionElement): def children(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[SessionElement, str]]: ... + ele_only: bool = True) -> Union[SessionElementsList, List[Union[SessionElement, str]]]: ... def prevs(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[SessionElement, str]]: ... + ele_only: bool = True) -> Union[SessionElementsList, List[Union[SessionElement, str]]]: ... def nexts(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[SessionElement, str]]: ... + ele_only: bool = True) -> Union[SessionElementsList, List[Union[SessionElement, str]]]: ... def befores(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[SessionElement, str]]: ... + ele_only: bool = True) -> Union[SessionElementsList, List[Union[SessionElement, str]]]: ... def afters(self, locator: Union[Tuple[str, str], str] = '', timeout: float = None, - ele_only: bool = True) -> List[Union[SessionElement, str]]: ... + ele_only: bool = True) -> Union[SessionElementsList, List[Union[SessionElement, str]]]: ... def attr(self, name: str) -> Optional[str]: ... diff --git a/DrissionPage/_functions/elements.py b/DrissionPage/_functions/elements.py index a79f894..69269f2 100644 --- a/DrissionPage/_functions/elements.py +++ b/DrissionPage/_functions/elements.py @@ -11,11 +11,9 @@ from .._elements.none_element import NoneElement class SessionElementsList(list): - def __init__(self, page=None): - super().__init__() + def __init__(self, page=None, *args): + super().__init__(*args) self._page = page - self._filter = None - self._filter_one = None self._getter = None @property @@ -26,30 +24,22 @@ class SessionElementsList(list): @property def filter(self): - if self._filter is None: - self._filter = SessionFilter(self) - return self._filter + return SessionFilter(self) @property def filter_one(self): - if self._filter_one is None: - self._filter_one = SessionFilterOne(self) - return self._filter_one + return SessionFilterOne(self) class ChromiumElementsList(SessionElementsList): @property def filter(self): - if self._filter is None: - self._filter = ChromiumFilter(self) - return self._filter + return ChromiumFilter(self) @property def filter_one(self): - if self._filter_one is None: - self._filter_one = ChromiumFilterOne(self) - return self._filter_one + return ChromiumFilterOne(self) def search(self, displayed=None, checked=None, selected=None, enabled=None, clickable=None, have_rect=None, have_text=None): @@ -63,28 +53,13 @@ class ChromiumElementsList(SessionElementsList): :param have_text: 是否含有文本,bool,None为忽略该项 :return: 筛选结果 """ - r = ChromiumElementsList(self._page) - 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)) - or (checked is not None and (checked is True and i.states.is_checked) or ( - checked is False and not i.states.is_checked)) - or (selected is not None and (selected is True and i.states.is_selected) or ( - selected is False and not i.states.is_selected)) - or (enabled is not None and (enabled is True and i.states.is_enabled) or ( - enabled is False and not i.states.is_enabled)) - or (clickable is not None and (clickable is True and i.states.is_clickable) or ( - clickable is False and not i.states.is_clickable)) - or (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)) - or (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 ChromiumFilter(r) + return _search(self, displayed=displayed, checked=checked, selected=selected, enabled=enabled, + clickable=clickable, have_rect=have_rect, have_text=have_text) - def search_one(self, displayed=None, checked=None, selected=None, enabled=None, clickable=None, + def search_one(self, index=1, displayed=None, checked=None, selected=None, enabled=None, clickable=None, have_rect=None, have_text=None): - """或关系筛选元素 + """或关系筛选元素,获取一个结果 + :param index: 元素序号,从1开始 :param displayed: 是否显示,bool,None为忽略该项 :param checked: 是否被选中,bool,None为忽略该项 :param selected: 是否被选择,bool,None为忽略该项 @@ -94,27 +69,8 @@ class ChromiumElementsList(SessionElementsList): :param have_text: 是否含有文本,bool,None为忽略该项 :return: 筛选结果 """ - 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)) - or (checked is not None and (checked is True and i.states.is_checked) or ( - checked is False and not i.states.is_checked)) - or (selected is not None and (selected is True and i.states.is_selected) or ( - selected is False and not i.states.is_selected)) - or (enabled is not None and (enabled is True and i.states.is_enabled) or ( - enabled is False and not i.states.is_enabled)) - or (clickable is not None and (clickable is True and i.states.is_clickable) or ( - clickable is False and not i.states.is_clickable)) - or (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)) - or (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(self._page, method='filter()', args={'displayed': displayed, - 'checked': checked, 'selected': selected, - 'enabled': enabled, 'clickable': clickable, - 'have_rect': have_rect, 'have_text': have_text}) + return _search_one(self, index=index, displayed=displayed, checked=checked, selected=selected, + enabled=enabled, clickable=clickable, have_rect=have_rect, have_text=have_text) class SessionFilterOne(object): @@ -123,6 +79,11 @@ class SessionFilterOne(object): self._index = 1 def __call__(self, index=1): + """返回结果中第几个元素 + :param index: 元素序号,从1开始 + :return: 对象自身 + """ + print('s') self._index = index return self @@ -142,23 +103,23 @@ class SessionFilterOne(object): :param contain: 是否包含该字符串,False表示不包含 :return: 筛选结果 """ + num = 0 if contain: - num = 0 for i in self._list: - t = i.raw_text + t = i if isinstance(i, str) else i.raw_text if (fuzzy and text in t) or (not fuzzy and text == t): num += 1 if self._index == num: return i else: - num = 0 for i in self._list: - t = i.raw_text + t = i if isinstance(i, str) else i.raw_text if (fuzzy and text not in t) or (not fuzzy and text != t): num += 1 if self._index == num: return i - return NoneElement(self._list._page, 'text()', args={'text': text, 'fuzzy': fuzzy, 'contain': contain}) + return NoneElement(self._list._page, 'text()', + args={'text': text, 'fuzzy': fuzzy, 'contain': contain, 'index': self._index}) def _get_attr(self, name, value, method, equal=True): """返回通过某个方法可获得某个值的元素 @@ -167,21 +128,21 @@ class SessionFilterOne(object): :param method: 方法名称 :return: 筛选结果 """ + num = 0 if equal: - num = 0 for i in self._list: - if getattr(i, method)(name) == value: + if not isinstance(i, str) and getattr(i, method)(name) == value: num += 1 if self._index == num: return i else: - num = 0 for i in self._list: - if getattr(i, method)(name) != value: + if not isinstance(i, str) and getattr(i, method)(name) != value: num += 1 if self._index == num: return i - return NoneElement(self._list._page, f'{method}()', args={'name': name, 'value': value, 'equal': equal}) + return NoneElement(self._list._page, f'{method}()', + args={'name': name, 'value': value, 'equal': equal, 'index': self._index}) class SessionFilter(SessionFilterOne): @@ -210,19 +171,8 @@ class SessionFilter(SessionFilterOne): :param contain: 是否包含该字符串,False表示不包含 :return: 筛选结果 """ - r = SessionElementsList(self._list._page) - if contain: - for i in self._list: - t = i.raw_text - if (fuzzy and text in t) or (not fuzzy and text == t): - r.append(i) - else: - for i in self._list: - t = i.raw_text - if (fuzzy and text not in t) or (not fuzzy and text != t): - r.append(i) - self._list = r - return self + self._list = _text_all(self._list, SessionElementsList(page=self._list._page), + text=text, fuzzy=fuzzy, contain=contain) def _get_attr(self, name, value, method, equal=True): """返回通过某个方法可获得某个值的元素 @@ -231,16 +181,8 @@ class SessionFilter(SessionFilterOne): :param method: 方法名称 :return: 筛选结果 """ - r = SessionElementsList(self._list._page) - if equal: - for i in self._list: - if getattr(i, method)(name) == value: - r.append(i) - else: - for i in self._list: - if getattr(i, method)(name) != value: - r.append(i) - self._list = r + self._list = _get_attr_all(self._list, SessionElementsList(page=self._list._page), + name=name, value=value, method=method, equal=equal) return self @@ -312,21 +254,20 @@ class ChromiumFilterOne(SessionFilterOne): :param equal: 是否是指定状态,False表示否定状态 :return: 选中的元素 """ + num = 0 if equal: - num = 0 for i in self._list: - if getattr(i.states, name): + if not isinstance(i, str) and getattr(i.states, name): num += 1 if self._index == num: return i else: - num = 0 for i in self._list: - if not getattr(i.states, name): + if not isinstance(i, str) and not getattr(i.states, name): num += 1 if self._index == num: return i - return NoneElement(self._list._page, f'{name}()', args={'equal': equal}) + return NoneElement(self._list._page, f'{name}()', args={'equal': equal, 'index': self._index}) class ChromiumFilter(ChromiumFilterOne): @@ -344,9 +285,14 @@ class ChromiumFilter(ChromiumFilterOne): return self._list[item] @property - def search_one(self, displayed=None, checked=None, selected=None, enabled=None, clickable=None, + def get(self): + """返回用于获取元素属性的对象""" + return self._list.get + + def search_one(self, index=1, displayed=None, checked=None, selected=None, enabled=None, clickable=None, have_rect=None, have_text=None): - """或关系筛选元素 + """或关系筛选元素,获取一个结果 + :param index: 元素序号,从1开始 :param displayed: 是否显示,bool,None为忽略该项 :param checked: 是否被选中,bool,None为忽略该项 :param selected: 是否被选择,bool,None为忽略该项 @@ -356,10 +302,9 @@ class ChromiumFilter(ChromiumFilterOne): :param have_text: 是否含有文本,bool,None为忽略该项 :return: 筛选结果 """ - return self._list.search_one(displayed=displayed, checked=checked, selected=selected, enabled=enabled, - clickable=clickable, have_rect=have_rect, have_text=have_text) + return _search_one(self._list, index=index, displayed=displayed, checked=checked, selected=selected, + enabled=enabled, clickable=clickable, have_rect=have_rect, have_text=have_text) - @property def search(self, displayed=None, checked=None, selected=None, enabled=None, clickable=None, have_rect=None, have_text=None): """或关系筛选元素 @@ -372,8 +317,8 @@ class ChromiumFilter(ChromiumFilterOne): :param have_text: 是否含有文本,bool,None为忽略该项 :return: 筛选结果 """ - return self._list.search(displayed=displayed, checked=checked, selected=selected, enabled=enabled, - clickable=clickable, have_rect=have_rect, have_text=have_text) + return _search(self._list, displayed=displayed, checked=checked, selected=selected, enabled=enabled, + clickable=clickable, have_rect=have_rect, have_text=have_text) def text(self, text, fuzzy=True, contain=True): """以是否含有指定文本为条件筛选元素 @@ -382,18 +327,8 @@ class ChromiumFilter(ChromiumFilterOne): :param contain: 是否包含该字符串,False表示不包含 :return: 筛选结果 """ - r = ChromiumElementsList(self._list._page) - if contain: - for i in self._list: - t = i.raw_text - if (fuzzy and text in t) or (not fuzzy and text == t): - r.append(i) - else: - for i in self._list: - t = i.raw_text - if (fuzzy and text not in t) or (not fuzzy and text != t): - r.append(i) - self._list = r + self._list = _text_all(self._list, ChromiumElementsList(page=self._list._page), + text=text, fuzzy=fuzzy, contain=contain) return self def _get_attr(self, name, value, method, equal=True): @@ -403,16 +338,8 @@ class ChromiumFilter(ChromiumFilterOne): :param method: 方法名称 :return: 筛选结果 """ - r = ChromiumElementsList(self._list._page) - if equal: - for i in self._list: - if getattr(i, method)(name) == value: - r.append(i) - else: - for i in self._list: - if getattr(i, method)(name) != value: - r.append(i) - self._list = r + self._list = _get_attr_all(self._list, ChromiumElementsList(page=self._list._page), + name=name, value=value, method=method, equal=equal) return self def _any_state(self, name, equal=True): @@ -421,14 +348,14 @@ class ChromiumFilter(ChromiumFilterOne): :param equal: 是否是指定状态,False表示否定状态 :return: 选中的列表 """ - r = ChromiumElementsList(self._list._page) + r = ChromiumElementsList(page=self._list._page) if equal: for i in self._list: - if getattr(i.states, name): + if not isinstance(i, str) and getattr(i.states, name): r.append(i) else: for i in self._list: - if not getattr(i.states, name): + if not isinstance(i, str) and not getattr(i.states, name): r.append(i) self._list = r return self @@ -440,18 +367,18 @@ class Getter(object): def links(self): """返回所有元素的link属性组成的列表""" - return [e.link for e in self._list] + return [e.link for e in self._list if not isinstance(e, str)] def texts(self): """返回所有元素的text属性组成的列表""" - return [e.text for e in self._list] + return [e if isinstance(e, str) else e.text for e in self._list] def attrs(self, name): """返回所有元素指定的attr属性组成的列表 :param name: 属性名称 :return: 属性文本组成的列表 """ - return [e.attr(name) for e in self._list] + return [e.attr(name) for e in self._list if not isinstance(e, str)] def get_eles(locators, owner, any_one=False, first_ele=True, timeout=10): @@ -476,5 +403,109 @@ def get_eles(locators, owner, any_one=False, first_ele=True, timeout=10): return res if False not in res.values(): break - return res + + +def _get_attr_all(src_list, aim_list, name, value, method, equal=True): + if equal: + for i in src_list: + if not isinstance(i, str) and getattr(i, method)(name) == value: + aim_list.append(i) + else: + for i in src_list: + if not isinstance(i, str) and getattr(i, method)(name) != value: + aim_list.append(i) + return aim_list + + +def _text_all(src_list, aim_list, text, fuzzy=True, contain=True): + """以是否含有指定文本为条件筛选元素 + :param text: 用于匹配的文本 + :param fuzzy: 是否模糊匹配 + :param contain: 是否包含该字符串,False表示不包含 + :return: 筛选结果 + """ + if contain: + for i in src_list: + t = i if isinstance(i, str) else i.raw_text + if (fuzzy and text in t) or (not fuzzy and text == t): + aim_list.append(i) + else: + for i in src_list: + t = i if isinstance(i, str) else i.raw_text + if (fuzzy and text not in t) or (not fuzzy and text != t): + aim_list.append(i) + return aim_list + + +def _search(_list, displayed=None, checked=None, selected=None, enabled=None, clickable=None, + have_rect=None, have_text=None): + """或关系筛选元素 + :param displayed: 是否显示,bool,None为忽略该项 + :param checked: 是否被选中,bool,None为忽略该项 + :param selected: 是否被选择,bool,None为忽略该项 + :param enabled: 是否可用,bool,None为忽略该项 + :param clickable: 是否可点击,bool,None为忽略该项 + :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 + :param have_text: 是否含有文本,bool,None为忽略该项 + :return: 筛选结果 + """ + r = ChromiumElementsList(page=_list._page) + for i in _list: + if not isinstance(i, str) and ( + (displayed is not None and (displayed is True and i.states.is_displayed) + or (displayed is False and not i.states.is_displayed)) + or (checked is not None and (checked is True and i.states.is_checked) + or (checked is False and not i.states.is_checked)) + or (selected is not None and (selected is True and i.states.is_selected) + or (selected is False and not i.states.is_selected)) + or (enabled is not None and (enabled is True and i.states.is_enabled) + or (enabled is False and not i.states.is_enabled)) + or (clickable is not None and (clickable is True and i.states.is_clickable) + or (clickable is False and not i.states.is_clickable)) + or (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)) + or (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 ChromiumFilter(r) + + +def _search_one(_list, index=1, displayed=None, checked=None, selected=None, enabled=None, clickable=None, + have_rect=None, have_text=None): + """或关系筛选元素,获取一个结果 + :param index: 元素序号,从1开始 + :param displayed: 是否显示,bool,None为忽略该项 + :param checked: 是否被选中,bool,None为忽略该项 + :param selected: 是否被选择,bool,None为忽略该项 + :param enabled: 是否可用,bool,None为忽略该项 + :param clickable: 是否可点击,bool,None为忽略该项 + :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 + :param have_text: 是否含有文本,bool,None为忽略该项 + :return: 筛选结果 + """ + num = 0 + for i in _list: + if not isinstance(i, str) and ( + (displayed is not None and (displayed is True and i.states.is_displayed) + or (displayed is False and not i.states.is_displayed)) + or (checked is not None and (checked is True and i.states.is_checked) + or (checked is False and not i.states.is_checked)) + or (selected is not None and (selected is True and i.states.is_selected) + or (selected is False and not i.states.is_selected)) + or (enabled is not None and (enabled is True and i.states.is_enabled) + or (enabled is False and not i.states.is_enabled)) + or (clickable is not None and (clickable is True and i.states.is_clickable) + or (clickable is False and not i.states.is_clickable)) + or (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)) + or (have_text is not None and (have_text is True and i.raw_text) + or (have_text is False and not i.raw_text))): + num += 1 + if num == index: + return i + + return NoneElement(_list._page, method='filter()', args={'displayed': displayed, + 'checked': checked, 'selected': selected, + 'enabled': enabled, 'clickable': clickable, + 'have_rect': have_rect, 'have_text': have_text}) diff --git a/DrissionPage/_functions/elements.pyi b/DrissionPage/_functions/elements.pyi index 3587bae..3484711 100644 --- a/DrissionPage/_functions/elements.pyi +++ b/DrissionPage/_functions/elements.pyi @@ -21,11 +21,9 @@ def get_eles(locators: Union[List[str], tuple], class SessionElementsList(list): _page = ... - _filter: Optional[SessionFilter] = ... - _filter_one: Optional[SessionFilterOne] = ... _getter: Optional[Getter] = ... - def __init__(self, page=None): ... + def __init__(self, page=None, *args): ... @property def get(self) -> Getter: ... @@ -40,8 +38,6 @@ class SessionElementsList(list): class ChromiumElementsList(SessionElementsList): - _filter: Optional[ChromiumFilter] = ... - _filter_one: Optional[ChromiumFilterOne] = ... @property def filter(self) -> ChromiumFilter: ... @@ -59,6 +55,7 @@ class ChromiumElementsList(SessionElementsList): have_text: Optional[bool] = None) -> ChromiumFilter: ... def search_one(self, + index: int = 1, displayed: Optional[bool] = None, checked: Optional[bool] = None, selected: Optional[bool] = None, @@ -195,6 +192,7 @@ class ChromiumFilter(ChromiumFilterOne): have_text: Optional[bool] = None) -> ChromiumFilter: ... def search_one(self, + index: int = 1, displayed: Optional[bool] = None, checked: Optional[bool] = None, selected: Optional[bool] = None, diff --git a/DrissionPage/_pages/session_page.pyi b/DrissionPage/_pages/session_page.pyi index 45c56d8..16f95be 100644 --- a/DrissionPage/_pages/session_page.pyi +++ b/DrissionPage/_pages/session_page.pyi @@ -111,8 +111,7 @@ class SessionPage(BasePage): timeout: float = None, index: Optional[int] = 1, relative: bool = True, - raise_err: bool = None) \ - -> Union[SessionElement, SessionElementsList]: ... + raise_err: bool = None) -> Union[SessionElement, SessionElementsList]: ... def cookies(self, as_dict: bool = False,