4.1.0.6(+)

DataPacket对象request增加params属性;
s_ele()补回timeout参数;
修复new_tab()无url时问题;
wait.has_rect()、wait.covered()成功时返回调用者;
元素列表切片时也返回列表对象
This commit is contained in:
g1879 2024-09-28 21:49:02 +08:00
parent cebee0a720
commit ecc82e69da
13 changed files with 73 additions and 43 deletions

View File

@ -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'

View File

@ -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})')

View File

@ -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(

View File

@ -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)

View File

@ -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]: ...

View File

@ -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:

View File

@ -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对象或属性文本组成的列表
"""
...

View File

@ -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:

View File

@ -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对象或属性文本组成的列表
"""
...

View File

@ -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:

View File

@ -279,6 +279,11 @@ class Request(object):
"""以大小写不敏感字典返回headers数据"""
...
@property
def params(self) -> dict:
"""dict格式返回请求url中的参数"""
...
@property
def postData(self) -> Any:
"""返回postData数据"""

View File

@ -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:

View File

@ -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设置