wait_ele()和scroll_to_see()弃用,整合到wait和scroll属性,待测试

This commit is contained in:
g1879 2023-02-12 23:07:26 +08:00
parent 82ac13fe16
commit 2c0595e57a
7 changed files with 227 additions and 79 deletions

View File

@ -37,7 +37,7 @@ class ActionChains:
ly = ele_or_loc[1] + offset_y
elif isinstance(ele_or_loc, str) or 'ChromiumElement' in str(type(ele_or_loc)):
ele_or_loc = self.page(ele_or_loc)
self.page.scroll_to_see(ele_or_loc)
self.page.scroll.to_see(ele_or_loc)
x, y = ele_or_loc.location if offset_x or offset_y else ele_or_loc.midpoint
lx = x + offset_x
ly = y + offset_y

View File

@ -6,13 +6,15 @@
from json import loads
from pathlib import Path
from time import perf_counter, sleep
from warnings import warn
from requests import Session
from .functions.tools import get_usable_path
from .base import BasePage
from .chromium_driver import ChromiumDriver
from .chromium_element import ChromiumElementWaiter, ChromiumScroll, ChromiumElement, run_js, make_chromium_ele
from .chromium_element import ChromiumWaiter, ChromiumScroll, ChromiumElement, run_js, make_chromium_ele, \
ChromiumElementWaiter
from .functions.locator import get_loc
from .functions.web import offset_scroll, cookies_to_tuple
from .session_element import make_session_ele
@ -306,9 +308,9 @@ class ChromiumBase(BasePage):
@property
def scroll(self):
"""返回用于滚动滚动条的对象"""
self._wait_loaded()
self.wait.load_complete() # todo: 用run_js()负责等待,这里删除
if not hasattr(self, '_scroll'):
self._scroll = ChromiumScroll(self)
self._scroll = ChromiumPageScroll(self)
return self._scroll
@property
@ -326,6 +328,11 @@ class ChromiumBase(BasePage):
"""返回等待上传文件列表"""
return self._upload_list
@property
def wait(self):
"""返回用于等待的对象"""
return ChromiumPageWaiter(self)
def set_timeouts(self, implicit=None, page_load=None, script=None):
"""设置超时时间,单位为秒
:param implicit: 查找元素超时时间
@ -378,20 +385,6 @@ class ChromiumBase(BasePage):
timeout=timeout)
return self._url_available
def wait_loading(self, timeout=None):
"""阻塞程序,等待页面进入加载状态
:param timeout: 超时时间
:return: 等待结束时是否进入加载状态
"""
if timeout != 0:
timeout = self.timeout if timeout in (None, True) else timeout
end_time = perf_counter() + timeout
while perf_counter() < end_time:
if self.is_loading:
return True
sleep(.005)
return False
def get_cookies(self, as_dict=False):
"""获取cookies信息
:param as_dict: 为True时返回由{name: value}键值对组成的dict
@ -503,29 +496,6 @@ class ChromiumBase(BasePage):
else:
return [make_chromium_ele(self, node_id=i) for i in nodeIds['nodeIds']]
def wait_ele(self, loc_or_ele, timeout=None):
"""返回用于等待元素到达某个状态的等待器对象
:param loc_or_ele: 可以是元素查询字符串loc元组
:param timeout: 等待超时时间
:return: 用于等待的ElementWaiter对象
"""
return ChromiumElementWaiter(self, loc_or_ele, timeout)
def scroll_to_see(self, loc_or_ele):
"""滚动页面直到元素可见
:param loc_or_ele: 元素的定位信息可以是loc元组或查询字符串详见ele函数注释
:return: None
"""
ele = self.ele(loc_or_ele)
node_id = ele.node_id
try:
self._wait_driver.DOM.scrollIntoViewIfNeeded(nodeId=node_id)
except Exception:
self.ele(loc_or_ele).run_js("this.scrollIntoView();")
if not ele.is_in_viewport:
offset_scroll(ele, 0, 0)
def refresh(self, ignore_cache=False):
"""刷新当前页面
:param ignore_cache: 是否忽略缓存
@ -533,7 +503,7 @@ class ChromiumBase(BasePage):
"""
self._is_loading = True
self.driver.Page.reload(ignoreCache=ignore_cache)
self.wait_loading()
self.wait.load_start()
def forward(self, steps=1):
"""在浏览历史中前进若干步
@ -597,7 +567,7 @@ class ChromiumBase(BasePage):
return r
if 'Cannot find context with specified id' in r['error']:
raise RuntimeError('页面被刷新,请操作前尝试等待页面刷新或加载完成可尝试wait.load_complete()方法')
raise RuntimeError('页面被刷新,请操作前尝试等待页面刷新或加载完成')
elif 'Could not find node with given id' in r['error']:
raise RuntimeError('该元素已不在当前页面中。')
elif 'tab closed' in r['error']:
@ -764,6 +734,93 @@ class ChromiumBase(BasePage):
return True
def wait_loading(self, timeout=None):
"""阻塞程序,等待页面进入加载状态
:param timeout: 超时时间
:return: 等待结束时是否进入加载状态
"""
warn("此方法即将弃用请用wait.load_start()方法代替。", DeprecationWarning)
return self.wait.load_start(timeout)
def wait_ele(self, loc_or_ele, timeout=None):
"""返回用于等待元素到达某个状态的等待器对象
:param loc_or_ele: 可以是元素查询字符串loc元组
:param timeout: 等待超时时间
:return: 用于等待的ElementWaiter对象
"""
warn("此方法即将弃用请用wait.ele_xxxx()方法代替。", DeprecationWarning)
return ChromiumElementWaiter(self, loc_or_ele, timeout)
def scroll_to_see(self, loc_or_ele):
"""滚动页面直到元素可见
:param loc_or_ele: 元素的定位信息可以是loc元组或查询字符串详见ele函数注释
:return: None
"""
warn("此方法即将弃用请用scroll.to_see()方法代替。", DeprecationWarning)
self.scroll.to_see(loc_or_ele)
class ChromiumPageWaiter(ChromiumWaiter):
def __init__(self, page):
"""
:param page: 所属页面对象
"""
super().__init__(page)
def _loading(self, timeout=None, start=True):
"""等待页面开始加载或加载完成
:param timeout: 超时时间为None时使用页面timeout属性
:param start: 等待开始还是结束
:return: 是否等待成功
"""
if timeout != 0:
timeout = self._driver.timeout if timeout in (None, True) else timeout
end_time = perf_counter() + timeout
while perf_counter() < end_time:
if self._driver.is_loading == start:
return True
sleep(.005)
return False
def load_start(self, timeout=None):
"""等待页面开始加载
:param timeout: 超时时间为None时使用页面timeout属性
:return: 是否等待成功
"""
return self._loading(timeout=timeout)
def load_complete(self, timeout=None):
"""等待页面开始加载
:param timeout: 超时时间为None时使用页面timeout属性
:return: 是否等待成功
"""
return self._loading(timeout=timeout, start=False)
class ChromiumPageScroll(ChromiumScroll):
def __init__(self, page):
"""
:param page: 页面对象
"""
super().__init__(page)
self.t1 = 'window'
self.t2 = 'document.documentElement'
def to_see(self, loc_or_ele):
"""滚动页面直到元素可见
:param loc_or_ele: 元素的定位信息可以是loc元组或查询字符串
:return: None
"""
ele = self._driver.ele(loc_or_ele)
node_id = ele.node_id
try:
self._driver._wait_driver.DOM.scrollIntoViewIfNeeded(nodeId=node_id)
except Exception:
ele.run_js("this.scrollIntoView();")
if not ele.is_in_viewport:
offset_scroll(ele, 0, 0)
class Timeout(object):
"""用于保存d模式timeout信息的类"""

View File

@ -12,7 +12,7 @@ from requests.cookies import RequestsCookieJar
from .base import BasePage
from .chromium_driver import ChromiumDriver
from .chromium_element import ChromiumElement, ChromiumElementWaiter, ChromiumScroll
from .chromium_element import ChromiumElement, ChromiumScroll, ChromiumElementWaiter, ChromiumWaiter
from .chromium_frame import ChromiumFrame
from .session_element import SessionElement
@ -109,7 +109,7 @@ class ChromiumBase(BasePage):
def page_load_strategy(self) -> str: ...
@property
def scroll(self) -> ChromiumScroll: ...
def scroll(self) -> ChromiumPageScroll: ...
@property
def timeouts(self) -> Timeout: ...
@ -120,6 +120,9 @@ class ChromiumBase(BasePage):
@property
def upload_list(self) -> list: ...
@property
def wait(self) -> ChromiumPageWaiter: ...
def set_timeouts(self, implicit: float = None, page_load: float = None, script: float = None) -> None: ...
def run_js(self, script: str, as_expr: bool = False, *args: Any) -> Any: ...
@ -133,7 +136,7 @@ class ChromiumBase(BasePage):
interval: float = None,
timeout: float = None) -> Union[None, bool]: ...
def wait_loading(self, timeout: float = 1) -> bool: ...
def wait_loading(self, timeout: float = None) -> bool: ...
def get_cookies(self, as_dict: bool = False) -> Union[list, dict]: ...
@ -161,7 +164,7 @@ class ChromiumBase(BasePage):
def wait_ele(self,
loc_or_ele: Union[str, tuple, ChromiumElement],
timeout: float = None) -> 'ChromiumElementWaiter': ...
timeout: float = None) -> ChromiumElementWaiter: ...
def scroll_to_see(self, loc_or_ele: Union[str, tuple, ChromiumElement]) -> None: ...
@ -207,6 +210,23 @@ class ChromiumBase(BasePage):
timeout: float = None) -> Union[bool, None]: ...
class ChromiumPageWaiter(ChromiumWaiter):
def __init__(self, page: ChromiumBase):
self._driver: ChromiumBase = ...
def _loading(self, timeout: Union[int, float] = None, start: bool = True) -> bool: ...
def load_start(self, timeout: Union[int, float] = None) -> bool: ...
def load_complete(self, timeout: Union[int, float] = None) -> bool: ...
class ChromiumPageScroll(ChromiumScroll):
def __init__(self, page: ChromiumBase): ...
def to_see(self, loc_or_ele: Union[str, tuple, ChromiumElement]) -> None: ...
class Timeout(object):
def __init__(self, page: ChromiumBase, implicit=None, page_load=None, script=None):

View File

@ -7,6 +7,7 @@ from os import sep
from os.path import basename
from pathlib import Path
from time import perf_counter, sleep
from warnings import warn
from .base import DrissionElement, BaseElement
from .functions.locator import get_loc
@ -270,13 +271,10 @@ class ChromiumElement(DrissionElement):
"""
return super().afters(filter_loc, timeout)
def wait_ele(self, loc_or_ele, timeout=None):
"""返回用于等待子元素到达某个状态的等待器对象
:param loc_or_ele: 可以是元素查询字符串loc元组
:param timeout: 等待超时时间
:return: 用于等待的ElementWaiter对象
"""
return ChromiumElementWaiter(self, loc_or_ele, timeout)
@property
def wait(self):
"""返回用于等待的对象"""
return ChromiumWaiter(self)
@property
def select(self):
@ -617,7 +615,7 @@ class ChromiumElement(DrissionElement):
return True
if not by_js:
self.page.scroll_to_see(self)
self.page.scroll.to_see(self)
if self.is_in_viewport:
client_x, client_y = self._client_click_point
if client_x:
@ -625,7 +623,7 @@ class ChromiumElement(DrissionElement):
click = do_it(client_x, client_y, loc_x, loc_y)
if click:
self.page.wait_loading(wait_loading)
self.page.wait.load_start(wait_loading)
return True
timeout = timeout if timeout is not None else self.page.timeout
@ -634,12 +632,12 @@ class ChromiumElement(DrissionElement):
click = do_it(client_x, client_y, loc_x, loc_y)
if click is not None:
self.page.wait_loading(wait_loading)
self.page.wait.load_start(wait_loading)
return True
if by_js is not False:
self.run_js('this.click();')
self.page.wait_loading(wait_loading)
self.page.wait.load_start(wait_loading)
return True
return False
@ -651,13 +649,13 @@ class ChromiumElement(DrissionElement):
:param button: 左键还是右键
:return: None
"""
self.page.scroll_to_see(self)
self.page.scroll.to_see(self)
x, y = offset_scroll(self, offset_x, offset_y)
self._click(x, y, button)
def r_click(self):
"""右键单击"""
self.page.scroll_to_see(self)
self.page.scroll.to_see(self)
x, y = self._client_click_point
self._click(x, y, 'right')
@ -671,7 +669,7 @@ class ChromiumElement(DrissionElement):
def m_click(self):
"""中键单击"""
self.page.scroll_to_see(self)
self.page.scroll.to_see(self)
x, y = self._client_click_point
self._click(x, y, 'middle')
@ -693,7 +691,7 @@ class ChromiumElement(DrissionElement):
:param offset_y: 相对元素左上角坐标的y轴偏移量
:return: None
"""
self.page.scroll_to_see(self)
self.page.scroll.to_see(self)
x, y = offset_scroll(self, offset_x, offset_y)
self.page.driver.Input.dispatchMouseEvent(type='mouseMoved', x=x, y=y)
@ -835,6 +833,15 @@ class ChromiumElement(DrissionElement):
sx, sy = xy.split(' ')
return int(x + float(sx)), int(y + float(sy))
def wait_ele(self, loc_or_ele, timeout=None):
"""返回用于等待子元素到达某个状态的等待器对象
:param loc_or_ele: 可以是元素查询字符串loc元组
:param timeout: 等待超时时间
:return: 用于等待的ElementWaiter对象
"""
warn("此方法即将弃用请用wait.ele_xxxx()方法代替。", DeprecationWarning)
return ChromiumElementWaiter(self, loc_or_ele, timeout)
class ChromiumShadowRootElement(BaseElement):
"""ChromiumShadowRootElement是用于处理ShadowRoot的类使用方法和ChromiumElement基本一致"""
@ -1395,19 +1402,12 @@ def _send_key(ele, modifier, key):
class ChromiumScroll(object):
"""用于滚动的对象"""
def __init__(self, page_or_ele):
def __init__(self, ele):
"""
:param page_or_ele: 页面对象元素对象或frame对象
:param ele: 元素对象
"""
self._driver = page_or_ele
if isinstance(page_or_ele, ChromiumElement):
self.t1 = self.t2 = 'this'
elif 'ChromiumFrame' in str(type(page_or_ele)):
self._driver = page_or_ele.doc_ele
self.t1 = self.t2 = 'this.documentElement'
else:
self.t1 = 'window'
self.t2 = 'document.documentElement'
self._driver = ele
self.t1 = self.t2 = 'this'
def _run_js(self, js):
js = js.format(self.t1, self.t2, self.t2)
@ -1660,6 +1660,38 @@ class ChromiumSelect(object):
return success
class ChromiumWaiter(object):
def __init__(self, page_or_ele):
"""
:param page_or_ele: 页面对象或元素对象
"""
self._driver = page_or_ele
def ele_delete(self, loc_or_ele, timeout=None):
"""
:param loc_or_ele: 要等待的元素可以是已有元素定位符
:param timeout: 超时时间默认读取页面超时时间
:return: 是否等待成功
"""
return ChromiumElementWaiter(self._driver, loc_or_ele, timeout).delete()
def ele_display(self, loc_or_ele, timeout=None):
"""
:param loc_or_ele: 要等待的元素可以是已有元素定位符
:param timeout: 超时时间默认读取页面超时时间
:return: 是否等待成功
"""
return ChromiumElementWaiter(self._driver, loc_or_ele, timeout).display()
def ele_hidden(self, loc_or_ele, timeout=None):
"""
:param loc_or_ele: 要等待的元素可以是已有元素定位符
:param timeout: 超时时间默认读取页面超时时间
:return: 是否等待成功
"""
return ChromiumElementWaiter(self._driver, loc_or_ele, timeout).hidden()
class ChromiumElementWaiter(object):
"""等待元素在dom中某种状态如删除、显示、隐藏"""
@ -1693,7 +1725,7 @@ class ChromiumElementWaiter(object):
end_time = perf_counter() + self.timeout
while perf_counter() < end_time:
if not self.loc_or_ele.is_alive:
if not ele.is_alive:
return True
return False

