tab也有hide()和show();_units的_page改成_owner

This commit is contained in:
g1879 2024-03-07 00:19:33 +08:00
parent f434381d09
commit 51c8471fb5
22 changed files with 242 additions and 249 deletions

View File

@ -505,11 +505,12 @@ class ChromiumElement(DrissionElement):
sleep(.1) sleep(.1)
src = self.attr('src') src = self.attr('src')
if not src:
raise RuntimeError('元素没有src值或该值为空。')
if src.lower().startswith('data:image'): if src.lower().startswith('data:image'):
if base64_to_bytes: if base64_to_bytes:
from base64 import b64decode from base64 import b64decode
return b64decode(src.split(',', 1)[-1]) return b64decode(src.split(',', 1)[-1])
else: else:
return src.split(',', 1)[-1] return src.split(',', 1)[-1]

View File

@ -107,7 +107,7 @@ def show_or_hide_browser(page, hide=True):
except ImportError: except ImportError:
raise ImportError('请先安装pip install pypiwin32') raise ImportError('请先安装pip install pypiwin32')
pid = page.process_id pid = page._page.process_id
if not pid: if not pid:
return None return None
hds = get_hwnds_from_pid(pid, page.title) hds = get_hwnds_from_pid(pid, page.title)

View File

@ -10,7 +10,7 @@ from pathlib import Path
from threading import Lock from threading import Lock
from typing import Union, Tuple from typing import Union, Tuple
from .._pages.chromium_page import ChromiumPage from .._pages.chromium_base import ChromiumBase
class PortFinder(object): class PortFinder(object):
@ -30,7 +30,7 @@ def port_is_using(ip: str, port: Union[str, int]) -> bool: ...
def clean_folder(folder_path: Union[str, Path], ignore: Union[tuple, list] = None) -> None: ... def clean_folder(folder_path: Union[str, Path], ignore: Union[tuple, list] = None) -> None: ...
def show_or_hide_browser(page: ChromiumPage, hide: bool = True) -> None: ... def show_or_hide_browser(page: ChromiumBase, hide: bool = True) -> None: ...
def get_browser_progress_id(progress: Union[popen, None], address: str) -> Union[str, None]: ... def get_browser_progress_id(progress: Union[popen, None], address: str) -> Union[str, None]: ...

View File

@ -31,7 +31,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
"""初始化函数 """初始化函数
:param mode: 'd' 's'即driver模式和session模式 :param mode: 'd' 's'即driver模式和session模式
:param timeout: 超时时间d模式时为寻找元素时间s模式时为连接时间默认10秒 :param timeout: 超时时间d模式时为寻找元素时间s模式时为连接时间默认10秒
:param chromium_options: Driver对象只使用s模式时应传入False :param chromium_options: ChromiumOptions对象只使用s模式时应传入False
:param session_or_options: Session对象或SessionOptions对象只使用d模式时应传入False :param session_or_options: Session对象或SessionOptions对象只使用d模式时应传入False
""" """
if hasattr(self, '_created'): if hasattr(self, '_created'):

View File

@ -184,17 +184,6 @@ class Clicker(object):
raise RuntimeError('没有出现新标签页。') raise RuntimeError('没有出现新标签页。')
return self._ele.page.get_tab(tid) return self._ele.page.get_tab(tid)
def for_new_tab(self, by_js=False):
"""点击后等待新tab出现并返回其对象
:param by_js: 是否使用js点击逻辑与click()一致
:return: 新标签页对象如果没有等到新标签页出现则抛出异常
"""
self.left(by_js=by_js)
tid = self._ele.page._page.wait.new_tab()
if not tid:
raise RuntimeError('没有出现新标签页。')
return self._ele.page._page.get_tab(tid)
def _click(self, client_x, client_y, button='left', count=1): def _click(self, client_x, client_y, button='left', count=1):
"""实施点击 """实施点击
:param client_x: 视口中的x坐标 :param client_x: 视口中的x坐标

View File

@ -11,8 +11,11 @@ from .._functions.web import set_browser_cookies, set_session_cookies
class CookiesSetter(object): class CookiesSetter(object):
def __init__(self, page): def __init__(self, owner):
self._page = page """
:param owner: ChromiumBase对象
"""
self._owner = owner
def __call__(self, cookies): def __call__(self, cookies):
"""设置一个或多个cookie """设置一个或多个cookie
@ -21,7 +24,7 @@ class CookiesSetter(object):
""" """
if (isinstance(cookies, dict) and 'name' in cookies and 'value' in cookies) or isinstance(cookies, Cookie): if (isinstance(cookies, dict) and 'name' in cookies and 'value' in cookies) or isinstance(cookies, Cookie):
cookies = [cookies] cookies = [cookies]
set_browser_cookies(self._page, cookies) set_browser_cookies(self._owner, cookies)
def remove(self, name, url=None, domain=None, path=None): def remove(self, name, url=None, domain=None, path=None):
"""删除一个cookie """删除一个cookie
@ -36,18 +39,20 @@ class CookiesSetter(object):
d['url'] = url d['url'] = url
if domain is not None: if domain is not None:
d['domain'] = domain d['domain'] = domain
if not url and not domain:
d['url'] = self._owner.url
if path is not None: if path is not None:
d['path'] = path d['path'] = path
self._page.run_cdp('Network.deleteCookies', **d) self._owner.run_cdp('Network.deleteCookies', **d)
def clear(self): def clear(self):
"""清除cookies""" """清除cookies"""
self._page.run_cdp('Network.clearBrowserCookies') self._owner.run_cdp('Network.clearBrowserCookies')
class SessionCookiesSetter(object): class SessionCookiesSetter(object):
def __init__(self, page): def __init__(self, owner):
self._page = page self._owner = owner
def __call__(self, cookies): def __call__(self, cookies):
"""设置多个cookie注意不要传入单个 """设置多个cookie注意不要传入单个
@ -56,18 +61,18 @@ class SessionCookiesSetter(object):
""" """
if (isinstance(cookies, dict) and 'name' in cookies and 'value' in cookies) or isinstance(cookies, Cookie): if (isinstance(cookies, dict) and 'name' in cookies and 'value' in cookies) or isinstance(cookies, Cookie):
cookies = [cookies] cookies = [cookies]
set_session_cookies(self._page.session, cookies) set_session_cookies(self._owner.session, cookies)
def remove(self, name): def remove(self, name):
"""删除一个cookie """删除一个cookie
:param name: cookie的name字段 :param name: cookie的name字段
:return: None :return: None
""" """
self._page.session.cookies.set(name, None) self._owner.session.cookies.set(name, None)
def clear(self): def clear(self):
"""清除cookies""" """清除cookies"""
self._page.session.cookies.clear() self._owner.session.cookies.clear()
class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter): class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
@ -77,9 +82,9 @@ class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
:param cookies: cookies信息 :param cookies: cookies信息
:return: None :return: None
""" """
if self._page.mode == 'd' and self._page._has_driver: if self._owner.mode == 'd' and self._owner._has_driver:
super().__call__(cookies) super().__call__(cookies)
elif self._page.mode == 's' and self._page._has_session: elif self._owner.mode == 's' and self._owner._has_session:
super(CookiesSetter, self).__call__(cookies) super(CookiesSetter, self).__call__(cookies)
def remove(self, name, url=None, domain=None, path=None): def remove(self, name, url=None, domain=None, path=None):
@ -90,16 +95,16 @@ class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
:param path: cookie的path字段可选d模式时才有效 :param path: cookie的path字段可选d模式时才有效
:return: None :return: None
""" """
if self._page.mode == 'd' and self._page._has_driver: if self._owner.mode == 'd' and self._owner._has_driver:
super().remove(name, url, domain, path) super().remove(name, url, domain, path)
elif self._page.mode == 's' and self._page._has_session: elif self._owner.mode == 's' and self._owner._has_session:
if url or domain or path: if url or domain or path:
raise AttributeError('url、domain、path参数只有d模式下有效。') raise AttributeError('url、domain、path参数只有d模式下有效。')
super(CookiesSetter, self).remove(name) super(CookiesSetter, self).remove(name)
def clear(self): def clear(self):
"""清除cookies""" """清除cookies"""
if self._page.mode == 'd' and self._page._has_driver: if self._owner.mode == 'd' and self._owner._has_driver:
super().clear() super().clear()
elif self._page.mode == 's' and self._page._has_session: elif self._owner.mode == 's' and self._owner._has_session:
super(CookiesSetter, self).clear() super(CookiesSetter, self).clear()

