From a13177f86e2de90f248c24da327cc09940869622 Mon Sep 17 00:00:00 2001 From: g1879 Date: Tue, 14 May 2024 17:08:42 +0800 Subject: [PATCH] =?UTF-8?q?4.0.4.23(+)=20=E5=A2=9E=E5=8A=A0ele.states.is?= =?UTF-8?q?=5Fclickable=E3=80=81ele.wait.clickable()=E3=80=81ele.set.style?= =?UTF-8?q?()=EF=BC=9B=20wait.stop=5Fmoving()=E5=8F=82=E6=95=B0=E9=A1=BA?= =?UTF-8?q?=E5=BA=8F=E6=94=B9=E5=8F=98=EF=BC=9B=20=E7=AD=89=E5=BE=85?= =?UTF-8?q?=E5=85=83=E7=B4=A0=E6=97=B6=E5=8F=AF=E6=8A=9B=E5=87=BA=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=96=AD=E5=BC=80=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/_pages/chromium_base.py | 7 ++++++- DrissionPage/_units/setter.py | 13 ++++++++++++- DrissionPage/_units/setter.pyi | 2 ++ DrissionPage/_units/states.py | 5 +++++ DrissionPage/_units/states.pyi | 3 +++ DrissionPage/_units/waiter.py | 20 +++++++++++++++++--- DrissionPage/_units/waiter.pyi | 4 +++- 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index d5d9a3c..570e11c 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -585,6 +585,9 @@ class ChromiumBase(BasePage): if r is not False: break + elif nIds[__ERROR__] == 'connection disconnected': + raise PageDisconnectedError + if perf_counter() >= end_time: return NoneElement(self) if index is not None else [] @@ -592,9 +595,11 @@ class ChromiumBase(BasePage): timeout = end_time - perf_counter() timeout = .5 if timeout <= 0 else timeout result = self.driver.run('DOM.performSearch', query=loc, _timeout=timeout, includeUserAgentShadowDOM=True) - if not result or __ERROR__ not in result: + if result and __ERROR__ not in result: num = result['resultCount'] search_ids.append(result['searchId']) + elif result and result[__ERROR__] == 'connection disconnected': + raise PageDisconnectedError for _id in search_ids: self._driver.run('DOM.discardSearchResults', searchId=_id) diff --git a/DrissionPage/_units/setter.py b/DrissionPage/_units/setter.py index 8e576b2..d52fd26 100644 --- a/DrissionPage/_units/setter.py +++ b/DrissionPage/_units/setter.py @@ -14,7 +14,7 @@ from .cookies_setter import SessionCookiesSetter, CookiesSetter, WebPageCookiesS from .._functions.settings import Settings from .._functions.tools import show_or_hide_browser from .._functions.web import format_headers -from ..errors import ElementLostError +from ..errors import ElementLostError, JavaScriptError class BasePageSetter(object): @@ -494,6 +494,17 @@ class ChromiumElementSetter(object): value = value.replace('"', r'\"') self._ele.run_js(f'this.{name}="{value}";') + def style(self, name, value): + """设置元素style样式 + :param name: 样式名称 + :param value: 样式值 + :return: None + """ + try: + self._ele.run_js(f'this.style.{name}="{value}";') + except JavaScriptError: + raise ValueError(f'设置失败,请检查属性名{name}') + def innerHTML(self, html): """设置元素innerHTML :param html: html文本 diff --git a/DrissionPage/_units/setter.pyi b/DrissionPage/_units/setter.pyi index b0e6810..f371bf6 100644 --- a/DrissionPage/_units/setter.pyi +++ b/DrissionPage/_units/setter.pyi @@ -172,6 +172,8 @@ class ChromiumElementSetter(object): def property(self, name: str, value: str) -> None: ... + def style(self, name: str, value: str) -> None: ... + def innerHTML(self, html: str) -> None: ... def value(self, value: str) -> None: ... diff --git a/DrissionPage/_units/states.py b/DrissionPage/_units/states.py index a038624..755b27b 100644 --- a/DrissionPage/_units/states.py +++ b/DrissionPage/_units/states.py @@ -71,6 +71,11 @@ class ElementStates(object): except CDPError: return False + @property + def is_clickable(self): + """返回元素是否可被模拟点击,从是否有大小、是否可用、是否显示、是否响应点击判断,不判断是否被遮挡""" + return self.has_rect and self.is_enabled and self.is_displayed and self._ele.style('pointer-events') != 'none' + @property def has_rect(self): """返回元素是否拥有位置和大小,没有返回False,有返回四个角在页面中坐标组成的列表""" diff --git a/DrissionPage/_units/states.pyi b/DrissionPage/_units/states.pyi index 71a673b..99b5464 100644 --- a/DrissionPage/_units/states.pyi +++ b/DrissionPage/_units/states.pyi @@ -40,6 +40,9 @@ class ElementStates(object): @property def is_covered(self) -> Union[Literal[False], int]: ... + @property + def is_clickable(self) -> bool: ... + @property def has_rect(self) -> Union[bool, List[Tuple[float, float]]]: ... diff --git a/DrissionPage/_units/waiter.py b/DrissionPage/_units/waiter.py index 4e6e3c4..4c3d2d5 100644 --- a/DrissionPage/_units/waiter.py +++ b/DrissionPage/_units/waiter.py @@ -461,10 +461,10 @@ class ElementWaiter(OriginWaiter): else: return False - def stop_moving(self, gap=.1, timeout=None, raise_err=None): + def stop_moving(self, timeout=None, gap=.1, raise_err=None): """等待当前元素停止运动 - :param gap: 检测间隔时间 :param timeout: 超时时间,为None使用元素所在页面timeout属性 + :param gap: 检测间隔时间 :param raise_err: 等待失败时是否报错,为None时根据Settings设置 :return: 是否等待成功 """ @@ -494,6 +494,20 @@ class ElementWaiter(OriginWaiter): else: return False + def clickable(self, wait_moved=True, timeout=None, raise_err=None): + """等待当前元素可被点击 + :param wait_moved: 是否等待元素运动结束 + :param timeout: 超时时间,为None使用元素所在页面timeout属性 + :param raise_err: 等待失败时是否报错,为None时根据Settings设置 + :return: 是否等待成功 + """ + t1 = perf_counter() + r = self._wait_state('is_clickable', True, timeout, raise_err, err_text='等待元素可点击失败(等{}秒)。') + r = self.stop_moving(timeout=perf_counter() - t1) if wait_moved and r else r + if raise_err and not r: + raise WaitTimeoutError(f'等待元素可点击失败(等{timeout}秒)。') + return r + def has_rect(self, timeout=None, raise_err=None): """等待当前元素有大小及位置属性 :param timeout: 超时时间,为None使用元素所在页面timeout属性 @@ -505,7 +519,7 @@ class ElementWaiter(OriginWaiter): def _wait_state(self, attr, mode=False, timeout=None, raise_err=None, err_text=None): """等待元素某个元素状态到达指定状态 :param attr: 状态名称 - :param mode: True或False + :param mode: 等待True还是False :param timeout: 超时时间,为None使用元素所在页面timeout属性 :param raise_err: 等待失败时是否报错,为None时根据Settings设置 :param err_text: 抛出错误时显示的信息 diff --git a/DrissionPage/_units/waiter.pyi b/DrissionPage/_units/waiter.pyi index 4b96890..e891bb2 100644 --- a/DrissionPage/_units/waiter.pyi +++ b/DrissionPage/_units/waiter.pyi @@ -99,11 +99,13 @@ class ElementWaiter(OriginWaiter): def disabled(self, timeout: float = None, raise_err: bool = None) -> bool: ... + def clickable(self, wait_moved: bool = True, timeout: float = None, raise_err: bool = None) -> bool: ... + def has_rect(self, timeout: float = None, raise_err: bool = None) -> bool: ... def disabled_or_deleted(self, timeout: float = None, raise_err: bool = None) -> bool: ... - def stop_moving(self, gap: float = .1, timeout: float = None, raise_err: bool = None) -> bool: ... + def stop_moving(self, timeout: float = None, gap: float = .1, raise_err: bool = None) -> bool: ... def _wait_state(self, attr: str,