View File

@ -141,7 +141,10 @@ class ChromiumElement(DrissionElement):
def wait_ele(self,
loc_or_ele: Union[str, tuple, ChromiumElement],
timeout: float = None) -> ChromiumElementWaiter: ...
timeout: float = None) -> ChromiumWaiter: ...
@property
def wait(self) -> ChromiumWaiter: ...
@property
def select(self) -> ChromiumSelect: ...
@ -455,12 +458,24 @@ class ChromiumSelect(object):
deselect: bool = False) -> bool: ...
class ChromiumWaiter(object):
def __init__(self, page_or_ele):
self._driver: Union[ChromiumBase, ChromiumElement] = ...
def ele_delete(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: Union[int, float] = None) -> bool: ...
def ele_display(self, loc_or_ele: Union[str, tuple, ChromiumElement],
timeout: Union[int, float] = None) -> bool: ...
def ele_hidden(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: Union[int, float] = None) -> bool: ...
class ChromiumElementWaiter(object):
def __init__(self,
page_or_ele: Union[ChromiumBase, ChromiumElement],
loc_or_ele: Union[str, tuple, ChromiumElement],
timeout: float = None):
timeout: Union[int, float] = None):
self.loc_or_ele: Union[str, tuple, ChromiumElement] = ...
self.timeout: float = ...
self.driver: Union[ChromiumPage, ChromiumPage] = ...