View File

@ -17,7 +17,7 @@ from .._pages.web_page import WebPage
class CookiesSetter(object): class CookiesSetter(object):
_page: ChromiumBase _owner: ChromiumBase
def __init__(self, page: ChromiumBase): ... def __init__(self, page: ChromiumBase): ...
@ -29,7 +29,7 @@ class CookiesSetter(object):
class SessionCookiesSetter(object): class SessionCookiesSetter(object):
_page: SessionPage _owner: SessionPage
def __init__(self, page: SessionPage): ... def __init__(self, page: SessionPage): ...
@ -41,7 +41,7 @@ class SessionCookiesSetter(object):
class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter): class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
_page: Union[WebPage, WebPageTab] _owner: Union[WebPage, WebPageTab]
def __init__(self, page: SessionPage): ... def __init__(self, page: SessionPage): ...

View File

@ -30,7 +30,7 @@ class DownloadManager(object):
def set_rename(self, tab_id: str, rename: str = None, suffix: str = None) -> None: ... def set_rename(self, tab_id: str, rename: str = None, suffix: str = None) -> None: ...
def set_file_exists(self, tab_id: str, mode: Literal['rename', 'skip', 'overwrite']) -> None: ... def set_file_exists(self, tab_id: str, mode: Literal['skip', 'rename', 'overwrite', 's', 'r', 'o']) -> None: ...
def set_flag(self, tab_id: str, flag: Union[bool, DownloadMission, None]) -> None: ... def set_flag(self, tab_id: str, flag: Union[bool, DownloadMission, None]) -> None: ...

View File

@ -21,13 +21,13 @@ from ..errors import WaitTimeoutError
class Listener(object): class Listener(object):
"""监听器基类""" """监听器基类"""
def __init__(self, page): def __init__(self, owner):
""" """
:param page: ChromiumBase对象 :param owner: ChromiumBase对象
""" """
self._page = page self._owner = owner
self._address = page.address self._address = owner.address
self._target_id = page._target_id self._target_id = owner._target_id
self._driver = None self._driver = None
self._running_requests = 0 self._running_requests = 0
self._running_targets = 0 self._running_targets = 0
@ -237,16 +237,16 @@ class Listener(object):
else: else:
return False return False
def _to_target(self, target_id, address, page): def _to_target(self, target_id, address, owner):
"""切换监听的页面对象 """切换监听的页面对象
:param target_id: 新页面对象_target_id :param target_id: 新页面对象_target_id
:param address: 新页面对象address :param address: 新页面对象address
:param page: 新页面对象 :param owner: 新页面对象
:return: None :return: None
""" """
self._target_id = target_id self._target_id = target_id
self._address = address self._address = address
self._page = page self._owner = owner
debug = False debug = False
if self._driver: if self._driver:
debug = self._driver._debug debug = self._driver._debug
@ -275,7 +275,7 @@ class Listener(object):
and (self._res_type is True or kwargs.get('type', '').upper() in self._res_type)): and (self._res_type is True or kwargs.get('type', '').upper() in self._res_type)):
self._running_targets += 1 self._running_targets += 1
rid = kwargs['requestId'] rid = kwargs['requestId']
p = self._request_ids.setdefault(rid, DataPacket(self._page.tab_id, True)) p = self._request_ids.setdefault(rid, DataPacket(self._owner.tab_id, True))
p._raw_request = kwargs p._raw_request = kwargs
if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None): if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None):
p._raw_post_data = self._driver.run('Network.getRequestPostData', p._raw_post_data = self._driver.run('Network.getRequestPostData',
@ -289,7 +289,7 @@ class Listener(object):
and (self._method is True or kwargs['request']['method'] in self._method) and (self._method is True or kwargs['request']['method'] in self._method)
and (self._res_type is True or kwargs.get('type', '').upper() in self._res_type)): and (self._res_type is True or kwargs.get('type', '').upper() in self._res_type)):
self._running_targets += 1 self._running_targets += 1
p = self._request_ids.setdefault(rid, DataPacket(self._page.tab_id, target)) p = self._request_ids.setdefault(rid, DataPacket(self._owner.tab_id, target))
p._raw_request = kwargs p._raw_request = kwargs
break break
@ -390,13 +390,13 @@ class Listener(object):
class FrameListener(Listener): class FrameListener(Listener):
def _requestWillBeSent(self, **kwargs): def _requestWillBeSent(self, **kwargs):
"""接收到请求时的回调函数""" """接收到请求时的回调函数"""
if not self._page._is_diff_domain and kwargs.get('frameId', None) != self._page._frame_id: if not self._owner._is_diff_domain and kwargs.get('frameId', None) != self._owner._frame_id:
return return
super()._requestWillBeSent(**kwargs) super()._requestWillBeSent(**kwargs)
def _response_received(self, **kwargs): def _response_received(self, **kwargs):
"""接收到返回信息时处理方法""" """接收到返回信息时处理方法"""
if not self._page._is_diff_domain and kwargs.get('frameId', None) != self._page._frame_id: if not self._owner._is_diff_domain and kwargs.get('frameId', None) != self._owner._frame_id:
return return
super()._response_received(**kwargs) super()._response_received(**kwargs)

View File

