From e10030e23f8854e2aa0b02c97fffa24a03922287 Mon Sep 17 00:00:00 2001 From: g1879 Date: Sun, 25 Aug 2024 23:25:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=97=E8=A1=A8=E4=B8=AD=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E5=A2=9E=E5=8A=A0tag=EF=BC=9Bget=5Fframes()?= =?UTF-8?q?=E8=BF=94=E5=9B=9EChromiumElementsList?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_elements/chromium_element.py | 2 +- DrissionPage/_functions/elements.py | 94 +++++++++----- DrissionPage/_functions/elements.pyi | 140 ++++++++++++++------- DrissionPage/_pages/chromium_base.py | 4 +- DrissionPage/_pages/chromium_base.pyi | 6 +- 5 files changed, 165 insertions(+), 81 deletions(-) diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index 6706eb6..bc58510 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -910,7 +910,7 @@ class ShadowRoot(BaseElement): if result: return result - return NoneElement(self.owner) if index is not None else ChromiumElementsList() + return NoneElement(self.owner) if index is not None else ChromiumElementsList(self.owner) def _get_node_id(self, obj_id): return self.owner._run_cdp('DOM.requestNode', objectId=obj_id)['nodeId'] diff --git a/DrissionPage/_functions/elements.py b/DrissionPage/_functions/elements.py index ebafcb3..c28f66c 100644 --- a/DrissionPage/_functions/elements.py +++ b/DrissionPage/_functions/elements.py @@ -40,24 +40,14 @@ class ChromiumElementsList(SessionElementsList): return ChromiumFilterOne(self) def search(self, 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: 筛选结果 - """ + have_rect=None, have_text=None, tag=None): return _search(self, displayed=displayed, checked=checked, selected=selected, enabled=enabled, - clickable=clickable, have_rect=have_rect, have_text=have_text) + clickable=clickable, have_rect=have_rect, have_text=have_text, tag=tag) def search_one(self, index=1, displayed=None, checked=None, selected=None, enabled=None, clickable=None, - have_rect=None, have_text=None): + have_rect=None, have_text=None, tag=None): return _search_one(self, index=index, displayed=displayed, checked=checked, selected=selected, - enabled=enabled, clickable=clickable, have_rect=have_rect, have_text=have_text) + enabled=enabled, clickable=clickable, have_rect=have_rect, have_text=have_text, tag=tag) class SessionFilterOne(object): @@ -69,6 +59,23 @@ class SessionFilterOne(object): self._index = index return self + def tag(self, name, equal=True): + num = 0 + name = name.lower() + if equal: + for i in self._list: + if not isinstance(i, str) and i.tag == name: + num += 1 + if self._index == num: + return i + else: + for i in self._list: + if not isinstance(i, str) and i.tag != name: + num += 1 + if self._index == num: + return i + return NoneElement(self._list._owner, 'tag()', args={'name': name, 'equal': equal, 'index': self._index}) + def attr(self, name, value, equal=True): return self._get_attr(name, value, 'attr', equal=equal) @@ -127,14 +134,18 @@ class SessionFilter(SessionFilterOne): def get(self): return self._list.get + def tag(self, name, equal=True): + self._list = _tag_all(self._list, SessionElementsList(owner=self._list._owner), name=name, equal=equal) + return self + def text(self, text, fuzzy=True, contain=True): self._list = _text_all(self._list, SessionElementsList(owner=self._list._owner), text=text, fuzzy=fuzzy, contain=contain) return self def _get_attr(self, name, value, method, equal=True): - self._list = _get_attr_all(self._list, SessionElementsList(owner=self._list._owner), - name=name, value=value, method=method, equal=equal) + self._list = _attr_all(self._list, SessionElementsList(owner=self._list._owner), + name=name, value=value, method=method, equal=equal) return self @@ -200,14 +211,18 @@ class ChromiumFilter(ChromiumFilterOne): 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): + have_rect=None, have_text=None, tag=None): 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) + enabled=enabled, clickable=clickable, have_rect=have_rect, have_text=have_text, tag=tag) def search(self, displayed=None, checked=None, selected=None, enabled=None, clickable=None, - have_rect=None, have_text=None): + have_rect=None, have_text=None, tag=None): return _search(self._list, displayed=displayed, checked=checked, selected=selected, enabled=enabled, - clickable=clickable, have_rect=have_rect, have_text=have_text) + clickable=clickable, have_rect=have_rect, have_text=have_text, tag=tag) + + def tag(self, name, equal=True): + self._list = _tag_all(self._list, ChromiumElementsList(owner=self._list._owner), name=name, equal=equal) + return self def text(self, text, fuzzy=True, contain=True): self._list = _text_all(self._list, ChromiumElementsList(owner=self._list._owner), @@ -215,8 +230,8 @@ class ChromiumFilter(ChromiumFilterOne): return self def _get_attr(self, name, value, method, equal=True): - self._list = _get_attr_all(self._list, ChromiumElementsList(owner=self._list._owner), - name=name, value=value, method=method, equal=equal) + self._list = _attr_all(self._list, ChromiumElementsList(owner=self._list._owner), + name=name, value=value, method=method, equal=equal) return self def _any_state(self, name, equal=True): @@ -302,7 +317,7 @@ def get_frame(owner, loc_ind_ele, timeout=None): return r -def _get_attr_all(src_list, aim_list, name, value, method, equal=True): +def _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: @@ -314,6 +329,19 @@ def _get_attr_all(src_list, aim_list, name, value, method, equal=True): return aim_list +def _tag_all(src_list, aim_list, name, equal=True): + name = name.lower() + if equal: + for i in src_list: + if not isinstance(i, str) and i.tag == name: + aim_list.append(i) + else: + for i in src_list: + if not isinstance(i, str) and i.tag != name: + aim_list.append(i) + return aim_list + + def _text_all(src_list, aim_list, text, fuzzy=True, contain=True): """以是否含有指定文本为条件筛选元素 :param text: 用于匹配的文本 @@ -335,7 +363,7 @@ def _text_all(src_list, aim_list, text, fuzzy=True, contain=True): def _search(_list, displayed=None, checked=None, selected=None, enabled=None, clickable=None, - have_rect=None, have_text=None): + have_rect=None, have_text=None, tag=None): """或关系筛选元素 :param displayed: 是否显示,bool,None为忽略该项 :param checked: 是否被选中,bool,None为忽略该项 @@ -344,6 +372,7 @@ def _search(_list, displayed=None, checked=None, selected=None, enabled=None, cl :param clickable: 是否可点击,bool,None为忽略该项 :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 :param have_text: 是否含有文本,bool,None为忽略该项 + :param tag: 元素类型 :return: 筛选结果 """ r = ChromiumElementsList(owner=_list._owner) @@ -362,13 +391,14 @@ def _search(_list, displayed=None, checked=None, selected=None, enabled=None, cl 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))): + or (have_text is False and not i.raw_text)) + or (tag is not None and i.tag == tag.lower())): 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): + have_rect=None, have_text=None, tag=None): """或关系筛选元素,获取一个结果 :param index: 元素序号,从1开始 :param displayed: 是否显示,bool,None为忽略该项 @@ -378,6 +408,7 @@ def _search_one(_list, index=1, displayed=None, checked=None, selected=None, ena :param clickable: 是否可点击,bool,None为忽略该项 :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 :param have_text: 是否含有文本,bool,None为忽略该项 + :param tag: 元素类型 :return: 筛选结果 """ num = 0 @@ -396,12 +427,13 @@ def _search_one(_list, index=1, displayed=None, checked=None, selected=None, ena 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))): + or (have_text is False and not i.raw_text)) + or (tag is not None and i.tag == tag.lower())): num += 1 if num == index: return i - return NoneElement(_list._owner, method='filter()', args={'displayed': displayed, - 'checked': checked, 'selected': selected, - 'enabled': enabled, 'clickable': clickable, - 'have_rect': have_rect, 'have_text': have_text}) + return NoneElement(_list._owner, method='filter()', args={'displayed': displayed, 'checked': checked, + 'selected': selected, 'enabled': enabled, + 'clickable': clickable, 'have_rect': have_rect, + 'have_text': have_text, 'tag': tag}) diff --git a/DrissionPage/_functions/elements.pyi b/DrissionPage/_functions/elements.pyi index ae8a73f..aaeeea4 100644 --- a/DrissionPage/_functions/elements.pyi +++ b/DrissionPage/_functions/elements.pyi @@ -20,7 +20,12 @@ class SessionElementsList(list): def __init__(self, owner: SessionPage = None, - *args): ... + *args): + """ + :param owner: 产生元素列表的页面 + :param args: + """ + ... @property def get(self) -> Getter: @@ -45,7 +50,12 @@ class ChromiumElementsList(SessionElementsList): def __init__(self, owner: ChromiumBase = None, - *args): ... + *args): + """ + :param owner: 产生元素列表的页面 + :param args: + """ + ... @property def filter(self) -> ChromiumFilter: @@ -64,7 +74,8 @@ class ChromiumElementsList(SessionElementsList): enabled: Optional[bool] = None, clickable: Optional[bool] = None, have_rect: Optional[bool] = None, - have_text: Optional[bool] = None) -> ChromiumFilter: + have_text: Optional[bool] = None, + tag: str = None) -> ChromiumFilter: """或关系筛选元素 :param displayed: 是否显示,bool,None为忽略该项 :param checked: 是否被选中,bool,None为忽略该项 @@ -73,6 +84,7 @@ class ChromiumElementsList(SessionElementsList): :param clickable: 是否可点击,bool,None为忽略该项 :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 :param have_text: 是否含有文本,bool,None为忽略该项 + :param tag: 指定的元素类型 :return: 筛选结果 """ ... @@ -85,7 +97,8 @@ class ChromiumElementsList(SessionElementsList): enabled: Optional[bool] = None, clickable: Optional[bool] = None, have_rect: Optional[bool] = None, - have_text: Optional[bool] = None) -> ChromiumElement: + have_text: Optional[bool] = None, + tag: str = None) -> ChromiumElement: """或关系筛选元素,获取一个结果 :param index: 元素序号,从1开始 :param displayed: 是否显示,bool,None为忽略该项 @@ -95,6 +108,7 @@ class ChromiumElementsList(SessionElementsList): :param clickable: 是否可点击,bool,None为忽略该项 :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 :param have_text: 是否含有文本,bool,None为忽略该项 + :param tag: 指定的元素类型 :return: 筛选结果 """ ... @@ -119,6 +133,14 @@ class SessionFilterOne(object): """ ... + def tag(self, name: str, equal: bool = True) -> SessionElement: + """筛选某种元素 + :param name: 标签页名称 + :param equal: True表示匹配这种元素,False表示匹配非这种元素 + :return: 筛选结果 + """ + ... + def attr(self, name: str, value: str, equal: bool = True) -> SessionElement: """以是否拥有某个attribute值为条件筛选元素 :param name: 属性名称 @@ -166,6 +188,14 @@ class SessionFilter(SessionFilterOne): """返回用于获取元素属性的对象""" ... + def tag(self, name: str, equal: bool = True) -> SessionFilter: + """筛选某种元素 + :param name: 标签页名称 + :param equal: True表示匹配这种元素,False表示匹配非这种元素 + :return: 筛选结果 + """ + ... + def attr(self, name: str, value: str, equal: bool = True) -> SessionFilter: """以是否拥有某个attribute值为条件筛选元素 :param name: 属性名称 @@ -214,6 +244,35 @@ class ChromiumFilterOne(SessionFilterOne): """ ... + def tag(self, name: str, equal: bool = True) -> SessionElement: + """筛选某种元素 + :param name: 标签页名称 + :param equal: True表示匹配这种元素,False表示匹配非这种元素 + :return: 筛选结果 + """ + ... + + def attr(self, name: str, value: str, equal: bool = True) -> ChromiumElement: + """以是否拥有某个attribute值为条件筛选元素 + :param name: 属性名称 + :param value: 属性值 + :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 + :return: 筛选结果 + """ + ... + + def text(self, + text: str, + fuzzy: bool = True, + contain: bool = True) -> ChromiumElement: + """以是否含有指定文本为条件筛选元素 + :param text: 用于匹配的文本 + :param fuzzy: 是否模糊匹配 + :param contain: 是否包含该字符串,False表示不包含 + :return: 筛选结果 + """ + ... + def displayed(self, equal: bool = True) -> ChromiumElement: """以是否显示为条件筛选元素 :param equal: 是否匹配显示的元素,False匹配不显示的 @@ -276,27 +335,6 @@ class ChromiumFilterOne(SessionFilterOne): """ ... - def attr(self, name: str, value: str, equal: bool = True) -> ChromiumElement: - """以是否拥有某个attribute值为条件筛选元素 - :param name: 属性名称 - :param value: 属性值 - :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 - :return: 筛选结果 - """ - ... - - def text(self, - text: str, - fuzzy: bool = True, - contain: bool = True) -> ChromiumElement: - """以是否含有指定文本为条件筛选元素 - :param text: 用于匹配的文本 - :param fuzzy: 是否模糊匹配 - :param contain: 是否包含该字符串,False表示不包含 - :return: 筛选结果 - """ - ... - def _get_attr(self, name: str, value: str, @@ -333,6 +371,32 @@ class ChromiumFilter(ChromiumFilterOne): """返回用于获取元素属性的对象""" ... + def tag(self, name: str, equal: bool = True) -> ChromiumFilter: + """筛选某种元素 + :param name: 标签页名称 + :param equal: True表示匹配这种元素,False表示匹配非这种元素 + :return: 筛选结果 + """ + ... + + def attr(self, name: str, value: str, equal: bool = True) -> ChromiumFilter: + """以是否拥有某个attribute值为条件筛选元素 + :param name: 属性名称 + :param value: 属性值 + :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 + :return: 筛选结果 + """ + ... + + def text(self, text: str, fuzzy: bool = True, contain: bool = True) -> ChromiumFilter: + """以是否含有指定文本为条件筛选元素 + :param text: 用于匹配的文本 + :param fuzzy: 是否模糊匹配 + :param contain: 是否包含该字符串,False表示不包含 + :return: 筛选结果 + """ + ... + def displayed(self, equal: bool = True) -> ChromiumFilter: """以是否显示为条件筛选元素 :param equal: 是否匹配显示的元素,False匹配不显示的 @@ -395,15 +459,6 @@ class ChromiumFilter(ChromiumFilterOne): """ ... - def attr(self, name: str, value: str, equal: bool = True) -> ChromiumFilter: - """以是否拥有某个attribute值为条件筛选元素 - :param name: 属性名称 - :param value: 属性值 - :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 - :return: 筛选结果 - """ - ... - def search_one(self, index: int = 1, displayed: Optional[bool] = None, @@ -412,7 +467,8 @@ class ChromiumFilter(ChromiumFilterOne): enabled: Optional[bool] = None, clickable: Optional[bool] = None, have_rect: Optional[bool] = None, - have_text: Optional[bool] = None) -> ChromiumElement: + have_text: Optional[bool] = None, + tag: str = None) -> ChromiumElement: """或关系筛选元素,获取一个结果 :param index: 元素序号,从1开始 :param displayed: 是否显示,bool,None为忽略该项 @@ -422,6 +478,7 @@ class ChromiumFilter(ChromiumFilterOne): :param clickable: 是否可点击,bool,None为忽略该项 :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 :param have_text: 是否含有文本,bool,None为忽略该项 + :param tag: 指定的元素类型 :return: 筛选结果 """ ... @@ -433,7 +490,8 @@ class ChromiumFilter(ChromiumFilterOne): enabled: Optional[bool] = None, clickable: Optional[bool] = None, have_rect: Optional[bool] = None, - have_text: Optional[bool] = None) -> ChromiumFilter: + have_text: Optional[bool] = None, + tag: str = None) -> ChromiumFilter: """或关系筛选元素 :param displayed: 是否显示,bool,None为忽略该项 :param checked: 是否被选中,bool,None为忽略该项 @@ -442,15 +500,7 @@ class ChromiumFilter(ChromiumFilterOne): :param clickable: 是否可点击,bool,None为忽略该项 :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 :param have_text: 是否含有文本,bool,None为忽略该项 - :return: 筛选结果 - """ - ... - - def text(self, text: str, fuzzy: bool = True, contain: bool = True) -> ChromiumFilter: - """以是否含有指定文本为条件筛选元素 - :param text: 用于匹配的文本 - :param fuzzy: 是否模糊匹配 - :param contain: 是否包含该字符串,False表示不包含 + :param tag: 指定的元素类型 :return: 筛选结果 """ ... diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 1d1b021..54020a7 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -476,7 +476,7 @@ class ChromiumBase(BasePage): raise PageDisconnectedError if perf_counter() >= end_time: - return NoneElement(self) if index is not None else ChromiumElementsList() + return NoneElement(self) if index is not None else ChromiumElementsList(owner=self) sleep(.1) timeout = end_time - perf_counter() @@ -601,7 +601,7 @@ class ChromiumBase(BasePage): def get_frames(self, locator=None, timeout=None): 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'] + return ChromiumElementsList(self, frames) def session_storage(self, item=None): js = f'sessionStorage.getItem("{item}")' if item else 'sessionStorage' diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index 94d75d1..b3b28a8 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -6,7 +6,7 @@ @License : BSD 3-Clause. """ from pathlib import Path -from typing import Union, Tuple, List, Any, Optional, Literal +from typing import Union, Tuple, Any, Optional, Literal from .chromium_page import ChromiumPage from .chromium_tab import ChromiumTab @@ -489,7 +489,9 @@ class ChromiumBase(BasePage): """ ... - def get_frames(self, locator: Union[str, tuple] = None, timeout: float = None) -> List[ChromiumFrame]: + def get_frames(self, + locator: Union[str, tuple] = None, + timeout: float = None) -> ChromiumElementsList: """获取所有符合条件的frame对象 :param locator: 定位符,为None时返回所有 :param timeout: 查找超时时间(秒)