From ecc82e69daa150246c94d89d3edb7645c5b23a98 Mon Sep 17 00:00:00 2001 From: g1879 Date: Sat, 28 Sep 2024 21:49:02 +0800 Subject: [PATCH] =?UTF-8?q?4.1.0.6(+)=20DataPacket=E5=AF=B9=E8=B1=A1reques?= =?UTF-8?q?t=E5=A2=9E=E5=8A=A0params=E5=B1=9E=E6=80=A7=EF=BC=9B=20s=5Fele(?= =?UTF-8?q?)=E8=A1=A5=E5=9B=9Etimeout=E5=8F=82=E6=95=B0=EF=BC=9B=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8Dnew=5Ftab()=E6=97=A0url=E6=97=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=9B=20wait.has=5Frect()=E3=80=81wait.covered()?= =?UTF-8?q?=E6=88=90=E5=8A=9F=E6=97=B6=E8=BF=94=E5=9B=9E=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E8=80=85=EF=BC=9B=20=E5=85=83=E7=B4=A0=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=88=87=E7=89=87=E6=97=B6=E4=B9=9F=E8=BF=94=E5=9B=9E=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/__init__.py | 2 +- DrissionPage/_base/chromium.py | 4 +-- DrissionPage/_elements/chromium_element.py | 11 +++---- DrissionPage/_functions/elements.py | 9 ++++++ DrissionPage/_functions/elements.pyi | 4 +-- DrissionPage/_pages/mix_tab.py | 11 +++---- DrissionPage/_pages/mix_tab.pyi | 7 +++-- DrissionPage/_pages/web_page.py | 11 +++---- DrissionPage/_pages/web_page.pyi | 7 +++-- DrissionPage/_units/listener.py | 5 ++++ DrissionPage/_units/listener.pyi | 5 ++++ DrissionPage/_units/waiter.py | 6 ++-- DrissionPage/_units/waiter.pyi | 34 +++++++++++----------- 13 files changed, 73 insertions(+), 43 deletions(-) diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index 37b3836..c1b2f89 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -12,4 +12,4 @@ from ._pages.chromium_page import ChromiumPage from ._pages.session_page import SessionPage from ._pages.web_page import WebPage -__version__ = '4.1.0.5' +__version__ = '4.1.0.6' diff --git a/DrissionPage/_base/chromium.py b/DrissionPage/_base/chromium.py index 70a054a..1b41973 100644 --- a/DrissionPage/_base/chromium.py +++ b/DrissionPage/_base/chromium.py @@ -339,7 +339,7 @@ class Chromium(object): if tabs: id_or_num = tabs[0] else: - return None + raise RuntimeError('没有找到指定标签页。') if as_id: return id_or_num @@ -478,9 +478,9 @@ def run_browser(chromium_options): def _new_tab_by_js(browser: Chromium, url, obj, new_window): mix = isinstance(obj, MixTab) tab = browser._get_tab(mix=mix) - url = f'"{url}"' if url else '' if url and not match(r'^.*?://.*', url): raise ValueError(f'url也许需要加上http://?') + url = f'"{url}"' if url else '""' new = 'target="_new"' if new_window else 'target="_blank"' tid = browser.latest_tab.tab_id tab.run_js(f'window.open({url}, {new})') diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index 4e9c1dc..c335efd 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -240,11 +240,12 @@ class ChromiumElement(DrissionElement): def over(self, timeout=None): if timeout is None: timeout = self.timeout - bid = self.wait.covered(timeout=timeout) - if bid: - return ChromiumElement(owner=self.owner, backend_id=bid) - else: - return NoneElement(page=self.owner, method='on()', args={'timeout': timeout}) + bid = self.states.is_covered + end_time = perf_counter() + timeout + while not bid and perf_counter() < end_time: + bid = self.states.is_covered + return (ChromiumElement(owner=self.owner, backend_id=bid) + if bid else NoneElement(page=self.owner, method='over()', args={'timeout': timeout})) def offset(self, locator=None, x=None, y=None, timeout=None): if locator and not (isinstance(locator, str) and not locator.startswith( diff --git a/DrissionPage/_functions/elements.py b/DrissionPage/_functions/elements.py index f559db2..304569d 100644 --- a/DrissionPage/_functions/elements.py +++ b/DrissionPage/_functions/elements.py @@ -16,6 +16,15 @@ class SessionElementsList(list): super().__init__(*args) self._owner = owner + def __getitem__(self, item): + cls = type(self) + if isinstance(item, slice): + return cls(self._owner, super().__getitem__(item)) + elif isinstance(item, int): + return super().__getitem__(item) + else: + raise TypeError('序号必须是数字或切片。') + @property def get(self): return Getter(self) diff --git a/DrissionPage/_functions/elements.pyi b/DrissionPage/_functions/elements.pyi index 1cf8704..830e925 100644 --- a/DrissionPage/_functions/elements.pyi +++ b/DrissionPage/_functions/elements.pyi @@ -29,7 +29,7 @@ class SessionElementsList(list): def __next__(self) -> SessionElement: ... - def __getitem__(self, _i) -> Union[SessionElement, List[SessionElement]]: ... + def __getitem__(self, _i) -> Union[SessionElement, SessionElementsList]: ... def __iter__(self) -> List[SessionElement]: ... @@ -63,7 +63,7 @@ class ChromiumElementsList(SessionElementsList): def __next__(self) -> ChromiumElement: ... - def __getitem__(self, _i) -> Union[ChromiumElement, List[ChromiumElement]]: ... + def __getitem__(self, _i) -> Union[ChromiumElement, ChromiumElementsList]: ... def __iter__(self) -> List[ChromiumElement]: ... diff --git a/DrissionPage/_pages/mix_tab.py b/DrissionPage/_pages/mix_tab.py index 72a46f2..186451a 100644 --- a/DrissionPage/_pages/mix_tab.py +++ b/DrissionPage/_pages/mix_tab.py @@ -112,12 +112,13 @@ class MixTab(SessionPage, ChromiumTab, BasePage): def eles(self, locator, timeout=None): return super(SessionPage, self).eles(locator, timeout=timeout) if self._d_mode else super().eles(locator) - def s_ele(self, locator=None, index=1): - return super(SessionPage, self).s_ele(locator, - index=index) if self._d_mode else super().s_ele(locator, index=index) + def s_ele(self, locator=None, index=1, timeout=None): + return (super(SessionPage, self).s_ele(locator, index=index, timeout=timeout) + if self._d_mode else super().s_ele(locator, index=index, timeout=timeout)) - def s_eles(self, locator): - return super(SessionPage, self).s_eles(locator) if self._d_mode else super().s_eles(locator) + def s_eles(self, locator, timeout=None): + return (super(SessionPage, self).s_eles(locator, timeout=timeout) + if self._d_mode else super().s_eles(locator, timeout=timeout)) def change_mode(self, mode=None, go=True, copy_cookies=True): if mode: diff --git a/DrissionPage/_pages/mix_tab.pyi b/DrissionPage/_pages/mix_tab.pyi index 066d908..c540b27 100644 --- a/DrissionPage/_pages/mix_tab.pyi +++ b/DrissionPage/_pages/mix_tab.pyi @@ -225,17 +225,20 @@ class MixTab(SessionPage, ChromiumTab): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> SessionElement: + index: int = 1, + timeout: float = None) -> SessionElement: """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: SessionElement对象或属性、文本 """ ... - def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionElementsList: + def s_eles(self, locator: Union[Tuple[str, str], str], timeout: float = None) -> SessionElementsList: """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: SessionElement对象或属性、文本组成的列表 """ ... diff --git a/DrissionPage/_pages/web_page.py b/DrissionPage/_pages/web_page.py index 52bff12..c6f9411 100644 --- a/DrissionPage/_pages/web_page.py +++ b/DrissionPage/_pages/web_page.py @@ -134,12 +134,13 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def eles(self, locator, timeout=None): return super(SessionPage, self).eles(locator, timeout=timeout) if self._d_mode else super().eles(locator) - def s_ele(self, locator=None, index=1): - return super(SessionPage, self).s_ele(locator, - index=index) if self._d_mode else super().s_ele(locator, index=index) + def s_ele(self, locator=None, index=1, timeout=None): + return (super(SessionPage, self).s_ele(locator, index=index, timeout=timeout) + if self._d_mode else super().s_ele(locator, index=index, timeout=timeout)) - def s_eles(self, locator): - return super(SessionPage, self).s_eles(locator) if self._d_mode else super().s_eles(locator) + def s_eles(self, locator, timeout=None): + return (super(SessionPage, self).s_eles(locator, timeout=timeout) + if self._d_mode else super().s_eles(locator, timeout=timeout)) def change_mode(self, mode=None, go=True, copy_cookies=True): if mode: diff --git a/DrissionPage/_pages/web_page.pyi b/DrissionPage/_pages/web_page.pyi index c6b9f74..a61286b 100644 --- a/DrissionPage/_pages/web_page.pyi +++ b/DrissionPage/_pages/web_page.pyi @@ -240,17 +240,20 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def s_ele(self, locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> SessionElement: + index: int = 1, + timeout: float = None) -> SessionElement: """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 :param locator: 元素的定位信息,可以是loc元组,或查询字符串 :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: SessionElement对象或属性、文本 """ ... - def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionElementsList: + def s_eles(self, locator: Union[Tuple[str, str], str], timeout: float = None) -> SessionElementsList: """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 :return: SessionElement对象或属性、文本组成的列表 """ ... diff --git a/DrissionPage/_units/listener.py b/DrissionPage/_units/listener.py index 612512e..818e33d 100644 --- a/DrissionPage/_units/listener.py +++ b/DrissionPage/_units/listener.py @@ -453,6 +453,11 @@ class Request(object): self._headers = CaseInsensitiveDict(self._request['headers']) return self._headers + @property + def params(self): + from urllib.parse import parse_qsl, urlparse + return dict(parse_qsl(urlparse(self.url).query, keep_blank_values=True)) + @property def postData(self): if self._postData is None: diff --git a/DrissionPage/_units/listener.pyi b/DrissionPage/_units/listener.pyi index fe1565e..91200aa 100644 --- a/DrissionPage/_units/listener.pyi +++ b/DrissionPage/_units/listener.pyi @@ -279,6 +279,11 @@ class Request(object): """以大小写不敏感字典返回headers数据""" ... + @property + def params(self) -> dict: + """dict格式返回请求url中的参数""" + ... + @property def postData(self) -> Any: """返回postData数据""" diff --git a/DrissionPage/_units/waiter.py b/DrissionPage/_units/waiter.py index 0bdabfc..6691484 100644 --- a/DrissionPage/_units/waiter.py +++ b/DrissionPage/_units/waiter.py @@ -316,7 +316,8 @@ class ElementWaiter(OriginWaiter): return self._wait_state('is_displayed', False, timeout, raise_err, err_text='等待元素隐藏失败。') def covered(self, timeout=None, raise_err=None): - return self._wait_state('is_covered', True, timeout, raise_err, err_text='等待元素被覆盖失败。') + return self._ele if self._wait_state('is_covered', True, timeout, raise_err, + err_text='等待元素被覆盖失败。') else False def not_covered(self, timeout=None, raise_err=None): return self._wait_state('is_covered', False, timeout, raise_err, err_text='等待元素不被覆盖失败。') @@ -355,7 +356,8 @@ class ElementWaiter(OriginWaiter): return r def has_rect(self, timeout=None, raise_err=None): - return self._wait_state('has_rect', True, timeout, raise_err, err_text='等待元素拥有大小及位置失败(等{}秒)。') + return self._ele if self._wait_state('has_rect', True, timeout, raise_err, + err_text='等待元素拥有大小及位置失败(等{}秒)。') else False def stop_moving(self, timeout=None, gap=.1, raise_err=None): if timeout is None: diff --git a/DrissionPage/_units/waiter.pyi b/DrissionPage/_units/waiter.pyi index df5cd8c..6a0216d 100644 --- a/DrissionPage/_units/waiter.pyi +++ b/DrissionPage/_units/waiter.pyi @@ -5,7 +5,7 @@ @Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. @License : BSD 3-Clause. """ -from typing import Union, Tuple, List, Any +from typing import Union, Tuple, Any from .downloader import DownloadMission from .._base.chromium import Chromium @@ -27,7 +27,7 @@ class OriginWaiter(object): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: 调用等待的对象 """ ... @@ -45,7 +45,7 @@ class BrowserWaiter(OriginWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: Chromium对象 """ ... @@ -163,7 +163,7 @@ class BaseWaiter(OriginWaiter): text: str, exclude: bool = False, timeout: float = None, - raise_err: bool = None) -> bool: + raise_err: bool = None) -> ChromiumBase: """等待url变成包含或不包含指定文本 :param text: 用于识别的文本 :param exclude: 是否排除,为True时当url不包含text指定文本时返回True @@ -177,7 +177,7 @@ class BaseWaiter(OriginWaiter): text: str, exclude: bool = False, timeout: float = None, - raise_err: bool = None) -> bool: + raise_err: bool = None) -> ChromiumBase: """等待title变成包含或不包含指定文本 :param text: 用于识别的文本 :param exclude: 是否排除,为True时当title不包含text指定文本时返回True @@ -219,7 +219,7 @@ class BaseWaiter(OriginWaiter): class TabWaiter(BaseWaiter): - _owner: Union[ChromiumTab, MixTab] = ... + _owner: ChromiumTab = ... def __init__(self, owner: ChromiumTab): """ @@ -233,7 +233,7 @@ class TabWaiter(BaseWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: ChromiumTab对象 """ ... @@ -284,7 +284,7 @@ class TabWaiter(BaseWaiter): class MixTabWaiter(BaseWaiter): - _owner: Union[ChromiumTab, MixTab] = ... + _owner: MixTab = ... def __init__(self, owner: MixTab): """ @@ -298,7 +298,7 @@ class MixTabWaiter(BaseWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: MixTab对象 """ ... @@ -363,7 +363,7 @@ class ChromiumPageWaiter(TabWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: ChromiumPage对象 """ ... @@ -431,7 +431,7 @@ class WebPageWaiter(TabWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: WebPage对象 """ ... @@ -500,7 +500,7 @@ class ElementWaiter(OriginWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: ChromiumElement对象 """ ... @@ -533,7 +533,7 @@ class ElementWaiter(OriginWaiter): """ ... - def covered(self, timeout: float = None, raise_err: bool = None) -> Union[False, int]: + def covered(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumFrame, False]: """等待当前元素被遮盖 :param timeout: 超时时间(秒),为None使用元素所在页面timeout属性 :param raise_err: 等待失败时是否报错,为None时根据Settings设置 @@ -587,11 +587,11 @@ class ElementWaiter(OriginWaiter): def has_rect(self, timeout: float = None, - raise_err: bool = None) -> Union[False, List[Tuple[float, float]]]: + raise_err: bool = None) -> Union[ChromiumElement, False]: """等待当前元素有大小及位置属性 :param timeout: 超时时间(秒),为None使用元素所在页面timeout属性 :param raise_err: 等待失败时是否报错,为None时根据Settings设置 - :return: 成功返回元素四角坐标(左上 右上 右下 左下),失败返回False + :return: 成功返回元素对象,失败返回False """ ... @@ -639,7 +639,7 @@ class FrameWaiter(BaseWaiter, ElementWaiter): """等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数 :param second: 秒数 :param scope: 随机数范围 - :return: None + :return: ChromiumFrame对象 """ ... @@ -695,7 +695,7 @@ class FrameWaiter(BaseWaiter, ElementWaiter): """ ... - def covered(self, timeout: float = None, raise_err: bool = None) -> Union[False, int]: + def covered(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumFrame, False]: """等待当前元素被遮盖 :param timeout: 超时时间(秒),为None使用元素所在页面timeout属性 :param raise_err: 等待失败时是否报错,为None时根据Settings设置