@ -19,8 +19,8 @@ __RES_TYPE__ = Literal['Document', 'Stylesheet', 'Image', 'Media', 'Font', 'Scri
class Listener(object): class Listener(object):
def __init__(self, page: ChromiumBase): def __init__(self, owner: ChromiumBase):
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
self._address: str = ... self._address: str = ...
self._target_id: str = ... self._target_id: str = ...
self._targets: Union[str, dict, None] = ... self._targets: Union[str, dict, None] = ...
@ -69,7 +69,7 @@ class Listener(object):
def wait_silent(self, timeout: float = None, targets_only: bool = False) -> bool: ... def wait_silent(self, timeout: float = None, targets_only: bool = False) -> bool: ...
def _to_target(self, target_id: str, address: str, page: ChromiumBase) -> None: ... def _to_target(self, target_id: str, address: str, owner: ChromiumBase) -> None: ...
def _requestWillBeSent(self, **kwargs) -> None: ... def _requestWillBeSent(self, **kwargs) -> None: ...
@ -92,8 +92,8 @@ class Listener(object):
class FrameListener(Listener): class FrameListener(Listener):
def __init__(self, page: ChromiumFrame): def __init__(self, owner: ChromiumFrame):
self._page: ChromiumFrame = ... self._owner: ChromiumFrame = ...
self._is_diff: bool = ... self._is_diff: bool = ...

View File

@ -113,8 +113,8 @@ class ElementRect(object):
class TabRect(object): class TabRect(object):
def __init__(self, page): def __init__(self, owner):
self._page = page self._owner = owner
@property @property
def window_state(self): def window_state(self):
@ -170,17 +170,17 @@ class TabRect(object):
@property @property
def viewport_size_with_scrollbar(self): def viewport_size_with_scrollbar(self):
"""返回视口宽高,包括滚动条,格式:(宽, 高)""" """返回视口宽高,包括滚动条,格式:(宽, 高)"""
r = self._page.run_js('return window.innerWidth.toString() + " " + window.innerHeight.toString();') r = self._owner.run_js('return window.innerWidth.toString() + " " + window.innerHeight.toString();')
w, h = r.split(' ') w, h = r.split(' ')
return int(w), int(h) return int(w), int(h)
def _get_page_rect(self): def _get_page_rect(self):
"""获取页面范围信息""" """获取页面范围信息"""
return self._page.run_cdp_loaded('Page.getLayoutMetrics') return self._owner.run_cdp_loaded('Page.getLayoutMetrics')
def _get_window_rect(self): def _get_window_rect(self):
"""获取窗口范围信息""" """获取窗口范围信息"""
return self._page.browser.get_window_bounds(self._page.tab_id) return self._owner.browser.get_window_bounds(self._owner.tab_id)
class FrameRect(object): class FrameRect(object):

View File

@ -62,8 +62,8 @@ class ElementRect(object):
class TabRect(object): class TabRect(object):
def __init__(self, page: ChromiumBase): def __init__(self, owner: Union[ChromiumPage, ChromiumTab, WebPage, WebPageTab]):
self._page: Union[ChromiumPage, ChromiumTab, WebPage, WebPageTab] = ... self._owner: Union[ChromiumPage, ChromiumTab, WebPage, WebPageTab] = ...
@property @property
def window_state(self) -> str: ... def window_state(self) -> str: ...

View File

@ -16,8 +16,8 @@ from time import sleep, time
class Screencast(object): class Screencast(object):
def __init__(self, page): def __init__(self, owner):
self._page = page self._owner = owner
self._path = None self._path = None
self._tmp_path = None self._tmp_path = None
self._running = False self._running = False
@ -39,16 +39,16 @@ class Screencast(object):
raise ValueError('save_path必须设置。') raise ValueError('save_path必须设置。')
if self._mode in ('frugal_video', 'video'): if self._mode in ('frugal_video', 'video'):
if self._page.browser.page._chromium_options.tmp_path: if self._owner.browser.page._chromium_options.tmp_path:
self._tmp_path = Path( self._tmp_path = Path(
self._page.browser.page._chromium_options.tmp_path) / f'screencast_tmp_{time()}_{randint(0, 100)}' self._owner.browser.page._chromium_options.tmp_path) / f'screencast_tmp_{time()}_{randint(0, 100)}'
else: else:
self._tmp_path = Path(gettempdir()) / 'DrissionPage' / f'screencast_tmp_{time()}_{randint(0, 100)}' self._tmp_path = Path(gettempdir()) / 'DrissionPage' / f'screencast_tmp_{time()}_{randint(0, 100)}'
self._tmp_path.mkdir(parents=True, exist_ok=True) self._tmp_path.mkdir(parents=True, exist_ok=True)
if self._mode.startswith('frugal'): if self._mode.startswith('frugal'):
self._page.driver.set_callback('Page.screencastFrame', self._onScreencastFrame) self._owner.driver.set_callback('Page.screencastFrame', self._onScreencastFrame)
self._page.run_cdp('Page.startScreencast', everyNthFrame=1, quality=100) self._owner.run_cdp('Page.startScreencast', everyNthFrame=1, quality=100)
elif not self._mode.startswith('js'): elif not self._mode.startswith('js'):
self._running = True self._running = True
@ -79,8 +79,8 @@ class Screencast(object):
} }
''' '''
print('请手动选择要录制的目标。') print('请手动选择要录制的目标。')
self._page.run_js('var DrissionPage_Screencast_blob;var DrissionPage_Screencast_blob_ok=false;') self._owner.run_js('var DrissionPage_Screencast_blob;var DrissionPage_Screencast_blob_ok=false;')
self._page.run_js(js) self._owner.run_js(js)
def stop(self, video_name=None): def stop(self, video_name=None):
"""停止录屏 """停止录屏
@ -93,19 +93,19 @@ class Screencast(object):
path = f'{self._path}{sep}{name}' path = f'{self._path}{sep}{name}'
if self._mode.startswith('js'): if self._mode.startswith('js'):
self._page.run_js('mediaRecorder.stop();', as_expr=True) self._owner.run_js('mediaRecorder.stop();', as_expr=True)
while not self._page.run_js('return DrissionPage_Screencast_blob_ok;'): while not self._owner.run_js('return DrissionPage_Screencast_blob_ok;'):
sleep(.1) sleep(.1)
blob = self._page.run_js('return DrissionPage_Screencast_blob;') blob = self._owner.run_js('return DrissionPage_Screencast_blob;')
uuid = self._page.run_cdp('IO.resolveBlob', objectId=blob['result']['objectId'])['uuid'] uuid = self._owner.run_cdp('IO.resolveBlob', objectId=blob['result']['objectId'])['uuid']
data = self._page.run_cdp('IO.read', handle=f'blob:{uuid}')['data'] data = self._owner.run_cdp('IO.read', handle=f'blob:{uuid}')['data']
with open(path, 'wb') as f: with open(path, 'wb') as f:
f.write(b64decode(data)) f.write(b64decode(data))
return path return path
if self._mode.startswith('frugal'): if self._mode.startswith('frugal'):
self._page.driver.set_callback('Page.screencastFrame', None) self._owner.driver.set_callback('Page.screencastFrame', None)
self._page.run_cdp('Page.stopScreencast') self._owner.run_cdp('Page.stopScreencast')
else: else:
self._enable = False self._enable = False
while self._running: while self._running:
@ -155,7 +155,7 @@ class Screencast(object):
self._running = True self._running = True
path = self._tmp_path or self._path path = self._tmp_path or self._path
while self._enable: while self._enable:
self._page.get_screenshot(path=path, name=f'{time()}.jpg') self._owner.get_screenshot(path=path, name=f'{time()}.jpg')
sleep(.04) sleep(.04)
self._running = False self._running = False
@ -164,7 +164,7 @@ class Screencast(object):
path = self._tmp_path or self._path path = self._tmp_path or self._path
with open(f'{path}{sep}{kwargs["metadata"]["timestamp"]}.jpg', 'wb') as f: with open(f'{path}{sep}{kwargs["metadata"]["timestamp"]}.jpg', 'wb') as f:
f.write(b64decode(kwargs['data'])) f.write(b64decode(kwargs['data']))
self._page.run_cdp('Page.screencastFrameAck', sessionId=kwargs['sessionId']) self._owner.run_cdp('Page.screencastFrameAck', sessionId=kwargs['sessionId'])
class ScreencastMode(object): class ScreencastMode(object):

View File

@ -12,8 +12,8 @@ from .._pages.chromium_base import ChromiumBase
class Screencast(object): class Screencast(object):
def __init__(self, page: ChromiumBase): def __init__(self, owner: ChromiumBase):
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
self._path: Path = ... self._path: Path = ...
self._tmp_path: Path = ... self._tmp_path: Path = ...
self._running: bool = ... self._running: bool = ...

View File

