From 36166c8723967fda13a8b2675abce9def346a478 Mon Sep 17 00:00:00 2001 From: g1879 Date: Mon, 22 Nov 2021 00:05:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=89=80=E6=9C=89ele()?= =?UTF-8?q?=E3=80=81eles()=E6=96=B9=E6=B3=95=E7=9A=84mode=E5=8F=82?= =?UTF-8?q?=E6=95=B0=EF=BC=9B=E5=88=A0=E9=99=A4Session=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=92=8C=E5=85=83=E7=B4=A0=E5=AF=B9=E8=B1=A1ele()=E3=80=81eles?= =?UTF-8?q?()=E6=96=B9=E6=B3=95=E7=9A=84timeout=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/base.py | 59 +++++------------- DrissionPage/driver_element.py | 92 ++++++++++++++++------------- DrissionPage/driver_page.py | 73 +++++++++++++---------- DrissionPage/mix_page.py | 83 +++++++++++++++++--------- DrissionPage/session_element.py | 74 ++++++++++++----------- DrissionPage/session_page.py | 59 ++++++++++-------- DrissionPage/shadow_root_element.py | 80 ++++++++++++++----------- 7 files changed, 286 insertions(+), 234 deletions(-) diff --git a/DrissionPage/base.py b/DrissionPage/base.py index cfbb141..ad6d894 100644 --- a/DrissionPage/base.py +++ b/DrissionPage/base.py @@ -15,23 +15,14 @@ from .common import format_html class BaseParser(object): - def __call__(self, - loc_or_str, - mode: str = 'single', - timeout: float = None): - return self.ele(loc_or_str, mode, timeout) + def __call__(self, loc_or_str): + return self.ele(loc_or_str) - def eles(self, - loc_or_str: Union[Tuple[str, str], str], - timeout: float = None): - return self.ele(loc_or_str, mode='all', timeout=timeout) + def ele(self, loc_or_ele): + return self._ele(loc_or_ele, True) - def s_eles(self, loc_or_str: Union[Tuple[str, str], str]): - """查找并以SessionElement方式返回元素 \n - :param loc_or_str: 定位符 - :return: SessionElement或属性、文本组成的列表 - """ - return self.s_ele(loc_or_str, mode='all') + def eles(self, loc_or_str: Union[Tuple[str, str], str]): + return self._ele(loc_or_str, False) # ----------------以下属性或方法待后代实现---------------- @property @@ -39,16 +30,20 @@ class BaseParser(object): return @abstractmethod - def s_ele(self, loc_or_ele, mode='single'): + def s_ele(self, loc_or_ele): pass @abstractmethod - def ele(self, loc_or_ele, mode='single', timeout=None): + def s_eles(self, loc_or_str): + pass + + @abstractmethod + def _ele(self, loc_or_ele, timeout=None, single=True): pass class BaseElement(BaseParser): - """SessionElement和DriverElement的基类""" + """SessionElement 和 DriverElement 的基类""" def __init__(self, ele: Union[WebElement, HtmlElement], page=None): self._inner_ele = ele @@ -63,9 +58,6 @@ class BaseElement(BaseParser): """返回后一个兄弟元素""" return self.nexts() - # def eles(self, loc_or_str, timeout): - # return super().eles(loc_or_str, timeout) - # ----------------以下属性或方法由后代实现---------------- @property def tag(self): @@ -87,10 +79,6 @@ class BaseElement(BaseParser): def is_valid(self): return True - @abstractmethod - def ele(self, loc_or_str, mode='single', timeout=None): - pass - @abstractmethod def nexts(self, num: int = 1): pass @@ -183,12 +171,12 @@ class DrissionElement(BaseElement): timeout = 0 if direction == 'prev' else .5 # 获取节点 - ele_or_node = self.ele(f'xpath:./{direction_txt}-sibling::{node_txt}[{num}]', timeout=timeout) + ele_or_node = self._ele(f'xpath:./{direction_txt}-sibling::{node_txt}[{num}]', timeout=timeout) # 跳过元素间的换行符 while isinstance(ele_or_node, str) and sub('[\n\t ]', '', ele_or_node) == '': num += 1 - ele_or_node = self.ele(f'xpath:./{direction_txt}-sibling::{node_txt}[{num}]', timeout=timeout) + ele_or_node = self._ele(f'xpath:./{direction_txt}-sibling::{node_txt}[{num}]', timeout=timeout) return ele_or_node @@ -217,14 +205,6 @@ class DrissionElement(BaseElement): def attr(self, attr: str): return '' - @abstractmethod - def ele(self, loc: Union[tuple, str], mode: str = None, timeout=None): - pass - - @abstractmethod - def eles(self, loc: Union[tuple, str], timeout=None): - pass - def _get_ele_path(self, mode): return '' @@ -241,7 +221,7 @@ class BasePage(BaseParser): @property def title(self) -> Union[str, None]: """返回网页title""" - ele = self.ele('x:/html/head/title') + ele = self.ele('xpath:/html/head/title') return ele.text if ele else None @property @@ -264,9 +244,6 @@ class BasePage(BaseParser): """返回当前访问的url有效性""" return self._url_available - # def eles(self, loc_or_str, timeout): - # return super().eles(loc_or_str, timeout) - # ----------------以下属性或方法由后代实现---------------- @property def url(self): @@ -293,10 +270,6 @@ class BasePage(BaseParser): interval: float = None): pass - @abstractmethod - def ele(self, loc_or_ele, mode='single', timeout=None): - pass - @abstractmethod def _try_to_connect(self, to_url: str, diff --git a/DrissionPage/driver_element.py b/DrissionPage/driver_element.py index a961b39..514df11 100644 --- a/DrissionPage/driver_element.py +++ b/DrissionPage/driver_element.py @@ -34,16 +34,14 @@ class DriverElement(DrissionElement): def __call__(self, loc_or_str: Union[Tuple[str, str], str], - mode: str = 'single', timeout: float = None): - """在内部查找元素 \n + """在内部查找元素 \n 例:ele2 = ele1('@id=ele_id') \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 :param timeout: 超时时间 - :return: DriverElement对象或属性文本 + :return: DriverElement对象或属性、文本 """ - return self.ele(loc_or_str, mode, timeout) + return self.ele(loc_or_str, timeout) # -----------------共有属性和方法------------------- @property @@ -116,12 +114,46 @@ class DriverElement(DrissionElement): def ele(self, loc_or_str: Union[Tuple[str, str], str], - mode: str = None, timeout: float = None): + """返回当前元素下级符合条件的第一个元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间 + :return: DriverElement对象或属性、文本 + """ + return self._ele(loc_or_str, timeout) + + def eles(self, + loc_or_str: Union[Tuple[str, str], str], + timeout: float = None): + """返回当前元素下级所有符合条件的子元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间 + :return: DriverElement对象或属性、文本组成的列表 + """ + return self._ele(loc_or_str, timeout=timeout, single=False) + + def s_ele(self, loc_or_ele): + """查找第一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 \n + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return make_session_ele(self, loc_or_ele) + + def s_eles(self, loc_or_str: Union[Tuple[str, str], str]): + """查找所有符合条件的元素以SessionElement列表形式返回 \n + :param loc_or_str: 定位符 + :return: SessionElement或属性、文本组成的列表 + """ + return make_session_ele(self, loc_or_str, single=False) + + def _ele(self, + loc_or_str: Union[Tuple[str, str], str], + timeout: float = None, + single: bool = True): """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 :param timeout: 查找元素超时时间 + :param single: True则返回第一个,False则返回全部 :return: DriverElement对象 """ loc_or_str = str_to_loc(loc_or_str) if isinstance(loc_or_str, str) else translate_loc(loc_or_str) @@ -134,25 +166,7 @@ class DriverElement(DrissionElement): loc_str = f'{self.css_path}{loc_or_str[1]}' loc_or_str = loc_or_str[0], loc_str - return make_driver_ele(self, loc_or_str, mode, timeout) - - def s_ele(self, loc_or_ele, mode='single'): - """查找元素以SessionElement形式返回,处理复杂页面时效率很高 \n - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 查找第一个或全部 - :return: SessionElement对象或属性、文本 - """ - return make_session_ele(self, loc_or_ele, mode) - - def eles(self, - loc_or_str: Union[Tuple[str, str], str], - timeout: float = None): - """返回当前元素下级所有符合条件的子元素、属性或节点文本 \n - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 查找元素超时时间 - :return: DriverElement对象组成的列表 - """ - return self.ele(loc_or_str, mode='all', timeout=timeout) + return make_driver_ele(self, loc_or_str, single, timeout) def _get_ele_path(self, mode) -> str: """返获取css路径或xpath路径""" @@ -532,20 +546,16 @@ class DriverElement(DrissionElement): def make_driver_ele(page_or_ele, loc: Union[str, Tuple[str, str]], - mode: str = 'single', + single: bool = True, timeout: float = None) -> Union[DriverElement, List[DriverElement], str, None]: """执行driver模式元素的查找 \n 页面查找元素及元素查找下级元素皆使用此方法 \n :param page_or_ele: DriverPage对象或DriverElement对象 :param loc: 元素定位元组 - :param mode: 'single' 或 'all',对应获取第一个或全部 + :param single: True则返回第一个,False则返回全部 :param timeout: 查找元素超时时间 :return: 返回DriverElement元素或它们组成的列表 """ - mode = mode or 'single' - if mode not in ('single', 'all'): - raise ValueError(f"mode参数只能是'single'或'all',现在是:'{mode}'。") - if isinstance(page_or_ele, BaseElement): page = page_or_ele.page driver = page_or_ele.inner_ele @@ -572,18 +582,18 @@ def make_driver_ele(page_or_ele, try: # 使用xpath查找 if loc[0] == 'xpath': - return wait.until(ElementsByXpath(page, loc[1], mode, timeout)) + return wait.until(ElementsByXpath(page, loc[1], single, timeout)) # 使用css selector查找 else: - if mode == 'single': + if single: return DriverElement(wait.until(ec.presence_of_element_located(loc)), page) - elif mode == 'all': + else: eles = wait.until(ec.presence_of_all_elements_located(loc)) return [DriverElement(ele, page) for ele in eles] except TimeoutException: - return [] if mode == 'all' else None + return [] if not single else None except InvalidElementStateException: raise ValueError(f'无效的查找语句:{loc}') @@ -592,16 +602,16 @@ def make_driver_ele(page_or_ele, class ElementsByXpath(object): """用js通过xpath获取元素、节点或属性,与WebDriverWait配合使用""" - def __init__(self, page, xpath: str = None, mode: str = 'all', timeout: float = 10): + def __init__(self, page, xpath: str = None, single: bool = False, timeout: float = 10): """ :param page: DrissionPage对象 :param xpath: xpath文本 - :param mode: 'all' 或 'single' + :param single: True则返回第一个,False则返回全部 :param timeout: 超时时间 """ self.page = page self.xpath = xpath - self.mode = mode + self.single = single self.timeout = timeout def __call__(self, ele_or_driver: Union[WebDriver, WebElement]) \ @@ -659,7 +669,7 @@ class ElementsByXpath(object): driver, the_node = ele_or_driver.parent, ele_or_driver # 把lxml元素对象包装成DriverElement对象并按需要返回第一个或全部 - if self.mode == 'single': + if self.single: try: e = get_nodes(the_node, xpath_txt=self.xpath, type_txt='9') @@ -680,7 +690,7 @@ class ElementsByXpath(object): else: return None - elif self.mode == 'all': + else: # 返回全部 return ([DriverElement(x, self.page) if isinstance(x, WebElement) else format_html(x) for x in get_nodes(the_node, xpath_txt=self.xpath) diff --git a/DrissionPage/driver_page.py b/DrissionPage/driver_page.py index 0c04a96..f8fc779 100644 --- a/DrissionPage/driver_page.py +++ b/DrissionPage/driver_page.py @@ -25,24 +25,21 @@ from .session_element import make_session_ele class DriverPage(BasePage): """DriverPage封装了页面操作的常用功能,使用selenium来获取、解析、操作网页""" - def __init__(self, driver: WebDriver, timeout: float = 10): + def __init__(self, driver: WebDriver, timeout: float = 10) -> None: """初始化函数,接收一个WebDriver对象,用来操作网页""" super().__init__(timeout) self._driver = driver self._wait_object = None - def __call__(self, - loc_or_str: Union[Tuple[str, str], str, DriverElement, WebElement], - mode: str = 'single', + def __call__(self, loc_or_str: Union[Tuple[str, str], str, DriverElement, WebElement], timeout: float = None) -> Union[DriverElement, List[DriverElement], str]: """在内部查找元素 \n - 例:ele = page('@id=ele_id') \n + 例:ele = page('@id=ele_id') \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 :param timeout: 超时时间 - :return: DriverElement对象或属性文本 + :return: DriverElement对象或属性、文本 """ - return super().__call__(loc_or_str, mode, timeout) + return self.ele(loc_or_str, timeout) # -----------------共有属性和方法------------------- @property @@ -97,17 +94,51 @@ class DriverPage(BasePage): def ele(self, loc_or_ele: Union[Tuple[str, str], str, DriverElement, WebElement], - mode: str = None, timeout: float = None) -> Union[DriverElement, List[DriverElement], str, None]: - """返回页面中符合条件的元素,默认返回第一个 \n + """返回页面中符合条件的第一个元素 \n :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param mode: 'single' 或 'all‘,对应查找一个或全部 :param timeout: 查找元素超时时间 + :return: DriverElement对象或属性、文本 + """ + return self._ele(loc_or_ele, timeout) + + def eles(self, + loc_or_str: Union[Tuple[str, str], str], + timeout: float = None) -> List[DriverElement]: + """返回页面中所有符合条件的元素 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间 + :return: DriverElement对象或属性、文本组成的列表 + """ + return self._ele(loc_or_str, timeout, single=False) + + def s_ele(self, loc_or_ele): + """查找第一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 \n + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return make_session_ele(self, loc_or_ele) + + def s_eles(self, loc_or_str: Union[Tuple[str, str], str]): + """查找所有符合条件的元素以SessionElement列表形式返回 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象组成的列表 + """ + return make_session_ele(self, loc_or_str, single=False) + + def _ele(self, + loc_or_ele: Union[Tuple[str, str], str, DriverElement, WebElement], + timeout: float = None, + single: bool = True) -> Union[DriverElement, List[DriverElement], str, None]: + """返回页面中符合条件的元素,默认返回第一个 \n + :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 查找元素超时时间 + :param single: True则返回第一个,False则返回全部 :return: DriverElement对象 """ # 接收到字符串或元组,获取定位loc元组 if isinstance(loc_or_ele, (str, tuple)): - return make_driver_ele(self, loc_or_ele, mode, timeout) + return make_driver_ele(self, loc_or_ele, single, timeout) # 接收到DriverElement对象直接返回 elif isinstance(loc_or_ele, DriverElement): @@ -121,24 +152,6 @@ class DriverPage(BasePage): else: raise ValueError('loc_or_str参数只能是tuple、str、DriverElement 或 DriverElement类型。') - def s_ele(self, loc_or_ele, mode='single'): - """查找元素以SessionElement形式返回,处理复杂页面时效率很高 \n - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 查找第一个或全部 - :return: SessionElement对象或属性、文本 - """ - return make_session_ele(self, loc_or_ele, mode) - - def eles(self, - loc_or_str: Union[Tuple[str, str], str], - timeout: float = None) -> List[DriverElement]: - """返回页面中所有符合条件的元素 \n - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 查找元素超时时间 - :return: DriverElement对象组成的列表 - """ - return super().eles(loc_or_str, timeout) - def get_cookies(self, as_dict: bool = False) -> Union[list, dict]: """返回当前网站cookies""" if as_dict: diff --git a/DrissionPage/mix_page.py b/DrissionPage/mix_page.py index bee5da8..6c9a2d0 100644 --- a/DrissionPage/mix_page.py +++ b/DrissionPage/mix_page.py @@ -33,7 +33,7 @@ class MixPage(SessionPage, DriverPage, BasePage): drission: Union[Drission, str] = None, timeout: float = 10, driver_options: Union[dict, DriverOptions] = None, - session_options: Union[dict, SessionOptions] = None): + session_options: Union[dict, SessionOptions] = None) -> None: """初始化函数 \n :param mode: 'd' 或 's',即driver模式和session模式 :param drission: Drission对象,不传入时会自动创建 @@ -50,17 +50,18 @@ class MixPage(SessionPage, DriverPage, BasePage): def __call__(self, loc_or_str: Union[Tuple[str, str], str, DriverElement, SessionElement, WebElement], - mode: str = 'single', timeout: float = None) \ -> Union[DriverElement, SessionElement, str, List[DriverElement], List[SessionElement]]: """在内部查找元素 \n 例:ele = page('@id=ele_id') \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 :param timeout: 超时时间 :return: 子元素对象或属性文本 """ - return super().__call__(loc_or_str, mode, timeout) + if self._mode == 's': + return super().__call__(loc_or_str) + elif self._mode == 'd': + return super(SessionPage, self).__call__(loc_or_str, timeout) # -----------------共有属性和方法------------------- @property @@ -119,30 +120,17 @@ class MixPage(SessionPage, DriverPage, BasePage): def ele(self, loc_or_ele: Union[Tuple[str, str], str, DriverElement, SessionElement, WebElement], - mode: str = None, timeout: float = None) \ -> Union[DriverElement, SessionElement, str, List[SessionElement], List[DriverElement]]: - """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 \n + """返回第一个符合条件的元素、属性或节点文本 \n :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param mode: 'single' 或 'all‘,对应查找一个或全部 :param timeout: 查找元素超时时间,d模式专用 :return: 元素对象或属性、文本节点文本 """ if self._mode == 's': - return super().ele(loc_or_ele, mode=mode) + return super().ele(loc_or_ele) elif self._mode == 'd': - return super(SessionPage, self).ele(loc_or_ele, mode=mode, timeout=timeout) - - def s_ele(self, loc_or_ele, mode='single') -> Union[SessionElement, List[SessionElement], List[str]]: - """查找元素以SessionElement形式返回,处理复杂页面时效率很高 \n - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 查找第一个或全部 - :return: SessionElement对象或属性、文本 - """ - if self._mode == 's': - return super().s_ele(loc_or_ele, mode=mode) - elif self._mode == 'd': - return super(SessionPage, self).s_ele(loc_or_ele, mode=mode) + return super(SessionPage, self).ele(loc_or_ele, timeout=timeout) def eles(self, loc_or_str: Union[Tuple[str, str], str], @@ -152,7 +140,46 @@ class MixPage(SessionPage, DriverPage, BasePage): :param timeout: 查找元素超时时间,d模式专用 :return: 元素对象或属性、文本组成的列表 """ - return super(SessionPage, self).eles(loc_or_str, timeout=timeout) + if self._mode == 's': + return super().eles(loc_or_str) + elif self._mode == 'd': + return super(SessionPage, self).eles(loc_or_str, timeout=timeout) + + def s_ele(self, loc_or_ele) -> Union[SessionElement, List[SessionElement], List[str]]: + """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 \n + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + if self._mode == 's': + return super().s_ele(loc_or_ele) + elif self._mode == 'd': + return super(SessionPage, self).s_ele(loc_or_ele) + + def s_eles(self, loc_or_ele) -> Union[SessionElement, List[SessionElement], List[str]]: + """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 \n + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本组成的列表 + """ + if self._mode == 's': + return super().s_eles(loc_or_ele) + elif self._mode == 'd': + return super(SessionPage, self).s_eles(loc_or_ele) + + def _ele(self, + loc_or_ele: Union[Tuple[str, str], str, DriverElement, SessionElement, WebElement], + timeout: float = None, + single: bool = True) \ + -> Union[DriverElement, SessionElement, str, List[SessionElement], List[DriverElement]]: + """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 \n + :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 查找元素超时时间,d模式专用 + :param single: True则返回第一个,False则返回全部 + :return: 元素对象或属性、文本节点文本 + """ + if self._mode == 's': + return super()._ele(loc_or_ele, single=single) + elif self._mode == 'd': + return super(SessionPage, self)._ele(loc_or_ele, timeout=timeout, single=single) def get_cookies(self, as_dict: bool = False, all_domains: bool = False) -> Union[dict, list]: """返回cookies \n @@ -189,13 +216,13 @@ class MixPage(SessionPage, DriverPage, BasePage): # ----------------MixPage独有属性和方法----------------------- @property def drission(self) -> Drission: - """返回当前使用的Dirssion对象""" + """返回当前使用的 Dirssion 对象""" return self._drission @property def driver(self) -> WebDriver: - """返回driver对象,如没有则创建 \n - 每次访问时切换到d模式,用于独有函数及外部调用 + """返回 driver 对象,如没有则创建 \n + 每次访问时切换到 d 模式,用于独有函数及外部调用 :return: WebDriver对象 """ self.change_mode('d') @@ -203,12 +230,12 @@ class MixPage(SessionPage, DriverPage, BasePage): @property def session(self) -> Session: - """返回Session对象,如没有则创建""" + """返回 Session 对象,如没有则创建""" return self._drission.session @property def response(self) -> Response: - """返回s模式获取到的Response对象,切换到s模式""" + """返回 s 模式获取到的 Response 对象,切换到 s 模式""" self.change_mode('s') return self._response @@ -219,11 +246,11 @@ class MixPage(SessionPage, DriverPage, BasePage): @property def _session_url(self) -> str: - """返回session保存的url""" + """返回 session 保存的url""" return self._response.url if self._response else None def change_mode(self, mode: str = None, go: bool = True) -> None: - """切换模式,接收's'或'd',除此以外的字符串会切换为d模式 \n + """切换模式,接收's'或'd',除此以外的字符串会切换为 d 模式 \n 切换时会把当前模式的cookies复制到目标模式 \n 切换后,如果go是True,调用相应的get函数使访问的页面同步 \n :param mode: 模式字符串 diff --git a/DrissionPage/session_element.py b/DrissionPage/session_element.py index 494fd23..906a0a1 100644 --- a/DrissionPage/session_element.py +++ b/DrissionPage/session_element.py @@ -25,15 +25,13 @@ class SessionElement(DrissionElement): attrs = [f"{attr}='{self.attrs[attr]}'" for attr in self.attrs] return f'' - def __call__(self, loc_or_str: Union[Tuple[str, str], str], mode: str = 'single', timeout: float = None): + def __call__(self, loc_or_str: Union[Tuple[str, str], str]): """在内部查找元素 \n - 例:ele2 = ele1('@id=ele_id') \n + 例:ele2 = ele1('@id=ele_id') \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 - :param timeout: 不起实际作用,用于和父类对应 - :return: SessionElement对象或属性文本 + :return: SessionElement对象或属性、文本 """ - return super().__call__(loc_or_str, mode, timeout) + return self.ele(loc_or_str) @property def tag(self) -> str: @@ -138,11 +136,39 @@ class SessionElement(DrissionElement): else: return self.inner_ele.get(attr) - def ele(self, loc_or_str: Union[Tuple[str, str], str], mode: str = None, timeout=None): - """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 \n + def ele(self, loc_or_str: Union[Tuple[str, str], str]): + """返回当前元素下级符合条件的第一个元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return self._ele(loc_or_str) + + def eles(self, loc_or_str: Union[Tuple[str, str], str]): + """返回当前元素下级所有符合条件的子元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本组成的列表 + """ + return self._ele(loc_or_str, single=False) + + def s_ele(self, loc_or_str: Union[Tuple[str, str], str]): + """返回当前元素下级符合条件的第一个元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return self._ele(loc_or_str) + + def s_eles(self, loc_or_str: Union[Tuple[str, str], str]): + """返回当前元素下级所有符合条件的子元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本组成的列表 + """ + return self._ele(loc_or_str, single=False) + + def _ele(self, loc_or_str: Union[Tuple[str, str], str], timeout=None, single: bool = True): + """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all‘,对应查找一个或全部 :param timeout: 不起实际作用,用于和父类对应 + :param single: True则返回第一个,False则返回全部 :return: SessionElement对象 """ loc_or_str = str_to_loc(loc_or_str) if isinstance(loc_or_str, str) else translate_loc(loc_or_str) @@ -158,23 +184,7 @@ class SessionElement(DrissionElement): element = self.page loc_or_str = loc_or_str[0], loc_str - return make_session_ele(element, loc_or_str, mode) - - def eles(self, loc_or_str: Union[Tuple[str, str], str], timeout=None): - """返回当前元素下级所有符合条件的子元素、属性或节点文本 \n - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 不起实际作用,用于和父类对应 - :return: SessionElement对象组成的列表 - """ - return self.ele(loc_or_str, mode='all') - - def s_ele(self, loc_or_str: Union[Tuple[str, str], str], mode: str = None): - """返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个 \n - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all‘,对应查找一个或全部 - :return: SessionElement对象 - """ - return self.ele(loc_or_str, mode=mode) + return make_session_ele(element, loc_or_str, single) def _get_ele_path(self, mode) -> str: """获取css路径或xpath路径 @@ -223,18 +233,14 @@ class SessionElement(DrissionElement): def make_session_ele(html_or_ele: Union[str, BaseElement, BasePage], loc: Union[str, Tuple[str, str]] = None, - mode: str = 'single', ) -> Union[SessionElement, List[SessionElement], str, None]: + single: bool = True) -> Union[SessionElement, List[SessionElement], str, None]: """从接收到的对象或html文本中查找元素,返回SessionElement对象 \n 如要直接从html生成SessionElement而不在下级查找,loc输入None即可 \n :param html_or_ele: html文本、BaseParser对象 :param loc: 定位元组或字符串,为None时不在下级查找,返回根元素 - :param mode: 'single' 或 'all',对应获取第一个或全部 + :param single: True则返回第一个,False则返回全部 :return: 返回SessionElement元素或列表,或属性文本 """ - mode = mode or 'single' - if mode not in ('single', 'all'): - raise ValueError(f"mode参数只能是'single'或'all',现在是:'{mode}'。") - # 根据传入对象类型获取页面对象和lxml元素对象 if isinstance(html_or_ele, SessionElement): # SessionElement page = html_or_ele.page @@ -278,7 +284,7 @@ def make_session_ele(html_or_ele: Union[str, BaseElement, BasePage], return ele # 把lxml元素对象包装成SessionElement对象并按需要返回第一个或全部 - if mode == 'single': + if single: ele = ele[0] if ele else None if isinstance(ele, HtmlElement): return SessionElement(ele, page) @@ -287,7 +293,7 @@ def make_session_ele(html_or_ele: Union[str, BaseElement, BasePage], else: return None - elif mode == 'all': + else: # 返回全部 return [SessionElement(e, page) if isinstance(e, HtmlElement) else e for e in ele if e != '\n'] except Exception as e: diff --git a/DrissionPage/session_page.py b/DrissionPage/session_page.py index ce51f17..07770ae 100644 --- a/DrissionPage/session_page.py +++ b/DrissionPage/session_page.py @@ -30,18 +30,14 @@ class SessionPage(BasePage): self._session = session self._response = None - def __call__(self, - loc_or_str: Union[Tuple[str, str], str, SessionElement], - mode: str = 'single', - timeout: float = None) -> Union[SessionElement, List[SessionElement], str]: + def __call__(self, loc_or_str: Union[Tuple[str, str], str, SessionElement]) \ + -> Union[SessionElement, List[SessionElement], str]: """在内部查找元素 \n - 例:ele2 = ele1('@id=ele_id') \n + 例:ele2 = ele1('@id=ele_id') \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 - :param timeout: 不起实际作用,用于和父类对应 :return: SessionElement对象或属性文本 """ - return super().__call__(loc_or_str, mode, timeout) + return self.ele(loc_or_str) # -----------------共有属性和方法------------------- @property @@ -100,33 +96,46 @@ class SessionPage(BasePage): return self._url_available - def ele(self, - loc_or_ele: Union[Tuple[str, str], str, SessionElement], - mode: str = None, - timeout=None) -> Union[SessionElement, List[SessionElement], str, None]: - """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 \n + def ele(self, loc_or_ele: Union[Tuple[str, str], str, SessionElement]) \ + -> Union[SessionElement, List[SessionElement], str, None]: + """返回页面中符合条件的第一个元素、属性或节点文本 \n :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param mode: 'single' 或 'all‘,对应查找一个或全部 - :param timeout: 不起实际作用,用于和父类对应 - :return: SessionElement对象 + :return: SessionElement对象或属性、文本 """ - return loc_or_ele if isinstance(loc_or_ele, SessionElement) else make_session_ele(self, loc_or_ele, mode) + return self._ele(loc_or_ele) - def eles(self, loc_or_str: Union[Tuple[str, str], str], timeout=None) -> List[SessionElement]: + def eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[SessionElement]: """返回页面中所有符合条件的元素、属性或节点文本 \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 不起实际作用,用于和父类对应 - :return: SessionElement对象组成的列表 + :return: SessionElement对象或属性、文本组成的列表 """ - return super().eles(loc_or_str, timeout) + return self._ele(loc_or_str, single=False) - def s_ele(self, loc_or_str: Union[Tuple[str, str], str], mode: str = None): - """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 \n + def s_ele(self, loc_or_str: Union[Tuple[str, str], str]): + """返回页面中符合条件的第一个元素、属性或节点文本 \n :param loc_or_str: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param mode: 'single' 或 'all‘,对应查找一个或全部 + :return: SessionElement对象或属性、文本 + """ + return self._ele(loc_or_str) + + def s_eles(self, loc_or_str: Union[Tuple[str, str], str]): + """返回页面中符合条件的所有元素、属性或节点文本 \n + :param loc_or_str: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return self._ele(loc_or_str, single=False) + + def _ele(self, + loc_or_ele: Union[Tuple[str, str], str, SessionElement], + timeout: float = None, + single: bool = True) -> Union[SessionElement, List[SessionElement], str, None]: + """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 \n + :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 不起实际作用,用于和父类对应 + :param single: True则返回第一个,False则返回全部 :return: SessionElement对象 """ - return self.ele(loc_or_str, mode=mode) + return loc_or_ele if isinstance(loc_or_ele, SessionElement) else make_session_ele(self, loc_or_ele, single) def get_cookies(self, as_dict: bool = False, all_domains: bool = False) -> Union[dict, list]: """返回cookies \n diff --git a/DrissionPage/shadow_root_element.py b/DrissionPage/shadow_root_element.py index d28ccf3..a507810 100644 --- a/DrissionPage/shadow_root_element.py +++ b/DrissionPage/shadow_root_element.py @@ -25,16 +25,14 @@ class ShadowRootElement(BaseElement): def __call__(self, loc_or_str: Union[Tuple[str, str], str], - mode: str = 'single', timeout: float = None) -> Union[DriverElement, List[DriverElement], str]: """在内部查找元素 \n 例:ele2 = ele1('@id=ele_id') \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 :param timeout: 超时时间 - :return: DriverElement对象或属性文本 + :return: DriverElement对象或属性、文本 """ - return self.ele(loc_or_str, mode, timeout) + return self.ele(loc_or_str, timeout) @property def tag(self) -> str: @@ -69,12 +67,46 @@ class ShadowRootElement(BaseElement): def ele(self, loc_or_str: Union[Tuple[str, str], str], - mode: str = 'single', timeout: float = None) -> Union[DriverElement, List[DriverElement]]: + """返回当前元素下级符合条件的第一个元素,默认返回 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间 + :return: DriverElement对象或属性、文本 + """ + return self._ele(loc_or_str, timeout) + + def eles(self, + loc_or_str: Union[Tuple[str, str], str], + timeout: float = None) -> List[DriverElement]: + """返回当前元素下级所有符合条件的子元素 \n + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间 + :return: DriverElement对象或属性、文本组成的列表 + """ + return self._ele(loc_or_str, timeout=timeout, single=False) + + def s_ele(self, loc_or_ele): + """查找第一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高 \n + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return make_session_ele(self, loc_or_ele) + + def s_eles(self, loc_or_ele): + """查找所有符合条件的元素以SessionElement列表形式返回,处理复杂页面时效率很高 \n + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + return make_session_ele(self, loc_or_ele, single=False) + + def _ele(self, + loc_or_str: Union[Tuple[str, str], str], + timeout: float = None, + single: bool = True) -> Union[DriverElement, List[DriverElement]]: """返回当前元素下级符合条件的子元素,默认返回第一个 \n :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 'single' 或 'all',对应查找一个或全部 :param timeout: 查找元素超时时间 + :param single: True则返回第一个,False则返回全部 :return: DriverElement对象 """ if isinstance(loc_or_str, str): @@ -86,27 +118,9 @@ class ShadowRootElement(BaseElement): raise ValueError('loc_or_str参数只能是tuple或str类型。') if loc_or_str[0] == 'css selector': - return make_driver_ele(self, loc_or_str, mode, timeout) + return make_driver_ele(self, loc_or_str, single, timeout) elif loc_or_str[0] == 'text': - return self._find_eles_by_text(loc_or_str[1], loc_or_str[2], loc_or_str[3], mode) - - def s_ele(self, loc_or_ele, mode='single'): - """查找元素以SessionElement形式返回,处理复杂页面时效率很高 \n - :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 - :param mode: 查找第一个或全部 - :return: SessionElement对象或属性、文本 - """ - return make_session_ele(self, loc_or_ele, mode) - - def eles(self, - loc_or_str: Union[Tuple[str, str], str], - timeout: float = None) -> List[DriverElement]: - """返回当前元素下级所有符合条件的子元素 \n - :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 查找元素超时时间 - :return: DriverElement对象组成的列表 - """ - return super().eles(loc_or_str, timeout) + return self._find_eles_by_text(loc_or_str[1], loc_or_str[2], loc_or_str[3], single) def run_script(self, script: str, *args) -> Any: """执行js代码,传入自己为第一个参数 \n @@ -133,12 +147,12 @@ class ShadowRootElement(BaseElement): text: str, tag: str = '', match: str = 'exact', - mode: str = 'single') -> Union[DriverElement, List[DriverElement]]: + single: bool = True) -> Union[DriverElement, List[DriverElement]]: """根据文本获取页面元素 \n :param text: 文本字符串 :param tag: tag name :param match: 'exact' 或 'fuzzy',对应精确或模糊匹配 - :param mode: 'single' 或 'all',对应匹配一个或全部 + :param single: True则返回第一个,False则返回全部 :return: 返回DriverElement对象或组成的列表 """ # 获取所有元素 @@ -158,21 +172,21 @@ class ShadowRootElement(BaseElement): if text == '' or match == 'exact': if text == txt: - if mode == 'single': + if single: return DriverElement(ele, self.page) - elif mode == 'all': + else: results.append(DriverElement(ele, self.page)) # 模糊匹配 elif match == 'fuzzy': if text in txt: - if mode == 'single': + if single: return DriverElement(ele, self.page) - elif mode == 'all': + else: results.append(DriverElement(ele, self.page)) - return None if mode == 'single' else results + return None if single else results def str_to_css_loc(loc: str) -> tuple: