1
0
mirror of https://gitee.com/g1879/DrissionPage.git synced 2024-12-10 04:00:23 +08:00

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

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

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

@ -10,7 +10,7 @@ from pathlib import Path
from threading import Lock
from typing import Union, Tuple
from .._pages.chromium_page import ChromiumPage
from .._pages.chromium_base import ChromiumBase
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 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]: ...

@ -31,7 +31,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
"""初始化函数
:param mode: 'd' 's'即driver模式和session模式
: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
"""
if hasattr(self, '_created'):

@ -184,17 +184,6 @@ class Clicker(object):
raise RuntimeError('没有出现新标签页。')
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):
"""实施点击
:param client_x: 视口中的x坐标

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

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

@ -30,7 +30,7 @@ class DownloadManager(object):
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: ...

@ -21,13 +21,13 @@ from ..errors import WaitTimeoutError
class Listener(object):
"""监听器基类"""
def __init__(self, page):
def __init__(self, owner):
"""
:param page: ChromiumBase对象
:param owner: ChromiumBase对象
"""
self._page = page
self._address = page.address
self._target_id = page._target_id
self._owner = owner
self._address = owner.address
self._target_id = owner._target_id
self._driver = None
self._running_requests = 0
self._running_targets = 0
@ -237,16 +237,16 @@ class Listener(object):
else:
return False
def _to_target(self, target_id, address, page):
def _to_target(self, target_id, address, owner):
"""切换监听的页面对象
:param target_id: 新页面对象_target_id
:param address: 新页面对象address
:param page: 新页面对象
:param owner: 新页面对象
:return: None
"""
self._target_id = target_id
self._address = address
self._page = page
self._owner = owner
debug = False
if self._driver:
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)):
self._running_targets += 1
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
if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None):
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._res_type is True or kwargs.get('type', '').upper() in self._res_type)):
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
break
@ -390,13 +390,13 @@ class Listener(object):
class FrameListener(Listener):
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
super()._requestWillBeSent(**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
super()._response_received(**kwargs)

@ -19,8 +19,8 @@ __RES_TYPE__ = Literal['Document', 'Stylesheet', 'Image', 'Media', 'Font', 'Scri
class Listener(object):
def __init__(self, page: ChromiumBase):
self._page: ChromiumBase = ...
def __init__(self, owner: ChromiumBase):
self._owner: ChromiumBase = ...
self._address: str = ...
self._target_id: str = ...
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 _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: ...
@ -92,8 +92,8 @@ class Listener(object):
class FrameListener(Listener):
def __init__(self, page: ChromiumFrame):
self._page: ChromiumFrame = ...
def __init__(self, owner: ChromiumFrame):
self._owner: ChromiumFrame = ...
self._is_diff: bool = ...

@ -113,8 +113,8 @@ class ElementRect(object):
class TabRect(object):
def __init__(self, page):
self._page = page
def __init__(self, owner):
self._owner = owner
@property
def window_state(self):
@ -170,17 +170,17 @@ class TabRect(object):
@property
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(' ')
return int(w), int(h)
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):
"""获取窗口范围信息"""
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):

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

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

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

@ -87,15 +87,15 @@ class Scroller(object):
if not self._wait_complete:
return
page = self._driver.owner if self._driver._type == 'ChromiumElement' else self._driver
r = page.run_cdp('Page.getLayoutMetrics')
owner = self._driver.owner if self._driver._type == 'ChromiumElement' else self._driver
r = owner.run_cdp('Page.getLayoutMetrics')
x = r['layoutViewport']['pageX']
y = r['layoutViewport']['pageY']
end_time = perf_counter() + page.timeout
end_time = perf_counter() + owner.timeout
while perf_counter() < end_time:
sleep(.1)
r = page.run_cdp('Page.getLayoutMetrics')
r = owner.run_cdp('Page.getLayoutMetrics')
x1 = r['layoutViewport']['pageX']
y1 = r['layoutViewport']['pageY']
@ -120,11 +120,11 @@ class ElementScroller(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.t2 = 'document.documentElement'

@ -51,7 +51,7 @@ class ElementScroller(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: ...

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

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

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

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

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

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