@ -87,15 +87,15 @@ class Scroller(object):
if not self._wait_complete: if not self._wait_complete:
return return
page = self._driver.owner if self._driver._type == 'ChromiumElement' else self._driver owner = self._driver.owner if self._driver._type == 'ChromiumElement' else self._driver
r = page.run_cdp('Page.getLayoutMetrics') r = owner.run_cdp('Page.getLayoutMetrics')
x = r['layoutViewport']['pageX'] x = r['layoutViewport']['pageX']
y = r['layoutViewport']['pageY'] y = r['layoutViewport']['pageY']
end_time = perf_counter() + page.timeout end_time = perf_counter() + owner.timeout
while perf_counter() < end_time: while perf_counter() < end_time:
sleep(.1) sleep(.1)
r = page.run_cdp('Page.getLayoutMetrics') r = owner.run_cdp('Page.getLayoutMetrics')
x1 = r['layoutViewport']['pageX'] x1 = r['layoutViewport']['pageX']
y1 = r['layoutViewport']['pageY'] y1 = r['layoutViewport']['pageY']
@ -120,11 +120,11 @@ class ElementScroller(Scroller):
class PageScroller(Scroller): class PageScroller(Scroller):
def __init__(self, page): def __init__(self, owner):
""" """
:param page: 页面对象 :param owner: 页面对象
""" """
super().__init__(page) super().__init__(owner)
self.t1 = 'window' self.t1 = 'window'
self.t2 = 'document.documentElement' self.t2 = 'document.documentElement'

View File

@ -51,7 +51,7 @@ class ElementScroller(Scroller):
class PageScroller(Scroller): class PageScroller(Scroller):
def __init__(self, page: ChromiumBase): ... def __init__(self, owner: ChromiumBase): ...
def to_see(self, loc_or_ele: Union[str, tuple, ChromiumElement], center: Union[bool, None] = None) -> None: ... def to_see(self, loc_or_ele: Union[str, tuple, ChromiumElement], center: Union[bool, None] = None) -> None: ...

View File