View File

@ -6,7 +6,7 @@
from re import search
from time import sleep
from .chromium_base import ChromiumBase
from .chromium_base import ChromiumBase, ChromiumPageScroll
from .chromium_element import ChromiumElement
@ -259,6 +259,11 @@ class ChromiumFrame(ChromiumBase):
except:
pass
@property
def scroll(self):
"""返回用于等待的对象"""
return ChromiumFrameScroll(self)
def refresh(self):
"""刷新frame页面"""
self._check_ok()
@ -445,3 +450,12 @@ class ChromiumFrame(ChromiumBase):
def _is_inner_frame(self):
"""返回当前frame是否同域"""
return self.frame_id in str(self.page.run_cdp('Page.getFrameTree')['frameTree'])
class ChromiumFrameScroll(ChromiumPageScroll):
def __init__(self, frame):
"""
:param frame: ChromiumFrame对象
"""
self._driver = frame.doc_ele
self.t1 = self.t2 = 'this.documentElement'

View File

@ -5,8 +5,8 @@
"""
from typing import Union, Tuple, List, Any
from .chromium_element import ChromiumElement
from .chromium_base import ChromiumBase
from .chromium_element import ChromiumElement, ChromiumScroll
from .chromium_base import ChromiumBase, ChromiumPageScroll
class ChromiumFrame(ChromiumBase):
@ -99,6 +99,12 @@ class ChromiumFrame(ChromiumBase):
@property
def css_path(self) -> str: ...
@property
def ready_state(self) -> str: ...
@property
def scroll(self) -> ChromiumFrameScroll: ...
def refresh(self) -> None: ...
def attr(self, attr: str) -> Union[str, None]: ...
@ -160,3 +166,7 @@ class ChromiumFrame(ChromiumBase):
timeout: float = None) -> Union[bool, None]: ...
def _is_inner_frame(self) -> bool: ...
class ChromiumFrameScroll(ChromiumPageScroll):
def __init__(self, frame: ChromiumFrame) -> None: ...