增加视觉相对定位,未完成;wait.has_rect()和wait.covered()返回信息

This commit is contained in:
g1879 2024-06-18 18:09:08 +08:00
parent dc5eae65ec
commit fa9e2ae7d7
5 changed files with 56 additions and 9 deletions

View File

@ -27,7 +27,8 @@ from .._units.selector import SelectElement
from .._units.setter import ChromiumElementSetter
from .._units.states import ElementStates, ShadowRootStates
from .._units.waiter import ElementWaiter
from ..errors import ContextLostError, ElementLostError, JavaScriptError, CDPError, NoResourceError, AlertExistsError
from ..errors import ContextLostError, ElementLostError, JavaScriptError, CDPError, NoResourceError, AlertExistsError, \
NoRectError
__FRAME_ELEMENT__ = ('iframe', 'frame')
@ -346,6 +347,34 @@ class ChromiumElement(DrissionElement):
"""
return super().afters(locator, timeout, ele_only=ele_only)
def on(self, timeout=None):
"""获取覆盖在本元素上最上层的元素
:param timeout: 等待元素出现的超时时间
:return: 元素对象
"""
timeout = timeout if timeout is None else self.owner.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})
def under(self, locator=None):
rect = self.states.has_rect
if not rect:
raise NoRectError
y = int(rect[2][1])
x = int(self.rect.midpoint[0])
while True:
y += 1
try:
ele = self.owner.run_cdp('DOM.getNodeForLocation', x=x, y=y)
break
except:
raise
continue
return ChromiumElement(owner=self.owner, backend_id=ele['backendNodeId'])
def attr(self, attr):
"""返回一个attribute属性值
:param attr: 属性名

View File

@ -161,6 +161,18 @@ class ChromiumElement(DrissionElement):
timeout: float = None,
ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ...
def on(self, timeout: float = None) -> ChromiumElement: ...
def under(self, locator: str = None) -> ChromiumElement: ...
def above(self, locator: str = None) -> ChromiumElement: ...
def left(self, locator: str = None) -> ChromiumElement: ...
def right(self, locator: str = None) -> ChromiumElement: ...
def offset(self, offset_x, offset_y) -> ChromiumElement: ...
@property
def wait(self) -> ElementWaiter: ...

View File

@ -44,7 +44,7 @@ class ElementStates(object):
def is_clickable(self) -> bool: ...
@property
def has_rect(self) -> Union[bool, List[Tuple[float, float]]]: ...
def has_rect(self) -> Union[Literal[False], List[Tuple[float, float]]]: ...
class ShadowRootStates(object):

View File

@ -382,7 +382,7 @@ class ElementWaiter(OriginWaiter):
"""等待当前元素被遮盖
:param timeout: 超时时间为None使用元素所在页面timeout属性
:param raise_err: 等待失败时是否报错为None时根据Settings设置
:return: 是否等待成功
:return: 成功返回覆盖元素id返回False
"""
return self._wait_state('is_covered', True, timeout, raise_err, err_text='等待元素被覆盖失败。')
@ -480,7 +480,7 @@ class ElementWaiter(OriginWaiter):
"""等待当前元素有大小及位置属性
:param timeout: 超时时间为None使用元素所在页面timeout属性
:param raise_err: 等待失败时是否报错为None时根据Settings设置
:return: 是否等待成功
:return: 成功返回元素四角坐标左上 右上 右下 左下失败返回False
"""
return self._wait_state('has_rect', True, timeout, raise_err, err_text='等待元素拥有大小及位置失败(等{}秒)。')
@ -493,16 +493,20 @@ class ElementWaiter(OriginWaiter):
:param err_text: 抛出错误时显示的信息
:return: 是否等待成功
"""
err_text = err_text or '等待元素状态改变失败(等待{}秒)。'
a = self._ele.states.__getattribute__(attr)
if (a and mode) or (not a and not mode):
return a
if timeout is None:
timeout = self._owner.timeout
end_time = perf_counter() + timeout
while perf_counter() < end_time:
a = self._ele.states.__getattribute__(attr)
if (a and mode) or (not a and not mode):
return True
return a
sleep(.05)
err_text = err_text or '等待元素状态改变失败(等待{}秒)。'
if raise_err is True or Settings.raise_when_wait_failed is True:
raise WaitTimeoutError(err_text.format(timeout))
else:

View File

@ -5,7 +5,7 @@
@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved.
@License : BSD 3-Clause.
"""
from typing import Union, Tuple
from typing import Union, Tuple, Literal, List
from .downloader import DownloadMission
from .._elements.chromium_element import ChromiumElement
@ -91,7 +91,7 @@ class ElementWaiter(OriginWaiter):
def hidden(self, timeout: float = None, raise_err: bool = None) -> bool: ...
def covered(self, timeout: float = None, raise_err: bool = None) -> bool: ...
def covered(self, timeout: float = None, raise_err: bool = None) -> Union[Literal[False], int]: ...
def not_covered(self, timeout: float = None, raise_err: bool = None) -> bool: ...
@ -101,7 +101,9 @@ class ElementWaiter(OriginWaiter):
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 has_rect(self,
timeout: float = None,
raise_err: bool = None) -> Union[Literal[False], List[Tuple[float, float]]]: ...
def disabled_or_deleted(self, timeout: float = None, raise_err: bool = None) -> bool: ...