@ -16,8 +16,11 @@ from .._functions.web import format_headers
class BasePageSetter(object): class BasePageSetter(object):
def __init__(self, page): def __init__(self, owner):
self._page = page """
:param owner: BasePage对象
"""
self._owner = owner
def NoneElement_value(self, value=None, on_off=True): def NoneElement_value(self, value=None, on_off=True):
"""设置空元素是否返回设定值 """设置空元素是否返回设定值
@ -25,39 +28,42 @@ class BasePageSetter(object):
:param on_off: 是否启用 :param on_off: 是否启用
:return: None :return: None
""" """
self._page._none_ele_return_value = on_off self._owner._none_ele_return_value = on_off
self._page._none_ele_value = value self._owner._none_ele_value = value
class ChromiumBaseSetter(BasePageSetter): class ChromiumBaseSetter(BasePageSetter):
def __init__(self, page): def __init__(self, owner):
super().__init__(page) """
:param owner: ChromiumBase对象
"""
super().__init__(owner)
self._cookies_setter = None self._cookies_setter = None
@property @property
def load_mode(self): def load_mode(self):
"""返回用于设置页面加载策略的对象""" """返回用于设置页面加载策略的对象"""
return LoadMode(self._page) return LoadMode(self._owner)
@property @property
def scroll(self): def scroll(self):
"""返回用于设置页面滚动设置的对象""" """返回用于设置页面滚动设置的对象"""
return PageScrollSetter(self._page.scroll) return PageScrollSetter(self._owner.scroll)
@property @property
def cookies(self): def cookies(self):
"""返回用于设置cookies的对象""" """返回用于设置cookies的对象"""
if self._cookies_setter is None: if self._cookies_setter is None:
self._cookies_setter = CookiesSetter(self._page) self._cookies_setter = CookiesSetter(self._owner)
return self._cookies_setter return self._cookies_setter
def retry_times(self, times): def retry_times(self, times):
"""设置连接失败重连次数""" """设置连接失败重连次数"""
self._page.retry_times = times self._owner.retry_times = times
def retry_interval(self, interval): def retry_interval(self, interval):
"""设置连接失败重连间隔""" """设置连接失败重连间隔"""
self._page.retry_interval = interval self._owner.retry_interval = interval
def timeouts(self, base=None, page_load=None, script=None, implicit=None): def timeouts(self, base=None, page_load=None, script=None, implicit=None):
"""设置超时时间,单位为秒 """设置超时时间,单位为秒
@ -68,14 +74,14 @@ class ChromiumBaseSetter(BasePageSetter):
""" """
base = base if base is not None else implicit base = base if base is not None else implicit
if base is not None: if base is not None:
self._page.timeouts.base = base self._owner.timeouts.base = base
self._page._timeout = base self._owner._timeout = base
if page_load is not None: if page_load is not None:
self._page.timeouts.page_load = page_load self._owner.timeouts.page_load = page_load
if script is not None: if script is not None:
self._page.timeouts.script = script self._owner.timeouts.script = script
def user_agent(self, ua, platform=None): def user_agent(self, ua, platform=None):
"""为当前tab设置user agent只在当前tab有效 """为当前tab设置user agent只在当前tab有效
@ -86,7 +92,7 @@ class ChromiumBaseSetter(BasePageSetter):
keys = {'userAgent': ua} keys = {'userAgent': ua}
if platform: if platform:
keys['platform'] = platform keys['platform'] = platform
self._page.run_cdp('Emulation.setUserAgentOverride', **keys) self._owner.run_cdp('Emulation.setUserAgentOverride', **keys)
def session_storage(self, item, value): def session_storage(self, item, value):
"""设置或删除某项sessionStorage信息 """设置或删除某项sessionStorage信息
@ -94,15 +100,15 @@ class ChromiumBaseSetter(BasePageSetter):
:param value: 项的值设置为False时删除该项 :param value: 项的值设置为False时删除该项
:return: None :return: None
""" """
self._page.run_cdp_loaded('DOMStorage.enable') self._owner.run_cdp_loaded('DOMStorage.enable')
i = self._page.run_cdp('Storage.getStorageKeyForFrame', frameId=self._page._frame_id)['storageKey'] i = self._owner.run_cdp('Storage.getStorageKeyForFrame', frameId=self._owner._frame_id)['storageKey']
if value is False: if value is False:
self._page.run_cdp('DOMStorage.removeDOMStorageItem', self._owner.run_cdp('DOMStorage.removeDOMStorageItem',
storageId={'storageKey': i, 'isLocalStorage': False}, key=item) storageId={'storageKey': i, 'isLocalStorage': False}, key=item)
else: else:
self._page.run_cdp('DOMStorage.setDOMStorageItem', storageId={'storageKey': i, 'isLocalStorage': False}, self._owner.run_cdp('DOMStorage.setDOMStorageItem', storageId={'storageKey': i, 'isLocalStorage': False},
key=item, value=value) key=item, value=value)
self._page.run_cdp_loaded('DOMStorage.disable') self._owner.run_cdp_loaded('DOMStorage.disable')
def local_storage(self, item, value): def local_storage(self, item, value):
"""设置或删除某项localStorage信息 """设置或删除某项localStorage信息
@ -110,38 +116,38 @@ class ChromiumBaseSetter(BasePageSetter):
:param value: 项的值设置为False时删除该项 :param value: 项的值设置为False时删除该项
:return: None :return: None
""" """
self._page.run_cdp_loaded('DOMStorage.enable') self._owner.run_cdp_loaded('DOMStorage.enable')
i = self._page.run_cdp('Storage.getStorageKeyForFrame', frameId=self._page._frame_id)['storageKey'] i = self._owner.run_cdp('Storage.getStorageKeyForFrame', frameId=self._owner._frame_id)['storageKey']
if value is False: if value is False:
self._page.run_cdp('DOMStorage.removeDOMStorageItem', self._owner.run_cdp('DOMStorage.removeDOMStorageItem',
storageId={'storageKey': i, 'isLocalStorage': True}, key=item) storageId={'storageKey': i, 'isLocalStorage': True}, key=item)
else: else:
self._page.run_cdp('DOMStorage.setDOMStorageItem', storageId={'storageKey': i, 'isLocalStorage': True}, self._owner.run_cdp('DOMStorage.setDOMStorageItem', storageId={'storageKey': i, 'isLocalStorage': True},
key=item, value=value) key=item, value=value)
self._page.run_cdp_loaded('DOMStorage.disable') self._owner.run_cdp_loaded('DOMStorage.disable')
def upload_files(self, files): def upload_files(self, files):
"""等待上传的文件路径 """等待上传的文件路径
:param files: 文件路径列表或字符串字符串时多个文件用回车分隔 :param files: 文件路径列表或字符串字符串时多个文件用回车分隔
:return: None :return: None
""" """
if not self._page._upload_list: if not self._owner._upload_list:
self._page.driver.set_callback('Page.fileChooserOpened', self._page._onFileChooserOpened) self._owner.driver.set_callback('Page.fileChooserOpened', self._owner._onFileChooserOpened)
self._page.run_cdp('Page.setInterceptFileChooserDialog', enabled=True) self._owner.run_cdp('Page.setInterceptFileChooserDialog', enabled=True)
if isinstance(files, str): if isinstance(files, str):
files = files.split('\n') files = files.split('\n')
elif isinstance(files, Path): elif isinstance(files, Path):
files = (files, ) files = (files,)
self._page._upload_list = [str(Path(i).absolute()) for i in files] self._owner._upload_list = [str(Path(i).absolute()) for i in files]
def headers(self, headers) -> None: def headers(self, headers) -> None:
"""设置固定发送的headers """设置固定发送的headers
:param headers: dict格式的headers数据 :param headers: dict格式的headers数据
:return: None :return: None
""" """
self._page.run_cdp('Network.enable') self._owner.run_cdp('Network.enable')
self._page.run_cdp('Network.setExtraHTTPHeaders', headers=format_headers(headers)) self._owner.run_cdp('Network.setExtraHTTPHeaders', headers=format_headers(headers))
def auto_handle_alert(self, on_off=True, accept=True): def auto_handle_alert(self, on_off=True, accept=True):
"""设置是否启用自动处理弹窗 """设置是否启用自动处理弹窗
@ -149,7 +155,7 @@ class ChromiumBaseSetter(BasePageSetter):
:param accept: bool表示确定还是取消 :param accept: bool表示确定还是取消
:return: None :return: None
""" """
self._page._alert.auto = accept if on_off else None self._owner._alert.auto = accept if on_off else None
def blocked_urls(self, urls): def blocked_urls(self, urls):
"""设置要忽略的url """设置要忽略的url
@ -162,25 +168,28 @@ class ChromiumBaseSetter(BasePageSetter):
urls = (urls,) urls = (urls,)
if not isinstance(urls, (list, tuple)): if not isinstance(urls, (list, tuple)):
raise TypeError('urls需传入str、list或tuple类型。') raise TypeError('urls需传入str、list或tuple类型。')
self._page.run_cdp('Network.enable') self._owner.run_cdp('Network.enable')
self._page.run_cdp('Network.setBlockedURLs', urls=urls) self._owner.run_cdp('Network.setBlockedURLs', urls=urls)
# --------------即将废弃--------------- # --------------即将废弃---------------
@property @property
def load_strategy(self): def load_strategy(self):
"""返回用于设置页面加载策略的对象""" """返回用于设置页面加载策略的对象"""
return LoadMode(self._page) return LoadMode(self._owner)
class TabSetter(ChromiumBaseSetter): class TabSetter(ChromiumBaseSetter):
def __init__(self, page): def __init__(self, owner):
super().__init__(page) """
:param owner: 标签页对象
"""
super().__init__(owner)
@property @property
def window(self): def window(self):
"""返回用于设置浏览器窗口的对象""" """返回用于设置浏览器窗口的对象"""
return WindowSetter(self._page) return WindowSetter(self._owner)
def download_path(self, path): def download_path(self, path):
"""设置下载路径 """设置下载路径
@ -188,10 +197,10 @@ class TabSetter(ChromiumBaseSetter):
:return: None :return: None
""" """
path = str(Path(path).absolute()) path = str(Path(path).absolute())
self._page._download_path = path self._owner._download_path = path
self._page.browser._dl_mgr.set_path(self._page, path) self._owner.browser._dl_mgr.set_path(self._owner, path)
if self._page._DownloadKit: if self._owner._DownloadKit:
self._page._DownloadKit.set.goal_path(path) self._owner._DownloadKit.set.goal_path(path)
def download_file_name(self, name=None, suffix=None): def download_file_name(self, name=None, suffix=None):
"""设置下一个被下载文件的名称 """设置下一个被下载文件的名称
@ -199,7 +208,7 @@ class TabSetter(ChromiumBaseSetter):
:param suffix: 后缀名显式设置后缀名不使用远程文件后缀 :param suffix: 后缀名显式设置后缀名不使用远程文件后缀
:return: None :return: None
""" """
self._page.browser._dl_mgr.set_rename(self._page.tab_id, name, suffix) self._owner.browser._dl_mgr.set_rename(self._owner.tab_id, name, suffix)
def when_download_file_exists(self, mode): def when_download_file_exists(self, mode):
"""设置当存在同名文件时的处理方式 """设置当存在同名文件时的处理方式
@ -212,11 +221,11 @@ class TabSetter(ChromiumBaseSetter):
if mode not in types: if mode not in types:
raise ValueError(f'''mode参数只能是 '{"', '".join(types.keys())}' 之一,现在是:{mode}''') raise ValueError(f'''mode参数只能是 '{"', '".join(types.keys())}' 之一,现在是:{mode}''')
self._page.browser._dl_mgr.set_file_exists(self._page.tab_id, mode) self._owner.browser._dl_mgr.set_file_exists(self._owner.tab_id, mode)
def activate(self): def activate(self):
"""使标签页处于最前面""" """使标签页处于最前面"""
self._page.browser.activate_tab(self._page.tab_id) self._owner.browser.activate_tab(self._owner.tab_id)
class ChromiumPageSetter(TabSetter): class ChromiumPageSetter(TabSetter):
@ -227,39 +236,34 @@ class ChromiumPageSetter(TabSetter):
:return: None :return: None
""" """
if not tab_or_id: if not tab_or_id:
tab_or_id = self._page.tab_id tab_or_id = self._owner.tab_id
elif not isinstance(tab_or_id, str): # 传入Tab对象 elif not isinstance(tab_or_id, str): # 传入Tab对象
tab_or_id = tab_or_id.tab_id tab_or_id = tab_or_id.tab_id
self._page.browser.activate_tab(tab_or_id) self._owner.browser.activate_tab(tab_or_id)
@property
def window(self):
"""返回用于设置浏览器窗口的对象"""
return PageWindowSetter(self._page)
class SessionPageSetter(BasePageSetter): class SessionPageSetter(BasePageSetter):
def __init__(self, page): def __init__(self, owner):
""" """
:param page: SessionPage对象 :param owner: SessionPage对象
""" """
super().__init__(page) super().__init__(owner)
self._cookies_setter = None self._cookies_setter = None
@property @property
def cookies(self): def cookies(self):
"""返回用于设置cookies的对象""" """返回用于设置cookies的对象"""
if self._cookies_setter is None: if self._cookies_setter is None:
self._cookies_setter = SessionCookiesSetter(self._page) self._cookies_setter = SessionCookiesSetter(self._owner)
return self._cookies_setter return self._cookies_setter
def retry_times(self, times): def retry_times(self, times):
"""设置连接失败时重连次数""" """设置连接失败时重连次数"""
self._page.retry_times = times self._owner.retry_times = times
def retry_interval(self, interval): def retry_interval(self, interval):
"""设置连接失败时重连间隔""" """设置连接失败时重连间隔"""
self._page.retry_interval = interval self._owner.retry_interval = interval
def download_path(self, path): def download_path(self, path):
"""设置下载路径 """设置下载路径
@ -267,16 +271,16 @@ class SessionPageSetter(BasePageSetter):
:return: None :return: None
""" """
path = str(Path(path).absolute()) path = str(Path(path).absolute())
self._page._download_path = path self._owner._download_path = path
if self._page._DownloadKit: if self._owner._DownloadKit:
self._page._DownloadKit.set.goal_path(path) self._owner._DownloadKit.set.goal_path(path)
def timeout(self, second): def timeout(self, second):
"""设置连接超时时间 """设置连接超时时间
:param second: 秒数 :param second: 秒数
:return: None :return: None
""" """
self._page.timeout = second self._owner.timeout = second
def encoding(self, encoding, set_all=True): def encoding(self, encoding, set_all=True):
"""设置编码 """设置编码
@ -285,16 +289,16 @@ class SessionPageSetter(BasePageSetter):
:return: None :return: None
""" """
if set_all: if set_all:
self._page._encoding = encoding if encoding else None self._owner._encoding = encoding if encoding else None
if self._page.response: if self._owner.response:
self._page.response.encoding = encoding self._owner.response.encoding = encoding
def headers(self, headers): def headers(self, headers):
"""设置通用的headers """设置通用的headers
:param headers: dict形式的headers :param headers: dict形式的headers
:return: None :return: None
""" """
self._page._headers = CaseInsensitiveDict(format_headers(headers)) self._owner._headers = CaseInsensitiveDict(format_headers(headers))
def header(self, name, value): def header(self, name, value):
"""设置headers中一个项 """设置headers中一个项
@ -302,14 +306,14 @@ class SessionPageSetter(BasePageSetter):
:param value: 设置值 :param value: 设置值
:return: None :return: None
""" """
self._page._headers[name] = value self._owner._headers[name] = value
def user_agent(self, ua): def user_agent(self, ua):
"""设置user agent """设置user agent
:param ua: user agent :param ua: user agent
:return: None :return: None
""" """
self._page._headers['user-agent'] = ua self._owner._headers['user-agent'] = ua
def proxies(self, http=None, https=None): def proxies(self, http=None, https=None):
"""设置proxies参数 """设置proxies参数
@ -317,63 +321,63 @@ class SessionPageSetter(BasePageSetter):
:param https: https代理地址 :param https: https代理地址
:return: None :return: None
""" """
self._page.session.proxies = {'http': http, 'https': https} self._owner.session.proxies = {'http': http, 'https': https}
def auth(self, auth): def auth(self, auth):
"""设置认证元组或对象 """设置认证元组或对象
:param auth: 认证元组或对象 :param auth: 认证元组或对象
:return: None :return: None
""" """
self._page.session.auth = auth self._owner.session.auth = auth
def hooks(self, hooks): def hooks(self, hooks):
"""设置回调方法 """设置回调方法
:param hooks: 回调方法 :param hooks: 回调方法
:return: None :return: None
""" """
self._page.session.hooks = hooks self._owner.session.hooks = hooks
def params(self, params): def params(self, params):
"""设置查询参数字典 """设置查询参数字典
:param params: 查询参数字典 :param params: 查询参数字典
:return: None :return: None
""" """
self._page.session.params = params self._owner.session.params = params
def verify(self, on_off): def verify(self, on_off):
"""设置是否验证SSL证书 """设置是否验证SSL证书
:param on_off: 是否验证 SSL 证书 :param on_off: 是否验证 SSL 证书
:return: None :return: None
""" """
self._page.session.verify = on_off self._owner.session.verify = on_off
def cert(self, cert): def cert(self, cert):
"""SSL客户端证书文件的路径(.pem格式),或(cert, key)元组 """SSL客户端证书文件的路径(.pem格式),或(cert, key)元组
:param cert: 证书路径或元组 :param cert: 证书路径或元组
:return: None :return: None
""" """
self._page.session.cert = cert self._owner.session.cert = cert
def stream(self, on_off): def stream(self, on_off):
"""设置是否使用流式响应内容 """设置是否使用流式响应内容
:param on_off: 是否使用流式响应内容 :param on_off: 是否使用流式响应内容
:return: None :return: None
""" """
self._page.session.stream = on_off self._owner.session.stream = on_off
def trust_env(self, on_off): def trust_env(self, on_off):
"""设置是否信任环境 """设置是否信任环境
:param on_off: 是否信任环境 :param on_off: 是否信任环境
:return: None :return: None
""" """
self._page.session.trust_env = on_off self._owner.session.trust_env = on_off
def max_redirects(self, times): def max_redirects(self, times):
"""设置最大重定向次数 """设置最大重定向次数
:param times: 最大重定向次数 :param times: 最大重定向次数
:return: None :return: None
""" """
self._page.session.max_redirects = times self._owner.session.max_redirects = times
def add_adapter(self, url, adapter): def add_adapter(self, url, adapter):
"""添加适配器 """添加适配器
@ -381,20 +385,20 @@ class SessionPageSetter(BasePageSetter):
:param adapter: 适配器对象 :param adapter: 适配器对象
:return: None :return: None
""" """
self._page.session.mount(url, adapter) self._owner.session.mount(url, adapter)
class WebPageSetter(ChromiumPageSetter): class WebPageSetter(ChromiumPageSetter):
def __init__(self, page): def __init__(self, owner):
super().__init__(page) super().__init__(owner)
self._session_setter = SessionPageSetter(self._page) self._session_setter = SessionPageSetter(self._owner)
self._chromium_setter = ChromiumPageSetter(self._page) self._chromium_setter = ChromiumPageSetter(self._owner)
@property @property
def cookies(self): def cookies(self):
"""返回用于设置cookies的对象""" """返回用于设置cookies的对象"""
if self._cookies_setter is None: if self._cookies_setter is None:
self._cookies_setter = WebPageCookiesSetter(self._page) self._cookies_setter = WebPageCookiesSetter(self._owner)
return self._cookies_setter return self._cookies_setter
def headers(self, headers) -> None: def headers(self, headers) -> None:
@ -402,30 +406,30 @@ class WebPageSetter(ChromiumPageSetter):
:param headers: dict格式的headers数据 :param headers: dict格式的headers数据
:return: None :return: None
""" """
if self._page.mode == 's': if self._owner.mode == 's':
self._session_setter.headers(headers) self._session_setter.headers(headers)
else: else:
self._chromium_setter.headers(headers) self._chromium_setter.headers(headers)
def user_agent(self, ua, platform=None): def user_agent(self, ua, platform=None):
"""设置user agentd模式下只有当前tab有效""" """设置user agentd模式下只有当前tab有效"""
if self._page.mode == 's': if self._owner.mode == 's':
self._session_setter.user_agent(ua) self._session_setter.user_agent(ua)
else: else:
self._chromium_setter.user_agent(ua, platform) self._chromium_setter.user_agent(ua, platform)
class WebPageTabSetter(TabSetter): class WebPageTabSetter(TabSetter):
def __init__(self, page): def __init__(self, owner):
super().__init__(page) super().__init__(owner)
self._session_setter = SessionPageSetter(self._page) self._session_setter = SessionPageSetter(self._owner)
self._chromium_setter = ChromiumBaseSetter(self._page) self._chromium_setter = ChromiumBaseSetter(self._owner)
@property @property
def cookies(self): def cookies(self):
"""返回用于设置cookies的对象""" """返回用于设置cookies的对象"""
if self._cookies_setter is None: if self._cookies_setter is None:
self._cookies_setter = WebPageCookiesSetter(self._page) self._cookies_setter = WebPageCookiesSetter(self._owner)
return self._cookies_setter return self._cookies_setter
def headers(self, headers) -> None: def headers(self, headers) -> None:
@ -433,16 +437,16 @@ class WebPageTabSetter(TabSetter):
:param headers: dict格式的headers数据 :param headers: dict格式的headers数据
:return: None :return: None
""" """
if self._page._has_session: if self._owner._has_session:
self._session_setter.headers(headers) self._session_setter.headers(headers)
if self._page._has_driver: if self._owner._has_driver:
self._chromium_setter.headers(headers) self._chromium_setter.headers(headers)
def user_agent(self, ua, platform=None): def user_agent(self, ua, platform=None):
"""设置user agentd模式下只有当前tab有效""" """设置user agentd模式下只有当前tab有效"""
if self._page._has_session: if self._owner._has_session:
self._session_setter.user_agent(ua) self._session_setter.user_agent(ua)
if self._page._has_driver: if self._owner._has_driver:
self._chromium_setter.user_agent(ua, platform) self._chromium_setter.user_agent(ua, platform)
@ -492,17 +496,17 @@ class ChromiumFrameSetter(ChromiumBaseSetter):
:param value: 属性值 :param value: 属性值
:return: None :return: None
""" """
self._page.frame_ele.set.attr(name, value) self._owner.frame_ele.set.attr(name, value)
class LoadMode(object): class LoadMode(object):
"""用于设置页面加载策略的类""" """用于设置页面加载策略的类"""
def __init__(self, page): def __init__(self, owner):
""" """
:param page: ChromiumBase对象 :param owner: ChromiumBase对象
""" """
self._page = page self._owner = owner
def __call__(self, value): def __call__(self, value):
"""设置加载策略 """设置加载策略
@ -511,23 +515,26 @@ class LoadMode(object):
""" """
if value.lower() not in ('normal', 'eager', 'none'): if value.lower() not in ('normal', 'eager', 'none'):
raise ValueError("只能选择 'normal', 'eager', 'none'") raise ValueError("只能选择 'normal', 'eager', 'none'")
self._page._load_mode = value self._owner._load_mode = value
def normal(self): def normal(self):
"""设置页面加载策略为normal""" """设置页面加载策略为normal"""
self._page._load_mode = 'normal' self._owner._load_mode = 'normal'
def eager(self): def eager(self):
"""设置页面加载策略为eager""" """设置页面加载策略为eager"""
self._page._load_mode = 'eager' self._owner._load_mode = 'eager'
def none(self): def none(self):
"""设置页面加载策略为none""" """设置页面加载策略为none"""
self._page._load_mode = 'none' self._owner._load_mode = 'none'
class PageScrollSetter(object): class PageScrollSetter(object):
def __init__(self, scroll): def __init__(self, scroll):
"""
:param scroll: PageScroller对象
"""
self._scroll = scroll self._scroll = scroll
def wait_complete(self, on_off=True): def wait_complete(self, on_off=True):
@ -554,11 +561,11 @@ class PageScrollSetter(object):
class WindowSetter(object): class WindowSetter(object):
"""用于设置窗口大小的类""" """用于设置窗口大小的类"""
def __init__(self, page): def __init__(self, owner):
""" """
:param page: 页面对象 :param owner: 页面对象
""" """
self._page = page self._owner = owner
self._window_id = self._get_info()['windowId'] self._window_id = self._get_info()['windowId']
def max(self): def max(self):
@ -621,7 +628,7 @@ class WindowSetter(object):
"""获取窗口位置及大小信息""" """获取窗口位置及大小信息"""
for _ in range(50): for _ in range(50):
try: try:
return self._page.run_cdp('Browser.getWindowForTarget') return self._owner.run_cdp('Browser.getWindowForTarget')
except: except:
sleep(.1) sleep(.1)
@ -631,7 +638,7 @@ class WindowSetter(object):
:return: None :return: None
""" """
try: try:
self._page.run_cdp('Browser.setWindowBounds', windowId=self._window_id, bounds=bounds) self._owner.run_cdp('Browser.setWindowBounds', windowId=self._window_id, bounds=bounds)
except: except:
raise RuntimeError('浏览器全屏或最小化状态时请先调用set.window.normal()恢复正常状态。') raise RuntimeError('浏览器全屏或最小化状态时请先调用set.window.normal()恢复正常状态。')
@ -649,12 +656,10 @@ class WindowSetter(object):
"""设置窗口为全屏""" """设置窗口为全屏"""
self.full() self.full()
class PageWindowSetter(WindowSetter):
def hide(self): def hide(self):
"""隐藏浏览器窗口只在Windows系统可用""" """隐藏浏览器窗口只在Windows系统可用"""
show_or_hide_browser(self._page, hide=True) show_or_hide_browser(self._owner, hide=True)
def show(self): def show(self):
"""显示浏览器窗口只在Windows系统可用""" """显示浏览器窗口只在Windows系统可用"""
show_or_hide_browser(self._page, hide=False) show_or_hide_browser(self._owner, hide=False)

