mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
4.0.4.13(+)
动作链wait()增加随机功能; latest_tab当tab设置为单例时返回Tab对象,否则返回tab id; 修复新标签页重复创建连接问题; 修复等待新tab不正确问题
This commit is contained in:
parent
4cbbf1dee1
commit
cfed80e196
@ -14,4 +14,4 @@ from ._configs.chromium_options import ChromiumOptions
|
||||
from ._configs.session_options import SessionOptions
|
||||
|
||||
__all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__']
|
||||
__version__ = '4.0.4.12'
|
||||
__version__ = '4.0.4.13'
|
||||
|
@ -72,7 +72,9 @@ class Browser(object):
|
||||
:param owner: 使用该驱动的对象
|
||||
:return: Driver对象
|
||||
"""
|
||||
d = self._drivers.pop(tab_id, Driver(tab_id, 'page', self.address))
|
||||
d = self._drivers.pop(tab_id, None)
|
||||
if not d:
|
||||
d = Driver(tab_id, 'page', self.address)
|
||||
d.owner = owner
|
||||
self._all_drivers.setdefault(tab_id, set()).add(d)
|
||||
return d
|
||||
@ -188,6 +190,30 @@ class Browser(object):
|
||||
"""
|
||||
return self.run_cdp('Browser.getWindowForTarget', targetId=tab_id or self.id)['bounds']
|
||||
|
||||
def new_tab(self, new_window=False, background=False, new_context=False):
|
||||
"""新建一个标签页
|
||||
:param new_window: 是否在新窗口打开标签页
|
||||
:param background: 是否不激活新标签页,如new_window为True则无效
|
||||
:param new_context: 是否创建新的上下文
|
||||
:return: 新标签页id
|
||||
"""
|
||||
bid = None
|
||||
if new_context:
|
||||
bid = self.run_cdp('Target.createBrowserContext')['browserContextId']
|
||||
|
||||
kwargs = {'url': ''}
|
||||
if new_window:
|
||||
kwargs['newWindow'] = True
|
||||
if background:
|
||||
kwargs['background'] = True
|
||||
if bid:
|
||||
kwargs['browserContextId'] = bid
|
||||
|
||||
tid = self.run_cdp('Target.createTarget', **kwargs)['targetId']
|
||||
while tid not in self._drivers:
|
||||
sleep(.1)
|
||||
return tid
|
||||
|
||||
def reconnect(self):
|
||||
"""断开重连"""
|
||||
self._driver.stop()
|
||||
|
@ -56,6 +56,8 @@ class Browser(object):
|
||||
|
||||
def get_window_bounds(self, tab_id: str = None) -> dict: ...
|
||||
|
||||
def new_tab(self, new_window: bool = False, background: bool = False, new_context: bool = False) -> str: ...
|
||||
|
||||
def reconnect(self) -> None: ...
|
||||
|
||||
def connect_to_page(self) -> None: ...
|
||||
|
@ -14,6 +14,7 @@ from requests import get
|
||||
from .._base.browser import Browser
|
||||
from .._configs.chromium_options import ChromiumOptions
|
||||
from .._functions.browser import connect_browser
|
||||
from .._functions.settings import Settings
|
||||
from .._functions.tools import PortFinder
|
||||
from .._pages.chromium_base import ChromiumBase, get_mhtml, get_pdf, Timeout
|
||||
from .._pages.chromium_tab import ChromiumTab
|
||||
@ -130,8 +131,9 @@ class ChromiumPage(ChromiumBase):
|
||||
|
||||
@property
|
||||
def latest_tab(self):
|
||||
"""返回最新的标签页对象,最新标签页指最后创建或最后被激活的"""
|
||||
return self.get_tab(self.tab_ids[0])
|
||||
"""返回最新的标签页,最新标签页指最后创建或最后被激活的
|
||||
当Settings.singleton_tab_obj==True时返回Tab对象,否则返回tab id"""
|
||||
return self.get_tab(self.tab_ids[0], as_id=not Settings.singleton_tab_obj)
|
||||
|
||||
@property
|
||||
def process_id(self):
|
||||
@ -163,7 +165,12 @@ class ChromiumPage(ChromiumBase):
|
||||
elif isinstance(id_or_num, int):
|
||||
id_or_num = self.tab_ids[id_or_num - 1 if id_or_num > 0 else id_or_num]
|
||||
elif isinstance(id_or_num, ChromiumTab):
|
||||
return id_or_num.tab_id if as_id else id_or_num
|
||||
if as_id:
|
||||
return id_or_num.tab_id
|
||||
elif Settings.singleton_tab_obj:
|
||||
return id_or_num
|
||||
else:
|
||||
return self.get_tab(id_or_num.tab_id)
|
||||
|
||||
elif title == url == tab_type is None:
|
||||
id_or_num = self.tab_id
|
||||
@ -202,32 +209,11 @@ class ChromiumPage(ChromiumBase):
|
||||
:param new_context: 是否创建新的上下文
|
||||
:return: 新标签页对象
|
||||
"""
|
||||
tab = ChromiumTab(self, tab_id=self._new_tab(new_window, background, new_context))
|
||||
tab = ChromiumTab(self, tab_id=self.browser.new_tab(new_window, background, new_context))
|
||||
if url:
|
||||
tab.get(url)
|
||||
return tab
|
||||
|
||||
def _new_tab(self, new_window=False, background=False, new_context=False):
|
||||
"""新建一个标签页
|
||||
:param new_window: 是否在新窗口打开标签页
|
||||
:param background: 是否不激活新标签页,如new_window为True则无效
|
||||
:param new_context: 是否创建新的上下文
|
||||
:return: 新标签页对象
|
||||
"""
|
||||
bid = None
|
||||
if new_context:
|
||||
bid = self.browser.run_cdp('Target.createBrowserContext')['browserContextId']
|
||||
|
||||
kwargs = {'url': ''}
|
||||
if new_window:
|
||||
kwargs['newWindow'] = True
|
||||
if background:
|
||||
kwargs['background'] = True
|
||||
if bid:
|
||||
kwargs['browserContextId'] = bid
|
||||
|
||||
return self.browser.run_cdp('Target.createTarget', **kwargs)['targetId']
|
||||
|
||||
def close(self):
|
||||
"""关闭Page管理的标签页"""
|
||||
self.close_tabs(self.tab_id)
|
||||
|
@ -57,7 +57,7 @@ class ChromiumPage(ChromiumBase):
|
||||
def wait(self) -> PageWaiter: ...
|
||||
|
||||
@property
|
||||
def latest_tab(self) -> Union[ChromiumTab, ChromiumPage]: ...
|
||||
def latest_tab(self) -> Union[ChromiumTab, ChromiumPage, str]: ...
|
||||
|
||||
@property
|
||||
def process_id(self) -> Optional[int]: ...
|
||||
@ -102,8 +102,6 @@ class ChromiumPage(ChromiumBase):
|
||||
def new_tab(self, url: str = None, new_window: bool = False, background: bool = False,
|
||||
new_context: bool = False) -> ChromiumTab: ...
|
||||
|
||||
def _new_tab(self, new_window: bool = False, background: bool = False, new_context: bool = False) -> str: ...
|
||||
|
||||
def close(self) -> None: ...
|
||||
|
||||
def close_tabs(self, tabs_or_ids: Union[str, ChromiumTab, List[Union[str, ChromiumTab]],
|
||||
|
@ -362,7 +362,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
|
||||
:param new_context: 是否创建新的上下文
|
||||
:return: 新标签页对象
|
||||
"""
|
||||
tab = WebPageTab(self, tab_id=self._new_tab(new_window, background, new_context))
|
||||
tab = WebPageTab(self, tab_id=self.browser.new_tab(new_window, background, new_context))
|
||||
if url:
|
||||
tab.get(url)
|
||||
return tab
|
||||
|
@ -298,10 +298,13 @@ class Actions:
|
||||
input_text_or_keys(self.owner, text)
|
||||
return self
|
||||
|
||||
def wait(self, second):
|
||||
"""等待若干秒"""
|
||||
sleep(second)
|
||||
return self
|
||||
def wait(self, second, scope=None):
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
self.owner.wait(second=second, scope=scope)
|
||||
|
||||
def _get_key_data(self, key, action):
|
||||
"""获取用于发送的按键信息
|
||||
|
@ -100,7 +100,7 @@ class Actions:
|
||||
|
||||
def input(self, text: Any) -> Actions: ...
|
||||
|
||||
def wait(self, second: float) -> Actions: ...
|
||||
def wait(self, second: float, scope: float = None) -> Actions: ...
|
||||
|
||||
def _get_key_data(self, key: str, action: str) -> dict: ...
|
||||
|
||||
|
@ -11,13 +11,7 @@ from .._functions.settings import Settings
|
||||
from ..errors import WaitTimeoutError, NoRectError
|
||||
|
||||
|
||||
class BaseWaiter(object):
|
||||
def __init__(self, page_or_ele):
|
||||
"""
|
||||
:param page_or_ele: 页面对象或元素对象
|
||||
"""
|
||||
self._driver = page_or_ele
|
||||
|
||||
class OriginWaiter(object):
|
||||
def __call__(self, second, scope=None):
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
@ -30,6 +24,14 @@ class BaseWaiter(object):
|
||||
from random import uniform
|
||||
sleep(uniform(second, scope))
|
||||
|
||||
|
||||
class BaseWaiter(OriginWaiter):
|
||||
def __init__(self, page_or_ele):
|
||||
"""
|
||||
:param page_or_ele: 页面对象或元素对象
|
||||
"""
|
||||
self._driver = page_or_ele
|
||||
|
||||
def ele_deleted(self, loc_or_ele, timeout=None, raise_err=None):
|
||||
"""等待元素从DOM中删除
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
@ -125,7 +127,7 @@ class BaseWaiter(object):
|
||||
:return: 成功返回任务对象,失败返回False
|
||||
"""
|
||||
if not self._driver.browser._dl_mgr._running:
|
||||
raise RuntimeError('使用下载管理功能前需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
raise RuntimeError('此功能需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
self._driver.browser._dl_mgr.set_flag(self._driver.tab_id, False if cancel_it else True)
|
||||
if timeout is None:
|
||||
timeout = self._driver.timeout
|
||||
@ -240,7 +242,7 @@ class TabWaiter(BaseWaiter):
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if not self._driver.browser._dl_mgr._running:
|
||||
raise RuntimeError('使用下载管理功能前需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
raise RuntimeError('此功能需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
if not timeout:
|
||||
while self._driver.browser._dl_mgr.get_tab_missions(self._driver.tab_id):
|
||||
sleep(.5)
|
||||
@ -282,9 +284,9 @@ class PageWaiter(TabWaiter):
|
||||
timeout = timeout if timeout is not None else self._driver.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
while perf_counter() < end_time:
|
||||
latest_tab = self._driver.latest_tab
|
||||
if self._driver.tab_id != latest_tab:
|
||||
return latest_tab
|
||||
latest_tid = self._driver.tab_ids[0]
|
||||
if self._driver.tab_id != latest_tid:
|
||||
return latest_tid
|
||||
sleep(.01)
|
||||
|
||||
if raise_err is True or Settings.raise_when_wait_failed is True:
|
||||
@ -299,7 +301,7 @@ class PageWaiter(TabWaiter):
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if not self._driver.browser._dl_mgr._running:
|
||||
raise RuntimeError('使用下载管理功能前需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
raise RuntimeError('此功能需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
if not timeout:
|
||||
while self._driver.browser._dl_mgr._missions:
|
||||
sleep(.5)
|
||||
@ -321,7 +323,7 @@ class PageWaiter(TabWaiter):
|
||||
return True
|
||||
|
||||
|
||||
class ElementWaiter(object):
|
||||
class ElementWaiter(OriginWaiter):
|
||||
"""等待元素在dom中某种状态,如删除、显示、隐藏"""
|
||||
|
||||
def __init__(self, owner, ele):
|
||||
@ -332,18 +334,6 @@ class ElementWaiter(object):
|
||||
self._owner = owner
|
||||
self._ele = ele
|
||||
|
||||
def __call__(self, second, scope=None):
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
if scope is None:
|
||||
sleep(second)
|
||||
else:
|
||||
from random import uniform
|
||||
sleep(uniform(second, scope))
|
||||
|
||||
def deleted(self, timeout=None, raise_err=None):
|
||||
"""等待元素从dom删除
|
||||
:param timeout: 超时时间,为None使用元素所在页面timeout属性
|
||||
@ -457,7 +447,7 @@ class ElementWaiter(object):
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._wait_state('has_rect', True, timeout, raise_err, err_text='等待元素拥有大小及位置属性失败(等待{}秒)。')
|
||||
return self._wait_state('has_rect', True, timeout, raise_err, err_text='等待元素拥有大小及位置失败(等{}秒)。')
|
||||
|
||||
def _wait_state(self, attr, mode=False, timeout=None, raise_err=None, err_text=None):
|
||||
"""等待元素某个元素状态到达指定状态
|
||||
|
@ -14,7 +14,11 @@ from .._pages.chromium_frame import ChromiumFrame
|
||||
from .._pages.chromium_page import ChromiumPage
|
||||
|
||||
|
||||
class BaseWaiter(object):
|
||||
class OriginWaiter(object):
|
||||
def __call__(self, second: float, scope: float = None) -> None: ...
|
||||
|
||||
|
||||
class BaseWaiter(OriginWaiter):
|
||||
def __init__(self, page: ChromiumBase):
|
||||
self._driver: ChromiumBase = ...
|
||||
|
||||
@ -73,7 +77,7 @@ class PageWaiter(TabWaiter):
|
||||
def all_downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool: ...
|
||||
|
||||
|
||||
class ElementWaiter(object):
|
||||
class ElementWaiter(OriginWaiter):
|
||||
def __init__(self, owner: ChromiumBase, ele: ChromiumElement):
|
||||
self._ele: ChromiumElement = ...
|
||||
self._owner: ChromiumBase = ...
|
||||
|
Loading…
x
Reference in New Issue
Block a user