View File

@ -6,7 +6,7 @@
@License : BSD 3-Clause. @License : BSD 3-Clause.
""" """
from pathlib import Path from pathlib import Path
from typing import Union, Tuple, Literal, Any from typing import Union, Tuple, Literal, Any, Optional
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
@ -18,7 +18,7 @@ from .._elements.chromium_element import ChromiumElement
from .._pages.chromium_base import ChromiumBase from .._pages.chromium_base import ChromiumBase
from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_frame import ChromiumFrame
from .._pages.chromium_page import ChromiumPage from .._pages.chromium_page import ChromiumPage
from .._pages.chromium_tab import ChromiumTab from .._pages.chromium_tab import ChromiumTab, WebPageTab
from .._pages.session_page import SessionPage from .._pages.session_page import SessionPage
from .._pages.web_page import WebPage from .._pages.web_page import WebPage
@ -26,15 +26,15 @@ FILE_EXISTS = Literal['skip', 'rename', 'overwrite', 's', 'r', 'o']
class BasePageSetter(object): class BasePageSetter(object):
def __init__(self, page: BasePage): def __init__(self, owner: BasePage):
self._page: BasePage = ... self._owner: BasePage = ...
def NoneElement_value(self, value: Any = None, on_off: bool = True) -> None: ... def NoneElement_value(self, value: Any = None, on_off: bool = True) -> None: ...
class ChromiumBaseSetter(BasePageSetter): class ChromiumBaseSetter(BasePageSetter):
def __init__(self, page): def __init__(self, owner):
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
self._cookies_setter: CookiesSetter = ... self._cookies_setter: CookiesSetter = ...
@property @property
@ -68,7 +68,9 @@ class ChromiumBaseSetter(BasePageSetter):
class TabSetter(ChromiumBaseSetter): class TabSetter(ChromiumBaseSetter):
def __init__(self, page): ... _owner: ChromiumTab = ...
def __init__(self, owner: Union[ChromiumTab, WebPage]): ...
@property @property
def window(self) -> WindowSetter: ... def window(self) -> WindowSetter: ...
@ -83,20 +85,16 @@ class TabSetter(ChromiumBaseSetter):
class ChromiumPageSetter(TabSetter): class ChromiumPageSetter(TabSetter):
_page: ChromiumPage = ... _owner: ChromiumPage = ...
@property
def window(self) -> PageWindowSetter: ...
def main_tab(self, tab_id: str = None) -> None: ...
def tab_to_front(self, tab_or_id: Union[str, ChromiumTab] = None) -> None: ... def tab_to_front(self, tab_or_id: Union[str, ChromiumTab] = None) -> None: ...
class SessionPageSetter(BasePageSetter): class SessionPageSetter(BasePageSetter):
def __init__(self, page: SessionPage): _owner: SessionPage = ...
self._page: SessionPage = ... _cookies_setter: Optional[SessionCookiesSetter] = ...
self._cookies_setter: SessionCookiesSetter = ...
def __init__(self, owner: SessionPage): ...
@property @property
def cookies(self) -> SessionCookiesSetter: ... def cookies(self) -> SessionCookiesSetter: ...
@ -139,7 +137,7 @@ class SessionPageSetter(BasePageSetter):
class WebPageSetter(ChromiumPageSetter): class WebPageSetter(ChromiumPageSetter):
_page: WebPage = ... _owner: WebPage = ...
_session_setter: SessionPageSetter = ... _session_setter: SessionPageSetter = ...
_chromium_setter: ChromiumPageSetter = ... _chromium_setter: ChromiumPageSetter = ...
@ -152,7 +150,7 @@ class WebPageSetter(ChromiumPageSetter):
class WebPageTabSetter(TabSetter): class WebPageTabSetter(TabSetter):
_page: WebPage = ... _owner: WebPageTab = ...
_session_setter: SessionPageSetter = ... _session_setter: SessionPageSetter = ...
_chromium_setter: ChromiumBaseSetter = ... _chromium_setter: ChromiumBaseSetter = ...
@ -178,14 +176,14 @@ class ChromiumElementSetter(object):
class ChromiumFrameSetter(ChromiumBaseSetter): class ChromiumFrameSetter(ChromiumBaseSetter):
_page: ChromiumFrame = ... _owner: ChromiumFrame = ...
def attr(self, name: str, value: str) -> None: ... def attr(self, name: str, value: str) -> None: ...
class LoadMode(object): class LoadMode(object):
def __init__(self, page: ChromiumBase): def __init__(self, owner: ChromiumBase):
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
def __call__(self, value: str) -> None: ... def __call__(self, value: str) -> None: ...
@ -206,8 +204,8 @@ class PageScrollSetter(object):
class WindowSetter(object): class WindowSetter(object):
def __init__(self, page: ChromiumBase): def __init__(self, owner: ChromiumBase):
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
self._window_id: str = ... self._window_id: str = ...
def max(self) -> None: ... def max(self) -> None: ...
@ -226,10 +224,6 @@ class WindowSetter(object):
def _perform(self, bounds: dict) -> None: ... def _perform(self, bounds: dict) -> None: ...
class PageWindowSetter(WindowSetter):
_page: ChromiumPage = ...
def hide(self) -> None: ... def hide(self) -> None: ...
def show(self) -> None: ... def show(self) -> None: ...

View File

@ -105,22 +105,22 @@ class ShadowRootStates(object):
class PageStates(object): class PageStates(object):
"""Page对象、Tab对象使用""" """Page对象、Tab对象使用"""
def __init__(self, page): def __init__(self, owner):
""" """
:param page: ChromiumBase对象 :param owner: ChromiumBase对象
""" """
self._page = page self._owner = owner
@property @property
def is_loading(self): def is_loading(self):
"""返回页面是否在加载状态""" """返回页面是否在加载状态"""
return self._page._is_loading return self._owner._is_loading
@property @property
def is_alive(self): def is_alive(self):
"""返回页面对象是否仍然可用""" """返回页面对象是否仍然可用"""
try: try:
self._page.run_cdp('Page.getLayoutMetrics') self._owner.run_cdp('Page.getLayoutMetrics')
return True return True
except PageDisconnectedError: except PageDisconnectedError:
return False return False
@ -128,12 +128,12 @@ class PageStates(object):
@property @property
def ready_state(self): def ready_state(self):
"""返回当前页面加载状态,'connecting' 'loading' 'interactive' 'complete'""" """返回当前页面加载状态,'connecting' 'loading' 'interactive' 'complete'"""
return self._page._ready_state return self._owner._ready_state
@property @property
def has_alert(self): def has_alert(self):
"""返回当前页面是否存在弹窗""" """返回当前页面是否存在弹窗"""
return self._page._has_alert return self._owner._has_alert
class FrameStates(object): class FrameStates(object):

View File

@ -59,8 +59,8 @@ class ShadowRootStates(object):
class PageStates(object): class PageStates(object):
def __init__(self, page: ChromiumBase): def __init__(self, owner: ChromiumBase):
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
@property @property
def is_loading(self) -> bool: ... def is_loading(self) -> bool: ...

View File

@ -272,7 +272,6 @@ class TabWaiter(BaseWaiter):
class PageWaiter(TabWaiter): class PageWaiter(TabWaiter):
def __init__(self, page): def __init__(self, page):
super().__init__(page) super().__init__(page)
# self._listener = None
def new_tab(self, timeout=None, raise_err=None): def new_tab(self, timeout=None, raise_err=None):
"""等待新标签页出现 """等待新标签页出现
@ -325,12 +324,12 @@ class PageWaiter(TabWaiter):
class ElementWaiter(object): class ElementWaiter(object):
"""等待元素在dom中某种状态如删除、显示、隐藏""" """等待元素在dom中某种状态如删除、显示、隐藏"""
def __init__(self, page, ele): def __init__(self, owner, ele):
"""等待元素在dom中某种状态如删除、显示、隐藏 """等待元素在dom中某种状态如删除、显示、隐藏
:param page: 元素所在页面 :param owner: 元素所在页面
:param ele: 要等待的元素 :param ele: 要等待的元素
""" """
self._page = page self._owner = owner
self._ele = ele self._ele = ele
def __call__(self, second, scope=None): def __call__(self, second, scope=None):
@ -408,7 +407,7 @@ class ElementWaiter(object):
:return: 是否等待成功 :return: 是否等待成功
""" """
if timeout is None: if timeout is None:
timeout = self._page.timeout timeout = self._owner.timeout
end_time = perf_counter() + timeout end_time = perf_counter() + timeout
while perf_counter() < end_time: while perf_counter() < end_time:
if not self._ele.states.is_enabled or not self._ele.states.is_alive: if not self._ele.states.is_enabled or not self._ele.states.is_alive:
@ -428,7 +427,7 @@ class ElementWaiter(object):
:return: 是否等待成功 :return: 是否等待成功
""" """
if timeout is None: if timeout is None:
timeout = self._page.timeout timeout = self._owner.timeout
end_time = perf_counter() + timeout end_time = perf_counter() + timeout
while perf_counter() < end_time: while perf_counter() < end_time:
try: try:
@ -471,7 +470,7 @@ class ElementWaiter(object):
""" """
err_text = err_text or '等待元素状态改变失败(等待{}秒)。' err_text = err_text or '等待元素状态改变失败(等待{}秒)。'
if timeout is None: if timeout is None:
timeout = self._page.timeout timeout = self._owner.timeout
end_time = perf_counter() + timeout end_time = perf_counter() + timeout
while perf_counter() < end_time: while perf_counter() < end_time:
a = self._ele.states.__getattribute__(attr) a = self._ele.states.__getattribute__(attr)

View File

@ -74,9 +74,9 @@ class PageWaiter(TabWaiter):
class ElementWaiter(object): class ElementWaiter(object):
def __init__(self, page: ChromiumBase, ele: ChromiumElement): def __init__(self, owner: ChromiumBase, ele: ChromiumElement):
self._ele: ChromiumElement = ... self._ele: ChromiumElement = ...
self._page: ChromiumBase = ... self._owner: ChromiumBase = ...
def __call__(self, second: float, scope: float = None) -> None: ... def __call__(self, second: float, scope: float = None) -> None: ...