mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
继续修改备注
This commit is contained in:
parent
a484aa0c45
commit
8a6e225e02
@ -981,7 +981,7 @@ def find_by_xpath(ele, xpath, index, timeout, relative=True):
|
||||
res = ele.owner._run_cdp('Runtime.getProperties', objectId=res['result']['objectId'],
|
||||
ownProperties=True)['result'][:-1]
|
||||
if index is None:
|
||||
r = ChromiumElementsList(page=ele.owner)
|
||||
r = ChromiumElementsList(owner=ele.owner)
|
||||
for i in res:
|
||||
if i['value']['type'] == 'object':
|
||||
r.append(make_chromium_eles(ele.owner, _ids=i['value']['objectId'], is_obj_id=True))
|
||||
@ -1010,7 +1010,7 @@ def find_by_xpath(ele, xpath, index, timeout, relative=True):
|
||||
|
||||
if result:
|
||||
return result
|
||||
return NoneElement(ele.owner) if index is not None else ChromiumElementsList(page=ele.owner)
|
||||
return NoneElement(ele.owner) if index is not None else ChromiumElementsList(owner=ele.owner)
|
||||
|
||||
|
||||
def find_by_css(ele, selector, index, timeout):
|
||||
@ -1049,7 +1049,7 @@ def find_by_css(ele, selector, index, timeout):
|
||||
|
||||
if result:
|
||||
return result
|
||||
return NoneElement(ele.owner) if index is not None else ChromiumElementsList(page=ele.owner)
|
||||
return NoneElement(ele.owner) if index is not None else ChromiumElementsList(owner=ele.owner)
|
||||
|
||||
|
||||
def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=False):
|
||||
@ -1073,7 +1073,7 @@ def make_chromium_eles(page, _ids, index=1, is_obj_id=True, ele_only=False):
|
||||
return get_node_func(page, obj_id, ele_only)
|
||||
|
||||
else: # 获取全部
|
||||
nodes = ChromiumElementsList(page=page)
|
||||
nodes = ChromiumElementsList(owner=page)
|
||||
for obj_id in _ids:
|
||||
# if obj_id == 0:
|
||||
# continue
|
||||
|
@ -266,7 +266,7 @@ def make_session_ele(html_or_ele, loc=None, index=1, method=None):
|
||||
|
||||
# 把lxml元素对象包装成SessionElement对象并按需要返回一个或全部
|
||||
if index is None:
|
||||
r = SessionElementsList(page=page)
|
||||
r = SessionElementsList(owner=page)
|
||||
for e in eles:
|
||||
if e != '\n':
|
||||
r.append(SessionElement(e, page) if isinstance(e, HtmlElement) else e)
|
||||
|
@ -42,10 +42,6 @@ class ChromiumBase(BasePage):
|
||||
"""标签页、Frame、Page基类"""
|
||||
|
||||
def __init__(self, browser, target_id=None):
|
||||
"""
|
||||
:param browser: Chromium
|
||||
:param target_id: 要控制的target id,不指定默认为激活的标签页
|
||||
"""
|
||||
super().__init__()
|
||||
self._browser = browser
|
||||
self._is_loading = None
|
||||
@ -72,14 +68,13 @@ class ChromiumBase(BasePage):
|
||||
self._d_set_runtime_settings()
|
||||
self._connect_browser(target_id)
|
||||
|
||||
def __call__(self, locator, index=1, timeout=None):
|
||||
return self.ele(locator, index, timeout)
|
||||
|
||||
def _d_set_runtime_settings(self):
|
||||
pass
|
||||
|
||||
def _connect_browser(self, target_id=None):
|
||||
"""连接浏览器,在第一次时运行
|
||||
:param target_id: 要控制的target id,不指定默认为激活的标签页
|
||||
:return: None
|
||||
"""
|
||||
self._is_reading = False
|
||||
|
||||
if not target_id:
|
||||
@ -109,10 +104,6 @@ class ChromiumBase(BasePage):
|
||||
self._ready_state = 'complete'
|
||||
|
||||
def _driver_init(self, target_id):
|
||||
"""新建页面、页面刷新后要进行的cdp参数初始化
|
||||
:param target_id: 要跳转到的target id
|
||||
:return: None
|
||||
"""
|
||||
self._is_loading = True
|
||||
self._driver = self.browser._get_driver(target_id, self)
|
||||
|
||||
@ -139,10 +130,6 @@ class ChromiumBase(BasePage):
|
||||
self._driver.set_callback('Page.frameDetached', self._onFrameDetached)
|
||||
|
||||
def _get_document(self, timeout=10):
|
||||
"""获取页面文档
|
||||
:param timeout: 超时时间(秒)
|
||||
:return: 是否获取成功
|
||||
"""
|
||||
if self._is_reading:
|
||||
return
|
||||
self._is_reading = True
|
||||
@ -185,7 +172,6 @@ class ChromiumBase(BasePage):
|
||||
self.browser._frames[kwargs['frameId']] = self.tab_id
|
||||
|
||||
def _onFrameStartedLoading(self, **kwargs):
|
||||
"""页面开始加载时执行"""
|
||||
self.browser._frames[kwargs['frameId']] = self.tab_id
|
||||
if kwargs['frameId'] == self._frame_id:
|
||||
self._doc_got = False
|
||||
@ -198,14 +184,12 @@ class ChromiumBase(BasePage):
|
||||
t.start()
|
||||
|
||||
def _onFrameNavigated(self, **kwargs):
|
||||
"""页面跳转时执行"""
|
||||
if kwargs['frame']['id'] == self._frame_id:
|
||||
self._doc_got = False
|
||||
self._ready_state = 'loading'
|
||||
self._is_loading = True
|
||||
|
||||
def _onDomContentEventFired(self, **kwargs):
|
||||
"""在页面刷新、变化后重新读取页面内容"""
|
||||
if self._load_mode == 'eager':
|
||||
self._run_cdp('Page.stopLoading')
|
||||
if self._get_document(self._load_end_time - perf_counter() - .1):
|
||||
@ -213,13 +197,11 @@ class ChromiumBase(BasePage):
|
||||
self._ready_state = 'interactive'
|
||||
|
||||
def _onLoadEventFired(self, **kwargs):
|
||||
"""在页面刷新、变化后重新读取页面内容"""
|
||||
if self._doc_got is False and self._get_document(self._load_end_time - perf_counter() - .1):
|
||||
self._doc_got = True
|
||||
self._ready_state = 'complete'
|
||||
|
||||
def _onFrameStoppedLoading(self, **kwargs):
|
||||
"""页面加载完成后执行"""
|
||||
self.browser._frames[kwargs['frameId']] = self.tab_id
|
||||
if kwargs['frameId'] == self._frame_id:
|
||||
if self._doc_got is False:
|
||||
@ -227,7 +209,6 @@ class ChromiumBase(BasePage):
|
||||
self._ready_state = 'complete'
|
||||
|
||||
def _onFileChooserOpened(self, **kwargs):
|
||||
"""文件选择框打开时执行"""
|
||||
if self._upload_list:
|
||||
if 'backendNodeId' not in kwargs:
|
||||
raise TypeError('该输入框无法接管,请改用对<input>元素输入路径的方法设置。')
|
||||
@ -238,18 +219,7 @@ class ChromiumBase(BasePage):
|
||||
self._run_cdp('Page.setInterceptFileChooserDialog', enabled=False)
|
||||
self._upload_list = None
|
||||
|
||||
def __call__(self, locator, index=1, timeout=None):
|
||||
"""在内部查找元素
|
||||
例:ele = page('@id=ele_id')
|
||||
:param locator: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 超时时间(秒)
|
||||
:return: ChromiumElement对象
|
||||
"""
|
||||
return self.ele(locator, index, timeout)
|
||||
|
||||
def _wait_to_stop(self):
|
||||
"""eager策略超时时使页面停止加载"""
|
||||
end_time = perf_counter() + self.timeouts.page_load
|
||||
while perf_counter() < end_time:
|
||||
sleep(.1)
|
||||
@ -259,28 +229,24 @@ class ChromiumBase(BasePage):
|
||||
# ----------挂件----------
|
||||
@property
|
||||
def wait(self):
|
||||
"""返回用于等待的对象"""
|
||||
if self._wait is None:
|
||||
self._wait = BaseWaiter(self)
|
||||
return self._wait
|
||||
|
||||
@property
|
||||
def set(self):
|
||||
"""返回用于设置的对象"""
|
||||
if self._set is None:
|
||||
self._set = ChromiumBaseSetter(self)
|
||||
return self._set
|
||||
|
||||
@property
|
||||
def screencast(self):
|
||||
"""返回用于录屏的对象"""
|
||||
if self._screencast is None:
|
||||
self._screencast = Screencast(self)
|
||||
return self._screencast
|
||||
|
||||
@property
|
||||
def actions(self):
|
||||
"""返回用于执行动作链的对象"""
|
||||
if self._actions is None:
|
||||
self._actions = Actions(self)
|
||||
self.wait.doc_loaded()
|
||||
@ -288,21 +254,18 @@ class ChromiumBase(BasePage):
|
||||
|
||||
@property
|
||||
def listen(self):
|
||||
"""返回用于聆听数据包的对象"""
|
||||
if self._listener is None:
|
||||
self._listener = Listener(self)
|
||||
return self._listener
|
||||
|
||||
@property
|
||||
def states(self):
|
||||
"""返回用于获取状态信息的对象"""
|
||||
if self._states is None:
|
||||
self._states = PageStates(self)
|
||||
return self._states
|
||||
|
||||
@property
|
||||
def scroll(self):
|
||||
"""返回用于滚动滚动条的对象"""
|
||||
self.wait.doc_loaded()
|
||||
if self._scroll is None:
|
||||
self._scroll = PageScroller(self)
|
||||
@ -310,7 +273,6 @@ class ChromiumBase(BasePage):
|
||||
|
||||
@property
|
||||
def rect(self):
|
||||
"""返回获取窗口坐标和大小的对象"""
|
||||
# self.wait.doc_loaded()
|
||||
if self._rect is None:
|
||||
self._rect = TabRect(self)
|
||||
@ -318,19 +280,16 @@ class ChromiumBase(BasePage):
|
||||
|
||||
@property
|
||||
def console(self):
|
||||
"""返回获取控制台信息的对象"""
|
||||
if self._console is None:
|
||||
self._console = Console(self)
|
||||
return self._console
|
||||
|
||||
@property
|
||||
def timeout(self):
|
||||
"""返回timeout设置"""
|
||||
return self._timeouts.base
|
||||
|
||||
@property
|
||||
def timeouts(self):
|
||||
"""返回timeouts设置"""
|
||||
return self._timeouts
|
||||
|
||||
# ----------挂件结束----------
|
||||
@ -341,35 +300,29 @@ class ChromiumBase(BasePage):
|
||||
|
||||
@property
|
||||
def driver(self):
|
||||
"""返回用于控制浏览器的Driver对象"""
|
||||
if self._driver is None:
|
||||
raise RuntimeError('浏览器已关闭或链接已断开。')
|
||||
return self._driver
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
"""返回当前页面title"""
|
||||
return self._run_cdp_loaded('Target.getTargetInfo', targetId=self._target_id)['targetInfo']['title']
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
"""返回当前页面url"""
|
||||
return self._run_cdp_loaded('Target.getTargetInfo', targetId=self._target_id)['targetInfo']['url']
|
||||
|
||||
@property
|
||||
def _browser_url(self):
|
||||
"""用于被MixTab覆盖"""
|
||||
return self.url
|
||||
|
||||
@property
|
||||
def html(self):
|
||||
"""返回当前页面html文本"""
|
||||
self.wait.doc_loaded()
|
||||
return self._run_cdp('DOM.getOuterHTML', objectId=self._root_id)['outerHTML']
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
"""当返回内容是json格式时,返回对应的字典,非json格式时返回None"""
|
||||
try:
|
||||
return loads(self('t:pre', timeout=.5).text)
|
||||
except JSONDecodeError:
|
||||
@ -377,37 +330,30 @@ class ChromiumBase(BasePage):
|
||||
|
||||
@property
|
||||
def tab_id(self):
|
||||
"""返回当前标签页id"""
|
||||
return self._target_id
|
||||
|
||||
@property
|
||||
def _target_id(self):
|
||||
"""返回当前标签页id"""
|
||||
return self.driver.id if self.driver.is_running else ''
|
||||
|
||||
@property
|
||||
def active_ele(self):
|
||||
"""返回当前焦点所在元素"""
|
||||
return self._run_js_loaded('return document.activeElement;')
|
||||
|
||||
@property
|
||||
def load_mode(self):
|
||||
"""返回页面加载策略,有3种:'none'、'normal'、'eager'"""
|
||||
return self._load_mode
|
||||
|
||||
@property
|
||||
def user_agent(self):
|
||||
"""返回user agent"""
|
||||
return self._run_cdp('Runtime.evaluate', expression='navigator.userAgent;')['result']['value']
|
||||
|
||||
@property
|
||||
def upload_list(self):
|
||||
"""返回等待上传文件列表"""
|
||||
return self._upload_list
|
||||
|
||||
@property
|
||||
def _js_ready_state(self):
|
||||
"""返回js获取的ready state信息"""
|
||||
try:
|
||||
return self._run_cdp('Runtime.evaluate', expression='document.readyState;', _timeout=3)['result']['value']
|
||||
except ContextLostError:
|
||||
@ -416,114 +362,47 @@ class ChromiumBase(BasePage):
|
||||
return 'timeout'
|
||||
|
||||
def run_cdp(self, cmd, **cmd_args):
|
||||
"""执行Chrome DevTools Protocol语句
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
r = self.driver.run(cmd, **cmd_args)
|
||||
return r if __ERROR__ not in r else raise_error(r, user=True)
|
||||
|
||||
def run_cdp_loaded(self, cmd, **cmd_args):
|
||||
"""执行Chrome DevTools Protocol语句,执行前等待页面加载完毕
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
self.wait.doc_loaded()
|
||||
r = self.driver.run(cmd, **cmd_args)
|
||||
return r if __ERROR__ not in r else raise_error(r, user=True)
|
||||
|
||||
def _run_cdp(self, cmd, **cmd_args):
|
||||
"""执行Chrome DevTools Protocol语句
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
ignore = cmd_args.pop('_ignore', None)
|
||||
r = self.driver.run(cmd, **cmd_args)
|
||||
return r if __ERROR__ not in r else raise_error(r, ignore)
|
||||
|
||||
def _run_cdp_loaded(self, cmd, **cmd_args):
|
||||
"""执行Chrome DevTools Protocol语句,执行前等待页面加载完毕
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
self.wait.doc_loaded()
|
||||
return self._run_cdp(cmd, **cmd_args)
|
||||
|
||||
def run_js(self, script, *args, as_expr=False, timeout=None):
|
||||
"""运行javascript代码
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script设置
|
||||
:return: 运行的结果
|
||||
"""
|
||||
return self._run_js(script, *args, as_expr=as_expr, timeout=timeout)
|
||||
|
||||
def run_js_loaded(self, script, *args, as_expr=False, timeout=None):
|
||||
"""运行javascript代码,执行前等待页面加载完毕
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script属性值
|
||||
:return: 运行的结果
|
||||
"""
|
||||
self.wait.doc_loaded()
|
||||
return self._run_js(script, *args, as_expr=as_expr, timeout=timeout)
|
||||
|
||||
def _run_js(self, script, *args, as_expr=False, timeout=None):
|
||||
"""运行javascript代码
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script设置
|
||||
:return: 运行的结果
|
||||
"""
|
||||
return run_js(self, script, as_expr, self.timeouts.script if timeout is None else timeout, args)
|
||||
|
||||
def _run_js_loaded(self, script, *args, as_expr=False, timeout=None):
|
||||
"""运行javascript代码,执行前等待页面加载完毕
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script属性值
|
||||
:return: 运行的结果
|
||||
"""
|
||||
self.wait.doc_loaded()
|
||||
return run_js(self, script, as_expr, self.timeouts.script if timeout is None else timeout, args)
|
||||
|
||||
def run_async_js(self, script, *args, as_expr=False):
|
||||
"""以异步方式执行js代码或js文件路径
|
||||
:param script: js文本
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:return: None
|
||||
"""
|
||||
run_js(self, script, as_expr, 0, args)
|
||||
|
||||
def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None):
|
||||
"""访问url
|
||||
:param url: 目标url
|
||||
:param show_errmsg: 是否显示和抛出异常
|
||||
:param retry: 重试次数,为None时使用页面对象retry_times属性值
|
||||
:param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值
|
||||
:param timeout: 连接超时时间(秒),为None时使用页面对象timeouts.page_load属性值
|
||||
:return: 目标url是否可用
|
||||
"""
|
||||
retry, interval, is_file = self._before_connect(url, retry, interval)
|
||||
self._url_available = self._d_connect(self._url, times=retry, interval=interval,
|
||||
show_errmsg=show_errmsg, timeout=timeout)
|
||||
return self._url_available
|
||||
|
||||
def cookies(self, all_domains=False, all_info=False):
|
||||
"""返回cookies信息
|
||||
:param all_domains: 是否返回所有域的cookies
|
||||
:param all_info: 是否返回所有信息,为False时只返回name、value、domain
|
||||
:return: cookies信息
|
||||
"""
|
||||
txt = 'Storage' if all_domains else 'Network'
|
||||
cookies = self._run_cdp_loaded(f'{txt}.getCookies')['cookies']
|
||||
|
||||
@ -535,51 +414,21 @@ class ChromiumBase(BasePage):
|
||||
return CookiesList(r)
|
||||
|
||||
def ele(self, locator, index=1, timeout=None):
|
||||
"""获取一个符合条件的元素对象
|
||||
:param locator: 定位符或元素对象
|
||||
:param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 查找超时时间(秒),默认与页面等待时间一致
|
||||
:return: ChromiumElement对象
|
||||
"""
|
||||
return self._ele(locator, timeout=timeout, index=index, method='ele()')
|
||||
|
||||
def eles(self, locator, timeout=None):
|
||||
"""获取所有符合条件的元素对象
|
||||
:param locator: 定位符或元素对象
|
||||
:param timeout: 查找超时时间(秒),默认与页面等待时间一致
|
||||
:return: ChromiumElement对象组成的列表
|
||||
"""
|
||||
return self._ele(locator, timeout=timeout, index=None)
|
||||
|
||||
def s_ele(self, locator=None, index=1, timeout=None):
|
||||
"""查找一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高
|
||||
:param locator: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param index: 获取第几个,从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 查找元素超时时间(秒),默认与页面等待时间一致
|
||||
:return: SessionElement对象或属性、文本
|
||||
"""
|
||||
return (NoneElement(self, method='s_ele()', args={'locator': locator, 'index': index})
|
||||
if locator and not self.wait.eles_loaded(locator, timeout=timeout)
|
||||
else make_session_ele(self, locator, index=index, method='s_ele()'))
|
||||
|
||||
def s_eles(self, locator, timeout=None):
|
||||
"""查找所有符合条件的元素以SessionElement列表形式返回
|
||||
:param locator: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param timeout: 查找元素超时时间(秒),默认与页面等待时间一致
|
||||
:return: SessionElement对象组成的列表
|
||||
"""
|
||||
return (make_session_ele(self, locator, index=None)
|
||||
if self.wait.eles_loaded(locator, timeout=timeout) else SessionElementsList())
|
||||
|
||||
def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None):
|
||||
"""执行元素查找
|
||||
:param locator: 定位符或元素对象
|
||||
:param timeout: 查找超时时间(秒)
|
||||
:param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有
|
||||
:param relative: MixTab用的表示是否相对定位的参数
|
||||
:param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置
|
||||
:return: ChromiumElement对象或元素对象组成的列表
|
||||
"""
|
||||
if isinstance(locator, (str, tuple)):
|
||||
loc = get_loc(locator)[1]
|
||||
elif locator._type in ('ChromiumElement', 'ChromiumFrame'):
|
||||
@ -645,33 +494,17 @@ class ChromiumBase(BasePage):
|
||||
return r
|
||||
|
||||
def refresh(self, ignore_cache=False):
|
||||
"""刷新当前页面
|
||||
:param ignore_cache: 是否忽略缓存
|
||||
:return: None
|
||||
"""
|
||||
self._is_loading = True
|
||||
self._run_cdp('Page.reload', ignoreCache=ignore_cache)
|
||||
self.wait.load_start()
|
||||
|
||||
def forward(self, steps=1):
|
||||
"""在浏览历史中前进若干步
|
||||
:param steps: 前进步数
|
||||
:return: None
|
||||
"""
|
||||
self._forward_or_back(steps)
|
||||
|
||||
def back(self, steps=1):
|
||||
"""在浏览历史中后退若干步
|
||||
:param steps: 后退步数
|
||||
:return: None
|
||||
"""
|
||||
self._forward_or_back(-steps)
|
||||
|
||||
def _forward_or_back(self, steps):
|
||||
"""执行浏览器前进或后退,会跳过url相同的历史记录
|
||||
:param steps: 步数
|
||||
:return: None
|
||||
"""
|
||||
if steps == 0:
|
||||
return
|
||||
|
||||
@ -694,7 +527,6 @@ class ChromiumBase(BasePage):
|
||||
self._run_cdp('Page.navigateToHistoryEntry', entryId=nid)
|
||||
|
||||
def stop_loading(self):
|
||||
"""页面停止加载"""
|
||||
try:
|
||||
self._run_cdp('Page.stopLoading')
|
||||
end_time = perf_counter() + 5
|
||||
@ -706,10 +538,6 @@ class ChromiumBase(BasePage):
|
||||
self._ready_state = 'complete'
|
||||
|
||||
def remove_ele(self, loc_or_ele):
|
||||
"""从页面上删除一个元素
|
||||
:param loc_or_ele: 元素对象或定位符
|
||||
:return: None
|
||||
"""
|
||||
if not loc_or_ele:
|
||||
return
|
||||
ele = self._ele(loc_or_ele, raise_err=False)
|
||||
@ -717,12 +545,6 @@ class ChromiumBase(BasePage):
|
||||
self._run_cdp('DOM.removeNode', nodeId=ele._node_id, _ignore=ElementLostError)
|
||||
|
||||
def add_ele(self, html_or_info, insert_to=None, before=None):
|
||||
"""新建一个元素
|
||||
:param html_or_info: 新元素的html文本或信息。信息格式为:(tag, {attr1: value, ...})
|
||||
:param insert_to: 插入到哪个元素中,可接收元素对象和定位符,为None且为html添加到body,不为html不插入
|
||||
:param before: 在哪个子节点前面插入,可接收对象和定位符,为None插入到父元素末尾
|
||||
:return: 元素对象
|
||||
"""
|
||||
if isinstance(html_or_info, str):
|
||||
insert_to = self.ele(insert_to) if insert_to else self.ele('t:body')
|
||||
args = [html_or_info, insert_to]
|
||||
@ -774,69 +596,33 @@ class ChromiumBase(BasePage):
|
||||
return ele
|
||||
|
||||
def get_frame(self, loc_ind_ele, timeout=None):
|
||||
"""获取页面中一个frame对象
|
||||
:param loc_ind_ele: 定位符、iframe序号、ChromiumFrame对象,序号从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 查找元素超时时间(秒)
|
||||
:return: ChromiumFrame对象
|
||||
"""
|
||||
return get_frame(self, loc_ind_ele=loc_ind_ele, timeout=timeout)
|
||||
|
||||
def get_frames(self, locator=None, timeout=None):
|
||||
"""获取所有符合条件的frame对象
|
||||
:param locator: 定位符,为None时返回所有
|
||||
:param timeout: 查找超时时间(秒)
|
||||
:return: ChromiumFrame对象组成的列表
|
||||
"""
|
||||
locator = locator or 'xpath://*[name()="iframe" or name()="frame"]'
|
||||
frames = self._ele(locator, timeout=timeout, index=None, raise_err=False)
|
||||
return [i for i in frames if i._type == 'ChromiumFrame']
|
||||
|
||||
def session_storage(self, item=None):
|
||||
"""返回sessionStorage信息,不设置item则获取全部
|
||||
:param item: 要获取的项,不设置则返回全部
|
||||
:return: sessionStorage一个或所有项内容
|
||||
"""
|
||||
js = f'sessionStorage.getItem("{item}")' if item else 'sessionStorage'
|
||||
return self._run_js_loaded(js, as_expr=True)
|
||||
|
||||
def local_storage(self, item=None):
|
||||
"""返回localStorage信息,不设置item则获取全部
|
||||
:param item: 要获取的项目,不设置则返回全部
|
||||
:return: localStorage一个或所有项内容
|
||||
"""
|
||||
js = f'localStorage.getItem("{item}")' if item else 'localStorage'
|
||||
return self._run_js_loaded(js, as_expr=True)
|
||||
|
||||
def get_screenshot(self, path=None, name=None, as_bytes=None, as_base64=None,
|
||||
full_page=False, left_top=None, right_bottom=None):
|
||||
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
||||
:param path: 保存路径
|
||||
:param name: 完整文件名,后缀可选 'jpg','jpeg','png','webp'
|
||||
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
||||
:param left_top: 截取范围左上角坐标
|
||||
:param right_bottom: 截取范围右下角角坐标
|
||||
:return: 图片完整路径或字节文本
|
||||
"""
|
||||
return self._get_screenshot(path=path, name=name, as_bytes=as_bytes, as_base64=as_base64,
|
||||
full_page=full_page, left_top=left_top, right_bottom=right_bottom)
|
||||
|
||||
def add_init_js(self, script):
|
||||
"""添加初始化脚本,在页面加载任何脚本前执行
|
||||
:param script: js文本
|
||||
:return: 添加的脚本的id
|
||||
"""
|
||||
js_id = self._run_cdp('Page.addScriptToEvaluateOnNewDocument', source=script,
|
||||
includeCommandLineAPI=True)['identifier']
|
||||
self._init_jss.append(js_id)
|
||||
return js_id
|
||||
|
||||
def remove_init_js(self, script_id=None):
|
||||
"""删除初始化脚本,js_id传入None时删除所有
|
||||
:param script_id: 脚本的id
|
||||
:return: None
|
||||
"""
|
||||
if script_id is None:
|
||||
for js_id in self._init_jss:
|
||||
self._run_cdp('Page.removeScriptToEvaluateOnNewDocument', identifier=js_id)
|
||||
@ -847,13 +633,6 @@ class ChromiumBase(BasePage):
|
||||
self._init_jss.remove(script_id)
|
||||
|
||||
def clear_cache(self, session_storage=True, local_storage=True, cache=True, cookies=True):
|
||||
"""清除缓存,可选要清除的项
|
||||
:param session_storage: 是否清除sessionStorage
|
||||
:param local_storage: 是否清除localStorage
|
||||
:param cache: 是否清除cache
|
||||
:param cookies: 是否清除cookies
|
||||
:return: None
|
||||
"""
|
||||
if session_storage or local_storage:
|
||||
self._run_cdp_loaded('DOMStorage.enable')
|
||||
i = self._run_cdp('Storage.getStorageKeyForFrame', frameId=self._frame_id)['storageKey']
|
||||
@ -870,16 +649,11 @@ class ChromiumBase(BasePage):
|
||||
self._run_cdp_loaded('Network.clearBrowserCookies')
|
||||
|
||||
def disconnect(self):
|
||||
"""断开与页面的连接,不关闭页面"""
|
||||
if self._driver:
|
||||
self._driver.stop()
|
||||
self.browser._all_drivers.get(self._driver.id, set()).discard(self._driver)
|
||||
|
||||
def reconnect(self, wait=0):
|
||||
"""断开与页面原来的页面,重新建立连接
|
||||
:param wait: 断开后等待若干秒再连接
|
||||
:return: None
|
||||
"""
|
||||
t_id = self._target_id
|
||||
self.disconnect()
|
||||
sleep(wait)
|
||||
@ -889,13 +663,6 @@ class ChromiumBase(BasePage):
|
||||
self._get_document()
|
||||
|
||||
def handle_alert(self, accept=True, send=None, timeout=None, next_one=False):
|
||||
"""处理提示框,可以自动等待提示框出现
|
||||
:param accept: True表示确认,False表示取消,为None不会按按钮但依然返回文本值
|
||||
:param send: 处理prompt提示框时可输入文本
|
||||
:param timeout: 等待提示框出现的超时时间(秒),为None则使用self.timeout属性的值
|
||||
:param next_one: 是否处理下一个出现的提示框,为True时timeout参数无效
|
||||
:return: 提示框内容文本,未等到提示框则返回False
|
||||
"""
|
||||
r = self._handle_alert(accept=accept, send=send, timeout=timeout, next_one=next_one)
|
||||
if not isinstance(accept, bool):
|
||||
return r
|
||||
@ -904,13 +671,6 @@ class ChromiumBase(BasePage):
|
||||
return r
|
||||
|
||||
def _handle_alert(self, accept=True, send=None, timeout=None, next_one=False):
|
||||
"""处理提示框,可以自动等待提示框出现
|
||||
:param accept: True表示确认,False表示取消,其它值不会按按钮但依然返回文本值
|
||||
:param send: 处理prompt提示框时可输入文本
|
||||
:param timeout: 等待提示框出现的超时时间(秒),为None则使用self.timeout属性的值
|
||||
:param next_one: 是否处理下一个出现的提示框,为True时timeout参数无效
|
||||
:return: 提示框内容文本,未等到提示框则返回False
|
||||
"""
|
||||
if next_one:
|
||||
self._alert.handle_next = accept
|
||||
self._alert.next_text = send
|
||||
@ -934,7 +694,6 @@ class ChromiumBase(BasePage):
|
||||
return res_text
|
||||
|
||||
def _on_alert_open(self, **kwargs):
|
||||
"""alert出现时触发的方法"""
|
||||
self._alert.activated = True
|
||||
self._alert.text = kwargs['message']
|
||||
self._alert.type = kwargs['type']
|
||||
@ -952,7 +711,6 @@ class ChromiumBase(BasePage):
|
||||
self._alert.handle_next = None
|
||||
|
||||
def _on_alert_close(self, **kwargs):
|
||||
"""alert关闭时触发的方法"""
|
||||
self._alert.activated = False
|
||||
self._alert.text = None
|
||||
self._alert.type = None
|
||||
@ -962,10 +720,6 @@ class ChromiumBase(BasePage):
|
||||
self._has_alert = False
|
||||
|
||||
def _wait_loaded(self, timeout=None):
|
||||
"""等待页面加载完成,超时触发停止加载
|
||||
:param timeout: 超时时间(秒)
|
||||
:return: 是否成功,超时返回False
|
||||
"""
|
||||
timeout = timeout if timeout is not None else self.timeouts.page_load
|
||||
end_time = perf_counter() + timeout
|
||||
while perf_counter() < end_time:
|
||||
@ -984,14 +738,6 @@ class ChromiumBase(BasePage):
|
||||
return False
|
||||
|
||||
def _d_connect(self, to_url, times=0, interval=1, show_errmsg=False, timeout=None):
|
||||
"""尝试连接,重试若干次
|
||||
:param to_url: 要访问的url
|
||||
:param times: 重试次数
|
||||
:param interval: 重试间隔(秒)
|
||||
:param show_errmsg: 是否抛出异常
|
||||
:param timeout: 连接超时时间(秒)
|
||||
:return: 是否成功,返回None表示不确定
|
||||
"""
|
||||
err = None
|
||||
self._is_loading = True
|
||||
timeout = timeout if timeout is not None else self.timeouts.page_load
|
||||
@ -1041,17 +787,6 @@ class ChromiumBase(BasePage):
|
||||
|
||||
def _get_screenshot(self, path=None, name=None, as_bytes=None, as_base64=None,
|
||||
full_page=False, left_top=None, right_bottom=None, ele=None):
|
||||
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
||||
:param path: 保存路径
|
||||
:param name: 完整文件名,后缀可选 'jpg','jpeg','png','webp'
|
||||
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
||||
:param left_top: 截取范围左上角坐标
|
||||
:param right_bottom: 截取范围右下角角坐标
|
||||
:param ele: 为异域iframe内元素截图设置
|
||||
:return: 图片完整路径或字节文本
|
||||
"""
|
||||
if as_bytes:
|
||||
if as_bytes is True:
|
||||
pic_type = 'png'
|
||||
@ -1132,11 +867,6 @@ class Timeout(object):
|
||||
"""用于保存d模式timeout信息的类"""
|
||||
|
||||
def __init__(self, base=None, page_load=None, script=None):
|
||||
"""
|
||||
:param base: 默认超时时间
|
||||
:param page_load: 页面加载超时时间
|
||||
:param script: js超时时间
|
||||
"""
|
||||
self.base = 10 if base is None else base
|
||||
self.page_load = 30 if page_load is None else page_load
|
||||
self.script = 30 if script is None else script
|
||||
|
@ -17,7 +17,6 @@ from .._elements.session_element import SessionElement
|
||||
from .._functions.cookies import CookiesList
|
||||
from .._functions.elements import SessionElementsList, ChromiumElementsList
|
||||
from .._pages.chromium_frame import ChromiumFrame
|
||||
from .._pages.chromium_page import ChromiumPage
|
||||
from .._units.actions import Actions
|
||||
from .._units.console import Console
|
||||
from .._units.listener import Listener
|
||||
@ -32,287 +31,624 @@ PIC_TYPE = Literal['jpg', 'jpeg', 'png', 'webp', True]
|
||||
|
||||
|
||||
class ChromiumBase(BasePage):
|
||||
_tab: Union[ChromiumTab, MixTab, ChromiumFrame] = ...
|
||||
_browser: Chromium = ...
|
||||
_driver: Optional[Driver] = ...
|
||||
_frame_id: str = ...
|
||||
_is_reading: bool = ...
|
||||
_is_timeout: bool = ...
|
||||
_timeouts: Timeout = ...
|
||||
_first_run: bool = ...
|
||||
_is_loading: Optional[bool] = ...
|
||||
_load_mode: str = ...
|
||||
_scroll: Optional[Scroller] = ...
|
||||
_url: str = ...
|
||||
_root_id: Optional[str] = ...
|
||||
_upload_list: Optional[list] = ...
|
||||
_wait: Optional[BaseWaiter] = ...
|
||||
_set: Optional[ChromiumBaseSetter] = ...
|
||||
_screencast: Optional[Screencast] = ...
|
||||
_actions: Optional[Actions] = ...
|
||||
_listener: Optional[Listener] = ...
|
||||
_states: Optional[PageStates] = ...
|
||||
_alert: Alert = ...
|
||||
_has_alert: bool = ...
|
||||
_doc_got: bool = ...
|
||||
_load_end_time: float = ...
|
||||
_init_jss: list = ...
|
||||
_ready_state: Optional[str] = ...
|
||||
_rect: Optional[TabRect] = ...
|
||||
_console: Optional[Console] = ...
|
||||
_type: str = ...
|
||||
def __init__(self,
|
||||
browser: Chromium,
|
||||
tab_id: str = None):
|
||||
self._tab: Union[ChromiumTab, MixTab, ChromiumFrame] = ...
|
||||
self._browser: Chromium = ...
|
||||
self._driver: Driver = ...
|
||||
self._frame_id: str = ...
|
||||
self._is_reading: bool = ...
|
||||
self._is_timeout: bool = ...
|
||||
self._timeouts: Timeout = ...
|
||||
self._first_run: bool = ...
|
||||
self._is_loading: bool = ...
|
||||
self._load_mode: str = ...
|
||||
self._scroll: Scroller = ...
|
||||
self._url: str = ...
|
||||
self._root_id: str = ...
|
||||
self._upload_list: list = ...
|
||||
self._wait: BaseWaiter = ...
|
||||
self._set: ChromiumBaseSetter = ...
|
||||
self._screencast: Screencast = ...
|
||||
self._actions: Actions = ...
|
||||
self._listener: Listener = ...
|
||||
self._states: PageStates = ...
|
||||
self._alert: Alert = ...
|
||||
self._has_alert: bool = ...
|
||||
self._doc_got: bool = ...
|
||||
self._load_end_time: float = ...
|
||||
self._init_jss: list = ...
|
||||
self._ready_state: Optional[str] = ...
|
||||
self._rect: TabRect = ...
|
||||
self._console: Console = ...
|
||||
self._type: str = ...
|
||||
"""
|
||||
:param browser: Chromium
|
||||
:param target_id: 要控制的target id,不指定默认为激活的标签页
|
||||
"""
|
||||
...
|
||||
|
||||
def _connect_browser(self, target_id: str = None) -> None: ...
|
||||
def __call__(self,
|
||||
locator: Union[Tuple[str, str], str, ChromiumElement],
|
||||
index: int = 1,
|
||||
timeout: float = None) -> ChromiumElement:
|
||||
"""在内部查找元素
|
||||
例:ele = page('@id=ele_id')
|
||||
:param locator: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 超时时间(秒)
|
||||
:return: ChromiumElement对象
|
||||
"""
|
||||
...
|
||||
|
||||
def _driver_init(self, target_id: str) -> None: ...
|
||||
def _d_set_runtime_settings(self) -> None: ...
|
||||
|
||||
def _get_document(self, timeout: float = 10) -> bool: ...
|
||||
def _connect_browser(self, target_id: str = None) -> None:
|
||||
"""连接浏览器,在第一次时运行
|
||||
:param target_id: 要控制的target id,不指定默认为激活的标签页
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _wait_loaded(self, timeout: float = None) -> bool: ...
|
||||
def _driver_init(self, target_id: str) -> None:
|
||||
"""新建页面、页面刷新后要进行的cdp参数初始化
|
||||
:param target_id: 要跳转到的target id
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _get_document(self, timeout: float = 10) -> bool:
|
||||
"""获取页面文档
|
||||
:param timeout: 超时时间(秒)
|
||||
:return: 是否获取成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _onFrameDetached(self, **kwargs) -> None: ...
|
||||
|
||||
def _onFrameAttached(self, **kwargs) -> None: ...
|
||||
|
||||
def _onFrameStartedLoading(self, **kwargs): ...
|
||||
def _onFrameStartedLoading(self, **kwargs):
|
||||
"""页面开始加载时执行"""
|
||||
...
|
||||
|
||||
def _onFrameNavigated(self, **kwargs): ...
|
||||
def _onFrameNavigated(self, **kwargs):
|
||||
"""页面跳转时执行"""
|
||||
...
|
||||
|
||||
def _onDomContentEventFired(self, **kwargs): ...
|
||||
def _onDomContentEventFired(self, **kwargs):
|
||||
"""在页面刷新、变化后重新读取页面内容"""
|
||||
...
|
||||
|
||||
def _onLoadEventFired(self, **kwargs): ...
|
||||
def _onLoadEventFired(self, **kwargs):
|
||||
"""在页面刷新、变化后重新读取页面内容"""
|
||||
...
|
||||
|
||||
def _onFrameStoppedLoading(self, **kwargs): ...
|
||||
def _onFrameStoppedLoading(self, **kwargs):
|
||||
"""页面加载完成后执行"""
|
||||
...
|
||||
|
||||
def _onFileChooserOpened(self, **kwargs): ...
|
||||
def _onFileChooserOpened(self, **kwargs):
|
||||
"""文件选择框打开时执行"""
|
||||
...
|
||||
|
||||
def _wait_to_stop(self): ...
|
||||
|
||||
# def _d_set_start_options(self, address) -> None: ...
|
||||
|
||||
def _d_set_runtime_settings(self) -> None: ...
|
||||
|
||||
def __call__(self,
|
||||
locator: Union[Tuple[str, str], str, ChromiumElement],
|
||||
index: int = 1,
|
||||
timeout: float = None) -> ChromiumElement: ...
|
||||
def _wait_to_stop(self):
|
||||
"""eager策略超时时使页面停止加载"""
|
||||
...
|
||||
|
||||
@property
|
||||
def _js_ready_state(self) -> str: ...
|
||||
def wait(self) -> BaseWaiter:
|
||||
"""返回用于等待的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def browser(self) -> Chromium: ...
|
||||
def set(self) -> ChromiumBaseSetter:
|
||||
"""返回用于设置的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def title(self) -> str: ...
|
||||
def screencast(self) -> Screencast:
|
||||
"""返回用于录屏的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def driver(self) -> Driver: ...
|
||||
def actions(self) -> Actions:
|
||||
"""返回用于执行动作链的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def url(self) -> str: ...
|
||||
def listen(self) -> Listener:
|
||||
"""返回用于聆听数据包的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def _browser_url(self) -> str: ...
|
||||
def states(self) -> PageStates:
|
||||
"""返回用于获取状态信息的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def html(self) -> str: ...
|
||||
def scroll(self) -> PageScroller:
|
||||
"""返回用于滚动滚动条的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def json(self) -> Union[dict, None]: ...
|
||||
def rect(self) -> TabRect:
|
||||
"""返回获取窗口坐标和大小的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def _target_id(self) -> str: ...
|
||||
def console(self) -> Console:
|
||||
"""返回获取控制台信息的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def tab_id(self) -> str: ...
|
||||
def timeout(self) -> float:
|
||||
"""返回timeout设置"""
|
||||
...
|
||||
|
||||
@property
|
||||
def active_ele(self) -> ChromiumElement: ...
|
||||
def timeouts(self) -> Timeout:
|
||||
"""返回timeouts设置"""
|
||||
...
|
||||
|
||||
@property
|
||||
def load_mode(self) -> str: ...
|
||||
def browser(self) -> Chromium:
|
||||
"""返回浏览器对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def user_agent(self) -> str: ...
|
||||
def driver(self) -> Driver:
|
||||
"""返回用于控制浏览器的Driver对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def scroll(self) -> PageScroller: ...
|
||||
def title(self) -> str:
|
||||
"""返回当前页面title"""
|
||||
...
|
||||
|
||||
@property
|
||||
def rect(self) -> TabRect: ...
|
||||
def url(self) -> str:
|
||||
"""返回当前页面url"""
|
||||
...
|
||||
|
||||
@property
|
||||
def console(self) -> Console: ...
|
||||
def _browser_url(self) -> str:
|
||||
"""用于被MixTab覆盖"""
|
||||
...
|
||||
|
||||
@property
|
||||
def timeout(self) -> float: ...
|
||||
def html(self) -> str:
|
||||
"""返回当前页面html文本"""
|
||||
...
|
||||
|
||||
@property
|
||||
def timeouts(self) -> Timeout: ...
|
||||
def json(self) -> Union[dict, None]:
|
||||
"""当返回内容是json格式时,返回对应的字典,非json格式时返回None"""
|
||||
...
|
||||
|
||||
@property
|
||||
def upload_list(self) -> list: ...
|
||||
def tab_id(self) -> str:
|
||||
"""返回当前标签页id"""
|
||||
...
|
||||
|
||||
@property
|
||||
def wait(self) -> BaseWaiter: ...
|
||||
def _target_id(self) -> str:
|
||||
"""返回当前标签页id"""
|
||||
...
|
||||
|
||||
@property
|
||||
def set(self) -> ChromiumBaseSetter: ...
|
||||
def active_ele(self) -> ChromiumElement:
|
||||
"""返回当前焦点所在元素"""
|
||||
...
|
||||
|
||||
@property
|
||||
def screencast(self) -> Screencast: ...
|
||||
def load_mode(self) -> Literal['none', 'normal', 'eager']:
|
||||
"""返回页面加载策略,有3种:'none'、'normal'、'eager'"""
|
||||
...
|
||||
|
||||
@property
|
||||
def actions(self) -> Actions: ...
|
||||
def user_agent(self) -> str:
|
||||
"""返回user agent"""
|
||||
...
|
||||
|
||||
@property
|
||||
def listen(self) -> Listener: ...
|
||||
def upload_list(self) -> list:
|
||||
"""返回等待上传文件列表"""
|
||||
...
|
||||
|
||||
@property
|
||||
def states(self) -> PageStates: ...
|
||||
def _js_ready_state(self) -> str:
|
||||
"""返回js获取的ready state信息"""
|
||||
...
|
||||
|
||||
def run_js(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any: ...
|
||||
def run_cdp(self, cmd: str, **cmd_args) -> dict:
|
||||
"""执行Chrome DevTools Protocol语句
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def run_js_loaded(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any: ...
|
||||
def run_cdp_loaded(self, cmd: str, **cmd_args) -> dict:
|
||||
"""执行Chrome DevTools Protocol语句,执行前等待页面加载完毕
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def _run_js(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any: ...
|
||||
def _run_cdp(self, cmd: str, **cmd_args) -> dict:
|
||||
"""执行Chrome DevTools Protocol语句
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def _run_js_loaded(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any: ...
|
||||
def _run_cdp_loaded(self, cmd: str, **cmd_args) -> dict:
|
||||
"""执行Chrome DevTools Protocol语句,执行前等待页面加载完毕
|
||||
:param cmd: 协议项目
|
||||
:param cmd_args: 参数
|
||||
:return: 执行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def run_async_js(self, script: Union[str, Path], *args, as_expr: bool = False) -> None: ...
|
||||
def run_js(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any:
|
||||
"""运行javascript代码
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script设置
|
||||
:return: 运行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def run_js_loaded(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any:
|
||||
"""运行javascript代码,执行前等待页面加载完毕
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script属性值
|
||||
:return: 运行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def _run_js(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any:
|
||||
"""运行javascript代码
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script设置
|
||||
:return: 运行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def _run_js_loaded(self, script: Union[str, Path], *args, as_expr: bool = False, timeout: float = None) -> Any:
|
||||
"""运行javascript代码,执行前等待页面加载完毕
|
||||
:param script: js文本或js文件路径
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:param timeout: js超时时间(秒),为None则使用页面timeouts.script属性值
|
||||
:return: 运行的结果
|
||||
"""
|
||||
...
|
||||
|
||||
def run_async_js(self, script: Union[str, Path], *args, as_expr: bool = False) -> None:
|
||||
"""以异步方式执行js代码或js文件路径
|
||||
:param script: js文本
|
||||
:param args: 参数,按顺序在js文本中对应arguments[0]、arguments[1]...
|
||||
:param as_expr: 是否作为表达式运行,为True时args无效
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def get(self, url: str, show_errmsg: bool = False, retry: int = None,
|
||||
interval: float = None, timeout: float = None) -> Union[None, bool]: ...
|
||||
interval: float = None, timeout: float = None) -> Union[None, bool]:
|
||||
"""访问url
|
||||
:param url: 目标url
|
||||
:param show_errmsg: 是否显示和抛出异常
|
||||
:param retry: 重试次数,为None时使用页面对象retry_times属性值
|
||||
:param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值
|
||||
:param timeout: 连接超时时间(秒),为None时使用页面对象timeouts.page_load属性值
|
||||
:return: 目标url是否可用
|
||||
"""
|
||||
...
|
||||
|
||||
def cookies(self, all_domains: bool = False, all_info: bool = False) -> CookiesList: ...
|
||||
def cookies(self, all_domains: bool = False, all_info: bool = False) -> CookiesList:
|
||||
"""返回cookies信息
|
||||
:param all_domains: 是否返回所有域的cookies
|
||||
:param all_info: 是否返回所有信息,为False时只返回name、value、domain
|
||||
:return: cookies信息
|
||||
"""
|
||||
...
|
||||
|
||||
def ele(self,
|
||||
locator: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame],
|
||||
index: int = 1,
|
||||
timeout: float = None) -> ChromiumElement: ...
|
||||
timeout: float = None) -> ChromiumElement:
|
||||
"""获取一个符合条件的元素对象
|
||||
:param locator: 定位符或元素对象
|
||||
:param index: 获取第几个元素,从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 查找超时时间(秒),默认与页面等待时间一致
|
||||
:return: ChromiumElement对象
|
||||
"""
|
||||
...
|
||||
|
||||
def eles(self,
|
||||
locator: Union[Tuple[str, str], str],
|
||||
timeout: float = None) -> ChromiumElementsList: ...
|
||||
timeout: float = None) -> ChromiumElementsList:
|
||||
"""获取所有符合条件的元素对象
|
||||
:param locator: 定位符或元素对象
|
||||
:param timeout: 查找超时时间(秒),默认与页面等待时间一致
|
||||
:return: ChromiumElement对象组成的列表
|
||||
"""
|
||||
...
|
||||
|
||||
def s_ele(self,
|
||||
locator: Union[Tuple[str, str], str] = None,
|
||||
index: int = 1,
|
||||
timeout: float = None) -> SessionElement: ...
|
||||
timeout: float = None) -> SessionElement:
|
||||
"""查找一个符合条件的元素以SessionElement形式返回,处理复杂页面时效率很高
|
||||
:param locator: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param index: 获取第几个,从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 查找元素超时时间(秒),默认与页面等待时间一致
|
||||
:return: SessionElement对象或属性、文本
|
||||
"""
|
||||
...
|
||||
|
||||
def s_eles(self,
|
||||
locator: Union[Tuple[str, str], str],
|
||||
timeout: float = None) -> SessionElementsList: ...
|
||||
timeout: float = None) -> SessionElementsList:
|
||||
"""查找所有符合条件的元素以SessionElement列表形式返回
|
||||
:param locator: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param timeout: 查找元素超时时间(秒),默认与页面等待时间一致
|
||||
:return: SessionElement对象组成的列表
|
||||
"""
|
||||
...
|
||||
|
||||
def _find_elements(self,
|
||||
locator: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame],
|
||||
timeout: float = None,
|
||||
index: Optional[int] = 1,
|
||||
relative: bool = False,
|
||||
raise_err: bool = None) -> Union[ChromiumElement, ChromiumFrame, ChromiumElementsList]: ...
|
||||
raise_err: bool = None) -> Union[ChromiumElement, ChromiumFrame, ChromiumElementsList]:
|
||||
"""执行元素查找
|
||||
:param locator: 定位符或元素对象
|
||||
:param timeout: 查找超时时间(秒)
|
||||
:param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有
|
||||
:param relative: MixTab用的表示是否相对定位的参数
|
||||
:param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置
|
||||
:return: ChromiumElement对象或元素对象组成的列表
|
||||
"""
|
||||
...
|
||||
|
||||
def refresh(self, ignore_cache: bool = False) -> None: ...
|
||||
def refresh(self, ignore_cache: bool = False) -> None:
|
||||
"""刷新当前页面
|
||||
:param ignore_cache: 是否忽略缓存
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def forward(self, steps: int = 1) -> None: ...
|
||||
def forward(self, steps: int = 1) -> None:
|
||||
"""在浏览历史中前进若干步
|
||||
:param steps: 前进步数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def back(self, steps: int = 1) -> None: ...
|
||||
def back(self, steps: int = 1) -> None:
|
||||
"""在浏览历史中后退若干步
|
||||
:param steps: 后退步数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _forward_or_back(self, steps: int) -> None: ...
|
||||
def _forward_or_back(self, steps: int) -> None:
|
||||
"""执行浏览器前进或后退,会跳过url相同的历史记录
|
||||
:param steps: 步数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def stop_loading(self) -> None: ...
|
||||
def stop_loading(self) -> None:
|
||||
"""页面停止加载"""
|
||||
...
|
||||
|
||||
def remove_ele(self, loc_or_ele: Union[ChromiumElement, ChromiumFrame, str, Tuple[str, str]]) -> None: ...
|
||||
def remove_ele(self, loc_or_ele: Union[ChromiumElement, ChromiumFrame, str, Tuple[str, str]]) -> None:
|
||||
"""从页面上删除一个元素
|
||||
:param loc_or_ele: 元素对象或定位符
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def add_ele(self,
|
||||
html_or_info: Union[str, Tuple[str, dict]],
|
||||
insert_to: Union[ChromiumElement, str, Tuple[str, str], None] = None,
|
||||
before: Union[ChromiumElement, str, Tuple[str, str], None] = None) -> ChromiumElement: ...
|
||||
before: Union[ChromiumElement, str, Tuple[str, str], None] = None) -> ChromiumElement:
|
||||
"""新建一个元素
|
||||
:param html_or_info: 新元素的html文本或信息。信息格式为:(tag, {attr1: value, ...})
|
||||
:param insert_to: 插入到哪个元素中,可接收元素对象和定位符,为None且为html添加到body,不为html不插入
|
||||
:param before: 在哪个子节点前面插入,可接收对象和定位符,为None插入到父元素末尾
|
||||
:return: 元素对象
|
||||
"""
|
||||
...
|
||||
|
||||
def get_frame(self,
|
||||
loc_ind_ele: Union[str, int, tuple, ChromiumFrame, ChromiumElement],
|
||||
timeout: float = None) -> ChromiumFrame: ...
|
||||
timeout: float = None) -> ChromiumFrame:
|
||||
"""获取页面中一个frame对象
|
||||
:param loc_ind_ele: 定位符、iframe序号、ChromiumFrame对象,序号从1开始,可传入负数获取倒数第几个
|
||||
:param timeout: 查找元素超时时间(秒)
|
||||
:return: ChromiumFrame对象
|
||||
"""
|
||||
...
|
||||
|
||||
def get_frames(self, locator: Union[str, tuple] = None, timeout: float = None) -> List[ChromiumFrame]: ...
|
||||
def get_frames(self, locator: Union[str, tuple] = None, timeout: float = None) -> List[ChromiumFrame]:
|
||||
"""获取所有符合条件的frame对象
|
||||
:param locator: 定位符,为None时返回所有
|
||||
:param timeout: 查找超时时间(秒)
|
||||
:return: ChromiumFrame对象组成的列表
|
||||
"""
|
||||
...
|
||||
|
||||
def run_cdp(self, cmd: str, **cmd_args) -> dict: ...
|
||||
def session_storage(self, item: str = None) -> Union[str, dict, None]:
|
||||
"""返回sessionStorage信息,不设置item则获取全部
|
||||
:param item: 要获取的项,不设置则返回全部
|
||||
:return: sessionStorage一个或所有项内容
|
||||
"""
|
||||
...
|
||||
|
||||
def run_cdp_loaded(self, cmd: str, **cmd_args) -> dict: ...
|
||||
|
||||
def _run_cdp(self, cmd: str, **cmd_args) -> dict: ...
|
||||
|
||||
def _run_cdp_loaded(self, cmd: str, **cmd_args) -> dict: ...
|
||||
|
||||
def session_storage(self, item: str = None) -> Union[str, dict, None]: ...
|
||||
|
||||
def local_storage(self, item: str = None) -> Union[str, dict, None]: ...
|
||||
|
||||
def add_init_js(self, script: str) -> str: ...
|
||||
|
||||
def remove_init_js(self, script_id: str = None) -> None: ...
|
||||
def local_storage(self, item: str = None) -> Union[str, dict, None]:
|
||||
"""返回localStorage信息,不设置item则获取全部
|
||||
:param item: 要获取的项目,不设置则返回全部
|
||||
:return: localStorage一个或所有项内容
|
||||
"""
|
||||
...
|
||||
|
||||
def get_screenshot(self, path: [str, Path] = None, name: str = None, as_bytes: PIC_TYPE = None,
|
||||
as_base64: PIC_TYPE = None, full_page: bool = False, left_top: Tuple[int, int] = None,
|
||||
right_bottom: Tuple[int, int] = None) -> Union[str, bytes]: ...
|
||||
right_bottom: Tuple[int, int] = None) -> Union[str, bytes]:
|
||||
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
||||
:param path: 保存路径
|
||||
:param name: 完整文件名,后缀可选 'jpg','jpeg','png','webp'
|
||||
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
||||
:param left_top: 截取范围左上角坐标
|
||||
:param right_bottom: 截取范围右下角角坐标
|
||||
:return: 图片完整路径或字节文本
|
||||
"""
|
||||
...
|
||||
|
||||
def add_init_js(self, script: str) -> str:
|
||||
"""添加初始化脚本,在页面加载任何脚本前执行
|
||||
:param script: js文本
|
||||
:return: 添加的脚本的id
|
||||
"""
|
||||
...
|
||||
|
||||
def remove_init_js(self, script_id: str = None) -> None:
|
||||
"""删除初始化脚本,js_id传入None时删除所有
|
||||
:param script_id: 脚本的id
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear_cache(self, session_storage: bool = True, local_storage: bool = True, cache: bool = True,
|
||||
cookies: bool = True) -> None:
|
||||
"""清除缓存,可选要清除的项
|
||||
:param session_storage: 是否清除sessionStorage
|
||||
:param local_storage: 是否清除localStorage
|
||||
:param cache: 是否清除cache
|
||||
:param cookies: 是否清除cookies
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def disconnect(self) -> None:
|
||||
"""断开与页面的连接,不关闭页面"""
|
||||
...
|
||||
|
||||
def reconnect(self, wait: float = 0) -> None:
|
||||
"""断开与页面原来的页面,重新建立连接
|
||||
:param wait: 断开后等待若干秒再连接
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def handle_alert(self, accept: Optional[bool] = True, send: str = None, timeout: float = None,
|
||||
next_one: bool = False) -> Union[str, False]:
|
||||
"""处理提示框,可以自动等待提示框出现
|
||||
:param accept: True表示确认,False表示取消,为None不会按按钮但依然返回文本值
|
||||
:param send: 处理prompt提示框时可输入文本
|
||||
:param timeout: 等待提示框出现的超时时间(秒),为None则使用self.timeout属性的值
|
||||
:param next_one: 是否处理下一个出现的提示框,为True时timeout参数无效
|
||||
:return: 提示框内容文本,未等到提示框则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def _handle_alert(self, accept: bool = True, send: str = None, timeout: float = None,
|
||||
next_one: bool = False) -> Union[str, False]:
|
||||
"""处理提示框,可以自动等待提示框出现
|
||||
:param accept: True表示确认,False表示取消,其它值不会按按钮但依然返回文本值
|
||||
:param send: 处理prompt提示框时可输入文本
|
||||
:param timeout: 等待提示框出现的超时时间(秒),为None则使用self.timeout属性的值
|
||||
:param next_one: 是否处理下一个出现的提示框,为True时timeout参数无效
|
||||
:return: 提示框内容文本,未等到提示框则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def _on_alert_open(self, **kwargs):
|
||||
"""alert出现时触发的方法"""
|
||||
...
|
||||
|
||||
def _on_alert_close(self, **kwargs):
|
||||
"""alert关闭时触发的方法"""
|
||||
...
|
||||
|
||||
def _wait_loaded(self, timeout: float = None) -> bool:
|
||||
"""等待页面加载完成,超时触发停止加载
|
||||
:param timeout: 超时时间(秒)
|
||||
:return: 是否成功,超时返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def _d_connect(self, to_url: str, times: int = 0, interval: float = 1, show_errmsg: bool = False,
|
||||
timeout: float = None) -> Union[bool, None]:
|
||||
"""尝试连接,重试若干次
|
||||
:param to_url: 要访问的url
|
||||
:param times: 重试次数
|
||||
:param interval: 重试间隔(秒)
|
||||
:param show_errmsg: 是否抛出异常
|
||||
:param timeout: 连接超时时间(秒)
|
||||
:return: 是否成功,返回None表示不确定
|
||||
"""
|
||||
...
|
||||
|
||||
def _get_screenshot(self, path: [str, Path] = None, name: str = None, as_bytes: PIC_TYPE = None,
|
||||
as_base64: PIC_TYPE = None, full_page: bool = False, left_top: Tuple[float, float] = None,
|
||||
right_bottom: Tuple[float, float] = None, ele: ChromiumElement = None) -> Union[str, bytes]: ...
|
||||
|
||||
def clear_cache(self, session_storage: bool = True, local_storage: bool = True, cache: bool = True,
|
||||
cookies: bool = True) -> None: ...
|
||||
|
||||
def disconnect(self) -> None: ...
|
||||
|
||||
def reconnect(self, wait: float = 0) -> None: ...
|
||||
|
||||
def handle_alert(self, accept: Optional[bool] = True, send: str = None, timeout: float = None,
|
||||
next_one: bool = False) -> Union[str, False]: ...
|
||||
|
||||
def _handle_alert(self, accept: bool = True, send: str = None, timeout: float = None,
|
||||
next_one: bool = False) -> Union[str, False]: ...
|
||||
|
||||
def _on_alert_close(self, **kwargs): ...
|
||||
|
||||
def _on_alert_open(self, **kwargs): ...
|
||||
|
||||
def _d_connect(self, to_url: str, times: int = 0, interval: float = 1, show_errmsg: bool = False,
|
||||
timeout: float = None) -> Union[bool, None]: ...
|
||||
right_bottom: Tuple[float, float] = None, ele: ChromiumElement = None) -> Union[str, bytes]:
|
||||
"""对页面进行截图,可对整个网页、可见网页、指定范围截图。对可视范围外截图需要90以上版本浏览器支持
|
||||
:param path: 保存路径
|
||||
:param name: 完整文件名,后缀可选 'jpg','jpeg','png','webp'
|
||||
:param as_bytes: 是否以字节形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数和as_base64参数无效
|
||||
:param as_base64: 是否以base64字符串形式返回图片,可选 'jpg','jpeg','png','webp',生效时path参数无效
|
||||
:param full_page: 是否整页截图,为True截取整个网页,为False截取可视窗口
|
||||
:param left_top: 截取范围左上角坐标
|
||||
:param right_bottom: 截取范围右下角角坐标
|
||||
:param ele: 为异域iframe内元素截图设置
|
||||
:return: 图片完整路径或字节文本
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class Timeout(object):
|
||||
base: float = ...
|
||||
page_load: float = ...
|
||||
script: float = ...
|
||||
|
||||
def __init__(self, base=None, page_load=None, script=None):
|
||||
self.base: float = ...
|
||||
self.page_load: float = ...
|
||||
self.script: float = ...
|
||||
"""
|
||||
:param base: 默认超时时间
|
||||
:param page_load: 页面加载超时时间
|
||||
:param script: js超时时间
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def as_dict(self) -> dict: ...
|
||||
def as_dict(self) -> dict:
|
||||
"""以dict格式返回timeout设置"""
|
||||
...
|
||||
|
||||
|
||||
class Alert(object):
|
||||
|
||||
def __init__(self):
|
||||
self.activated: bool = ...
|
||||
self.text: str = ...
|
||||
self.type: str = ...
|
||||
self.defaultPrompt: str = ...
|
||||
self.response_accept: str = ...
|
||||
self.response_text: str = ...
|
||||
self.handle_next: Optional[bool] = ...
|
||||
self.next_text: str = ...
|
||||
self.auto: Optional[bool] = ...
|
||||
|
||||
|
||||
def get_mhtml(page: Union[ChromiumPage, ChromiumTab],
|
||||
path: Union[str, Path] = None,
|
||||
name: str = None) -> str: ...
|
||||
|
||||
|
||||
def get_pdf(page: Union[ChromiumPage, ChromiumTab],
|
||||
path: Union[str, Path] = None,
|
||||
name: str = None, kwargs: dict = None) -> bytes: ...
|
||||
activated: Optional[bool] = ...
|
||||
text: Optional[str] = ...
|
||||
type: Optional[str] = ...
|
||||
defaultPrompt: Optional[str] = ...
|
||||
response_accept: Optional[str] = ...
|
||||
response_text: Optional[str] = ...
|
||||
handle_next: Optional[bool] = ...
|
||||
next_text: Optional[str] = ...
|
||||
auto: Optional[bool] = ...
|
||||
|
@ -24,18 +24,19 @@ from .._units.setter import MixPageSetter
|
||||
|
||||
|
||||
class MixPage(SessionPage, ChromiumPage, BasePage):
|
||||
_mode: str = ...
|
||||
_set: MixPageSetter = ...
|
||||
_has_driver: Optional[bool] = ...
|
||||
_has_session: Optional[bool] = ...
|
||||
_session_options: Union[SessionOptions, None] = ...
|
||||
_chromium_options: Union[ChromiumOptions, None] = ...
|
||||
|
||||
def __init__(self,
|
||||
mode: str = 'd',
|
||||
timeout: float = None,
|
||||
chromium_options: Union[ChromiumOptions, bool] = None,
|
||||
session_or_options: Union[Session, SessionOptions, bool] = None) -> None:
|
||||
self._mode: str = ...
|
||||
self._set: MixPageSetter = ...
|
||||
self._has_driver: bool = ...
|
||||
self._has_session: bool = ...
|
||||
self._session_options: Union[SessionOptions, None] = ...
|
||||
self._chromium_options: Union[ChromiumOptions, None] = ...
|
||||
...
|
||||
|
||||
def __call__(self,
|
||||
locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement],
|
||||
|
@ -14,28 +14,12 @@ from ..errors import CanNotClickError, CDPError, NoRectError, AlertExistsError
|
||||
|
||||
class Clicker(object):
|
||||
def __init__(self, ele):
|
||||
"""
|
||||
:param ele: ChromiumElement
|
||||
"""
|
||||
self._ele = ele
|
||||
|
||||
def __call__(self, by_js=False, timeout=1.5, wait_stop=True):
|
||||
"""点击元素
|
||||
如果遇到遮挡,可选择是否用js点击
|
||||
:param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击
|
||||
:param timeout: 模拟点击的超时时间(秒),等待元素可见、可用、进入视口
|
||||
:param wait_stop: 是否等待元素运动结束再执行点击
|
||||
:return: 是否点击成功
|
||||
"""
|
||||
return self.left(by_js, timeout, wait_stop)
|
||||
|
||||
def left(self, by_js=False, timeout=1.5, wait_stop=True):
|
||||
"""点击元素,可选择是否用js点击
|
||||
:param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击
|
||||
:param timeout: 模拟点击的超时时间(秒),等待元素可见、可用、进入视口
|
||||
:param wait_stop: 是否等待元素运动结束再执行点击
|
||||
:return: 是否点击成功
|
||||
"""
|
||||
if self._ele.tag == 'option':
|
||||
if not self._ele.states.is_selected:
|
||||
self._ele.parent('t:select').select.by_option(self._ele)
|
||||
@ -108,15 +92,10 @@ class Clicker(object):
|
||||
return False
|
||||
|
||||
def right(self):
|
||||
"""右键单击"""
|
||||
self._ele.owner.scroll.to_see(self._ele)
|
||||
return self._click(*self._ele.rect.viewport_click_point, button='right')
|
||||
|
||||
def middle(self, get_tab=True):
|
||||
"""中键单击,默认返回新出现的tab对象
|
||||
:param get_tab: 是否返回新tab对象,为False则返回None
|
||||
:return: Tab对象或None
|
||||
"""
|
||||
self._ele.owner.scroll.to_see(self._ele)
|
||||
curr_tid = self._ele.tab.browser.tab_ids[0]
|
||||
self._click(*self._ele.rect.viewport_click_point, button='middle')
|
||||
@ -128,13 +107,6 @@ class Clicker(object):
|
||||
else self._ele.tab.browser.get_tab(tid))
|
||||
|
||||
def at(self, offset_x=None, offset_y=None, button='left', count=1):
|
||||
"""带偏移量点击本元素,相对于左上角坐标。不传入x或y值时点击元素中间点
|
||||
:param offset_x: 相对元素左上角坐标的x轴偏移量
|
||||
:param offset_y: 相对元素左上角坐标的y轴偏移量
|
||||
:param button: 点击哪个键,可选 left, middle, right, back, forward
|
||||
:param count: 点击次数
|
||||
:return: None
|
||||
"""
|
||||
self._ele.owner.scroll.to_see(self._ele)
|
||||
if offset_x is None and offset_y is None:
|
||||
w, h = self._ele.rect.size
|
||||
@ -143,22 +115,9 @@ class Clicker(object):
|
||||
return self._click(*offset_scroll(self._ele, offset_x, offset_y), button=button, count=count)
|
||||
|
||||
def multi(self, times=2):
|
||||
"""多次点击
|
||||
:param times: 默认双击
|
||||
:return: None
|
||||
"""
|
||||
return self.at(count=times)
|
||||
|
||||
def to_download(self, save_path=None, rename=None, suffix=None, new_tab=False, by_js=False, timeout=None):
|
||||
"""点击触发下载
|
||||
:param save_path: 保存路径,为None保存在原来设置的,如未设置保存到当前路径
|
||||
:param rename: 重命名文件名
|
||||
:param suffix: 指定文件后缀
|
||||
:param new_tab: 该下载是否在新tab中触发
|
||||
:param by_js: 是否用js方式点击,逻辑与click()一致
|
||||
:param timeout: 等待下载触发的超时时间,为None则使用页面对象设置
|
||||
:return: DownloadMission对象
|
||||
"""
|
||||
if save_path:
|
||||
self._ele.tab.set.download_path(save_path)
|
||||
elif not self._ele.tab._browser._dl_mgr._running:
|
||||
@ -172,21 +131,11 @@ class Clicker(object):
|
||||
return obj.wait.download_begin(timeout=timeout)
|
||||
|
||||
def to_upload(self, file_paths, by_js=False):
|
||||
"""触发上传文件选择框并自动填入指定路径
|
||||
:param file_paths: 文件路径,如果上传框支持多文件,可传入列表或字符串,字符串时多个文件用回车分隔
|
||||
:param by_js: 是否用js方式点击,逻辑与click()一致
|
||||
:return: None
|
||||
"""
|
||||
self._ele.owner.set.upload_files(file_paths)
|
||||
self.left(by_js=by_js)
|
||||
self._ele.owner.wait.upload_paths_inputted()
|
||||
|
||||
def for_new_tab(self, by_js=False, timeout=3):
|
||||
"""点击后等待新tab出现并返回其对象
|
||||
:param by_js: 是否使用js点击,逻辑与click()一致
|
||||
:param timeout: 等待超时时间
|
||||
:return: 新标签页对象,如果没有等到新标签页出现则抛出异常
|
||||
"""
|
||||
curr_tid = self._ele.tab.browser.tab_ids[0]
|
||||
self.left(by_js=by_js)
|
||||
tid = self._ele.tab.browser.wait.new_tab(timeout=timeout, curr_tab=curr_tid)
|
||||
@ -196,13 +145,6 @@ class Clicker(object):
|
||||
else self._ele.tab.browser.get_tab(tid))
|
||||
|
||||
def for_url_change(self, text=None, exclude=False, by_js=False, timeout=None):
|
||||
"""点击并等待tab的url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本,为None等待当前url变化
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True,text为None时自动设为True
|
||||
:param by_js: 是否用js点击
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if text is None:
|
||||
exclude = True
|
||||
text = self._ele.tab.url
|
||||
@ -210,13 +152,6 @@ class Clicker(object):
|
||||
return True if self._ele.tab.wait.url_change(text=text, exclude=exclude, timeout=timeout) else False
|
||||
|
||||
def for_title_change(self, text=None, exclude=False, by_js=False, timeout=None):
|
||||
"""点击并等待tab的title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本,为None等待当前title变化
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True,text为None时自动设为True
|
||||
:param by_js: 是否用js点击
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if text is None:
|
||||
exclude = True
|
||||
text = self._ele.tab.title
|
||||
@ -224,13 +159,6 @@ class Clicker(object):
|
||||
return True if self._ele.tab.wait.title_change(text=text, exclude=exclude, timeout=timeout) else False
|
||||
|
||||
def _click(self, view_x, view_y, button='left', count=1):
|
||||
"""实施点击
|
||||
:param view_x: 视口x坐标
|
||||
:param view_y: 视口y坐标
|
||||
:param button: 'left' 'right' 'middle' 'back' 'forward'
|
||||
:param count: 点击次数
|
||||
:return: None
|
||||
"""
|
||||
self._ele.owner._run_cdp('Input.dispatchMouseEvent', type='mousePressed', x=view_x,
|
||||
y=view_y, button=button, clickCount=count, _ignore=AlertExistsError)
|
||||
self._ele.owner._run_cdp('Input.dispatchMouseEvent', type='mouseReleased', x=view_x,
|
||||
|
@ -14,26 +14,66 @@ from .._pages.tabs import MixTab, ChromiumTab
|
||||
|
||||
|
||||
class Clicker(object):
|
||||
_ele: ChromiumElement = ...
|
||||
|
||||
def __init__(self, ele: ChromiumElement):
|
||||
self._ele: ChromiumElement = ...
|
||||
"""
|
||||
:param ele: ChromiumElement
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, by_js: Union[bool, str, None] = False,
|
||||
timeout: float = 1.5, wait_stop: bool = True) -> Union[ChromiumElement, False]: ...
|
||||
timeout: float = 1.5, wait_stop: bool = True) -> Union[ChromiumElement, False]:
|
||||
"""点击元素
|
||||
如果遇到遮挡,可选择是否用js点击
|
||||
:param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击
|
||||
:param timeout: 模拟点击的超时时间(秒),等待元素可见、可用、进入视口
|
||||
:param wait_stop: 是否等待元素运动结束再执行点击
|
||||
:return: 是否点击成功
|
||||
"""
|
||||
...
|
||||
|
||||
def left(self, by_js: Union[bool, str, None] = False,
|
||||
timeout: float = 1.5, wait_stop: bool = True) -> Union[ChromiumElement, False]: ...
|
||||
timeout: float = 1.5, wait_stop: bool = True) -> Union[ChromiumElement, False]:
|
||||
"""点击元素,可选择是否用js点击
|
||||
:param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击
|
||||
:param timeout: 模拟点击的超时时间(秒),等待元素可见、可用、进入视口
|
||||
:param wait_stop: 是否等待元素运动结束再执行点击
|
||||
:return: 是否点击成功
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self) -> ChromiumElement: ...
|
||||
def right(self) -> ChromiumElement:
|
||||
"""右键单击"""
|
||||
...
|
||||
|
||||
def middle(self, get_tab: bool = True) -> Union[ChromiumTab, MixTab, None]: ...
|
||||
def middle(self, get_tab: bool = True) -> Union[ChromiumTab, MixTab, None]:
|
||||
"""中键单击,默认返回新出现的tab对象
|
||||
:param get_tab: 是否返回新tab对象,为False则返回None
|
||||
:return: Tab对象或None
|
||||
"""
|
||||
...
|
||||
|
||||
def at(self,
|
||||
offset_x: float = None,
|
||||
offset_y: float = None,
|
||||
button: str = 'left',
|
||||
count: int = 1) -> ChromiumElement: ...
|
||||
count: int = 1) -> ChromiumElement:
|
||||
"""带偏移量点击本元素,相对于左上角坐标。不传入x或y值时点击元素中间点
|
||||
:param offset_x: 相对元素左上角坐标的x轴偏移量
|
||||
:param offset_y: 相对元素左上角坐标的y轴偏移量
|
||||
:param button: 点击哪个键,可选 left, middle, right, back, forward
|
||||
:param count: 点击次数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def multi(self, times: int = 2) -> ChromiumElement: ...
|
||||
def multi(self, times: int = 2) -> ChromiumElement:
|
||||
"""多次点击
|
||||
:param times: 默认双击
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def to_download(self,
|
||||
save_path: Union[str, Path] = None,
|
||||
@ -41,20 +81,66 @@ class Clicker(object):
|
||||
suffix: str = None,
|
||||
new_tab: bool = False,
|
||||
by_js: bool = False,
|
||||
timeout: float = None) -> DownloadMission: ...
|
||||
timeout: float = None) -> DownloadMission:
|
||||
"""点击触发下载
|
||||
:param save_path: 保存路径,为None保存在原来设置的,如未设置保存到当前路径
|
||||
:param rename: 重命名文件名
|
||||
:param suffix: 指定文件后缀
|
||||
:param new_tab: 该下载是否在新tab中触发
|
||||
:param by_js: 是否用js方式点击,逻辑与click()一致
|
||||
:param timeout: 等待下载触发的超时时间,为None则使用页面对象设置
|
||||
:return: DownloadMission对象
|
||||
"""
|
||||
...
|
||||
|
||||
def to_upload(self, file_paths: Union[str, Path, list, tuple], by_js: bool = False) -> None: ...
|
||||
def to_upload(self, file_paths: Union[str, Path, list, tuple], by_js: bool = False) -> None:
|
||||
"""触发上传文件选择框并自动填入指定路径
|
||||
:param file_paths: 文件路径,如果上传框支持多文件,可传入列表或字符串,字符串时多个文件用回车分隔
|
||||
:param by_js: 是否用js方式点击,逻辑与click()一致
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def for_new_tab(self, by_js: bool = False, timeout: float = 3) -> Union[ChromiumTab, MixTab]: ...
|
||||
def for_new_tab(self, by_js: bool = False, timeout: float = 3) -> Union[ChromiumTab, MixTab]:
|
||||
"""点击后等待新tab出现并返回其对象
|
||||
:param by_js: 是否使用js点击,逻辑与click()一致
|
||||
:param timeout: 等待超时时间
|
||||
:return: 新标签页对象,如果没有等到新标签页出现则抛出异常
|
||||
"""
|
||||
...
|
||||
|
||||
def for_url_change(self, text: str = None, exclude: bool = False,
|
||||
by_js: bool = False, timeout: float = None) -> bool: ...
|
||||
by_js: bool = False, timeout: float = None) -> bool:
|
||||
"""点击并等待tab的url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本,为None等待当前url变化
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True,text为None时自动设为True
|
||||
:param by_js: 是否用js点击
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def for_title_change(self, text: str = None, exclude: bool = False,
|
||||
by_js: bool = False, timeout: float = None) -> bool: ...
|
||||
by_js: bool = False, timeout: float = None) -> bool:
|
||||
"""点击并等待tab的title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本,为None等待当前title变化
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True,text为None时自动设为True
|
||||
:param by_js: 是否用js点击
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _click(self,
|
||||
view_x: float,
|
||||
view_y: float,
|
||||
button: str = 'left',
|
||||
count: int = 1) -> ChromiumElement: ...
|
||||
count: int = 1) -> ChromiumElement:
|
||||
"""实施点击
|
||||
:param view_x: 视口x坐标
|
||||
:param view_y: 视口y坐标
|
||||
:param button: 'left' 'right' 'middle' 'back' 'forward'
|
||||
:param count: 点击次数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
@ -53,7 +53,6 @@ class ConsoleData(object):
|
||||
self._data = data
|
||||
|
||||
def __getattr__(self, item):
|
||||
"""获取属性"""
|
||||
return self._data.get(item, None)
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -10,10 +10,16 @@ class Console(object):
|
||||
owner: ChromiumBase = ...
|
||||
_caught: Optional[Queue] = ...
|
||||
|
||||
def __init__(self, owner: ChromiumBase) -> None: ...
|
||||
def __init__(self, owner: ChromiumBase) -> None:
|
||||
"""
|
||||
:param owner: 页面对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def messages(self) -> List[ConsoleData]: ...
|
||||
def messages(self) -> List[ConsoleData]:
|
||||
"""以list方式返回获取到的信息,返回后会清空列表"""
|
||||
...
|
||||
|
||||
def start(self) -> None:
|
||||
"""开启console监听"""
|
||||
|
@ -10,44 +10,21 @@ from .._functions.cookies import set_tab_cookies, set_session_cookies, set_brows
|
||||
|
||||
class BrowserCookiesSetter(object):
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: Chromium对象
|
||||
"""
|
||||
self._owner = owner
|
||||
|
||||
def __call__(self, cookies):
|
||||
"""设置一个或多个cookie
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
set_browser_cookies(self._owner, cookies)
|
||||
|
||||
def clear(self):
|
||||
"""清除cookies"""
|
||||
self._owner._run_cdp('Storage.clearCookies')
|
||||
|
||||
|
||||
class CookiesSetter(BrowserCookiesSetter):
|
||||
|
||||
def __call__(self, cookies):
|
||||
"""设置一个或多个cookie
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
set_tab_cookies(self._owner, cookies)
|
||||
|
||||
def clear(self):
|
||||
"""清除cookies"""
|
||||
self._owner._run_cdp('Network.clearBrowserCookies')
|
||||
|
||||
def remove(self, name, url=None, domain=None, path=None):
|
||||
"""删除一个cookie
|
||||
:param name: cookie的name字段
|
||||
:param url: cookie的url字段,可选
|
||||
:param domain: cookie的domain字段,可选
|
||||
:param path: cookie的path字段,可选
|
||||
:return: None
|
||||
"""
|
||||
d = {'name': name}
|
||||
if url is not None:
|
||||
d['url'] = url
|
||||
@ -61,50 +38,33 @@ class CookiesSetter(BrowserCookiesSetter):
|
||||
d['path'] = path
|
||||
self._owner._run_cdp('Network.deleteCookies', **d)
|
||||
|
||||
def clear(self):
|
||||
self._owner._run_cdp('Network.clearBrowserCookies')
|
||||
|
||||
|
||||
class SessionCookiesSetter(object):
|
||||
def __init__(self, owner):
|
||||
self._owner = owner
|
||||
|
||||
def __call__(self, cookies):
|
||||
"""设置多个cookie,注意不要传入单个
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
set_session_cookies(self._owner.session, cookies)
|
||||
|
||||
def remove(self, name):
|
||||
"""删除一个cookie
|
||||
:param name: cookie的name字段
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.cookies.set(name, None)
|
||||
|
||||
def clear(self):
|
||||
"""清除cookies"""
|
||||
self._owner.session.cookies.clear()
|
||||
|
||||
|
||||
class MixPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
|
||||
|
||||
def __call__(self, cookies):
|
||||
"""设置多个cookie,注意不要传入单个
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
if self._owner.mode == 'd' and self._owner._has_driver:
|
||||
super().__call__(cookies)
|
||||
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):
|
||||
"""删除一个cookie
|
||||
:param name: cookie的name字段
|
||||
:param url: cookie的url字段,可选,d模式时才有效
|
||||
:param domain: cookie的domain字段,可选,d模式时才有效
|
||||
:param path: cookie的path字段,可选,d模式时才有效
|
||||
:return: None
|
||||
"""
|
||||
if self._owner.mode == 'd' and self._owner._has_driver:
|
||||
super().remove(name, url, domain, path)
|
||||
elif self._owner.mode == 's' and self._owner._has_session:
|
||||
@ -113,7 +73,6 @@ class MixPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
|
||||
super(CookiesSetter, self).remove(name)
|
||||
|
||||
def clear(self):
|
||||
"""清除cookies"""
|
||||
if self._owner.mode == 'd' and self._owner._has_driver:
|
||||
super().clear()
|
||||
elif self._owner.mode == 's' and self._owner._has_session:
|
||||
|
@ -18,42 +18,117 @@ from .._pages.mix_page import MixPage
|
||||
class BrowserCookiesSetter(object):
|
||||
_owner: Chromium = ...
|
||||
|
||||
def __init__(self, page: Chromium): ...
|
||||
def __init__(self, owner: Chromium):
|
||||
"""
|
||||
:param owner: Chromium对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None: ...
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None:
|
||||
"""设置一个或多个cookie
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear(self) -> None: ...
|
||||
def clear(self) -> None:
|
||||
"""清除cookies"""
|
||||
...
|
||||
|
||||
|
||||
class CookiesSetter(BrowserCookiesSetter):
|
||||
_owner: ChromiumBase = ...
|
||||
|
||||
def __init__(self, page: ChromiumBase): ...
|
||||
def __init__(self, owner: ChromiumBase):
|
||||
"""
|
||||
:param owner: 页面对象
|
||||
"""
|
||||
...
|
||||
|
||||
def remove(self, name: str, url: str = None, domain: str = None, path: str = None) -> None: ...
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None:
|
||||
"""设置一个或多个cookie
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear(self) -> None: ...
|
||||
def remove(self,
|
||||
name: str,
|
||||
url: str = None,
|
||||
domain: str = None,
|
||||
path: str = None) -> None:
|
||||
"""删除一个cookie
|
||||
:param name: cookie的name字段
|
||||
:param url: cookie的url字段,可选
|
||||
:param domain: cookie的domain字段,可选
|
||||
:param path: cookie的path字段,可选
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear(self) -> None:
|
||||
"""清除cookies"""
|
||||
...
|
||||
|
||||
|
||||
class SessionCookiesSetter(object):
|
||||
_owner: SessionPage = ...
|
||||
|
||||
def __init__(self, page: SessionPage): ...
|
||||
def __init__(self, owner: SessionPage):
|
||||
"""
|
||||
:param owner: SessionPage对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None: ...
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None:
|
||||
"""设置一个或多个cookie
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def remove(self, name: str) -> None: ...
|
||||
def remove(self, name: str) -> None:
|
||||
"""删除一个cookie
|
||||
:param name: cookie的name字段
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear(self) -> None: ...
|
||||
def clear(self) -> None:
|
||||
"""清除cookies"""
|
||||
...
|
||||
|
||||
|
||||
class MixPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
|
||||
_owner: Union[MixPage, MixTab] = ...
|
||||
|
||||
def __init__(self, page: SessionPage): ...
|
||||
def __init__(self, owner: Union[MixPage, MixTab]):
|
||||
"""
|
||||
:param owner: MixPage, MixTab对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None: ...
|
||||
def __call__(self, cookies: Union[CookieJar, Cookie, list, tuple, str, dict]) -> None:
|
||||
"""设置一个或多个cookie
|
||||
:param cookies: cookies信息
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def remove(self, name: str, url: str = None, domain: str = None, path: str = None) -> None: ...
|
||||
def remove(self,
|
||||
name: str,
|
||||
url: str = None,
|
||||
domain: str = None,
|
||||
path: str = None) -> None:
|
||||
"""删除一个cookie
|
||||
:param name: cookie的name字段
|
||||
:param url: cookie的url字段,可选,d模式时才有效
|
||||
:param domain: cookie的domain字段,可选,d模式时才有效
|
||||
:param path: cookie的path字段,可选,d模式时才有效
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear(self) -> None: ...
|
||||
def clear(self) -> None:
|
||||
"""清除cookies"""
|
||||
...
|
||||
|
@ -16,9 +16,6 @@ from DataRecorder.tools import get_usable_path
|
||||
class DownloadManager(object):
|
||||
|
||||
def __init__(self, browser):
|
||||
"""
|
||||
:param browser: Browser对象
|
||||
"""
|
||||
self._browser = browser
|
||||
|
||||
t = TabDownloadSettings('browser')
|
||||
@ -35,15 +32,9 @@ class DownloadManager(object):
|
||||
|
||||
@property
|
||||
def missions(self):
|
||||
"""返回所有未完成的下载任务"""
|
||||
return self._missions
|
||||
|
||||
def set_path(self, tab, path):
|
||||
"""设置某个tab的下载路径
|
||||
:param tab: 页面对象
|
||||
:param path: 下载路径(绝对路径str)
|
||||
:return: None
|
||||
"""
|
||||
tid = tab if isinstance(tab, str) else tab.tab_id
|
||||
TabDownloadSettings(tid).path = path
|
||||
if not self._running or tid == 'browser':
|
||||
@ -56,53 +47,23 @@ class DownloadManager(object):
|
||||
self._running = True
|
||||
|
||||
def set_rename(self, tab_id, rename=None, suffix=None):
|
||||
"""设置某个tab的重命名文件名
|
||||
:param tab_id: tab id
|
||||
:param rename: 文件名,可不含后缀,会自动使用远程文件后缀
|
||||
:param suffix: 后缀名,显式设置后缀名,不使用远程文件后缀
|
||||
:return: None
|
||||
"""
|
||||
ts = TabDownloadSettings(tab_id)
|
||||
ts.rename = rename
|
||||
ts.suffix = suffix
|
||||
|
||||
def set_file_exists(self, tab_id, mode):
|
||||
"""设置某个tab下载文件重名时执行的策略
|
||||
:param tab_id: tab id
|
||||
:param mode: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
TabDownloadSettings(tab_id).when_file_exists = mode
|
||||
|
||||
def set_flag(self, tab_id, flag):
|
||||
"""设置某个tab的重命名文件名
|
||||
:param tab_id: tab id
|
||||
:param flag: 等待标志
|
||||
:return: None
|
||||
"""
|
||||
self._flags[tab_id] = flag
|
||||
|
||||
def get_flag(self, tab_id):
|
||||
"""获取tab下载等待标记
|
||||
:param tab_id: tab id
|
||||
:return: 任务对象或False
|
||||
"""
|
||||
return self._flags.get(tab_id, None)
|
||||
|
||||
def get_tab_missions(self, tab_id):
|
||||
"""获取某个tab正在下载的任务
|
||||
:param tab_id:
|
||||
:return: 下载任务组成的列表
|
||||
"""
|
||||
return self._tab_missions.get(tab_id, [])
|
||||
|
||||
def set_done(self, mission, state, final_path=None):
|
||||
"""设置任务结束
|
||||
:param mission: 任务对象
|
||||
:param state: 任务状态
|
||||
:param final_path: 最终路径
|
||||
:return: None
|
||||
"""
|
||||
if mission.state not in ('canceled', 'skipped'):
|
||||
mission.state = state
|
||||
mission.final_path = final_path
|
||||
@ -112,10 +73,6 @@ class DownloadManager(object):
|
||||
mission._is_done = True
|
||||
|
||||
def cancel(self, mission):
|
||||
"""取消任务
|
||||
:param mission: 任务对象
|
||||
:return: None
|
||||
"""
|
||||
mission.state = 'canceled'
|
||||
try:
|
||||
self._browser._run_cdp('Browser.cancelDownload', guid=mission.id)
|
||||
@ -125,10 +82,6 @@ class DownloadManager(object):
|
||||
Path(mission.final_path).unlink(True)
|
||||
|
||||
def skip(self, mission):
|
||||
"""跳过任务
|
||||
:param mission: 任务对象
|
||||
:return: None
|
||||
"""
|
||||
mission.state = 'skipped'
|
||||
try:
|
||||
self._browser._run_cdp('Browser.cancelDownload', guid=mission.id)
|
||||
@ -136,17 +89,11 @@ class DownloadManager(object):
|
||||
pass
|
||||
|
||||
def clear_tab_info(self, tab_id):
|
||||
"""当tab关闭时清除有关信息
|
||||
:param tab_id: 标签页id
|
||||
:return: None
|
||||
"""
|
||||
self._tab_missions.pop(tab_id, None)
|
||||
self._flags.pop(tab_id, None)
|
||||
TabDownloadSettings.TABS.pop(tab_id, None)
|
||||
|
||||
def _onDownloadWillBegin(self, **kwargs):
|
||||
"""用于获取弹出新标签页触发的下载任务"""
|
||||
# print(kwargs)
|
||||
guid = kwargs['guid']
|
||||
tab_id = self._browser._frames.get(kwargs['frameId'], 'browser')
|
||||
|
||||
@ -196,7 +143,6 @@ class DownloadManager(object):
|
||||
self._flags[tab_id] = m
|
||||
|
||||
def _onDownloadProgress(self, **kwargs):
|
||||
"""下载状态变化时执行"""
|
||||
if kwargs['guid'] in self._missions:
|
||||
mission = self._missions[kwargs['guid']]
|
||||
if kwargs['state'] == 'inProgress':
|
||||
@ -241,9 +187,6 @@ class TabDownloadSettings(object):
|
||||
return object.__new__(cls)
|
||||
|
||||
def __init__(self, tab_id):
|
||||
"""
|
||||
:param tab_id: tab id
|
||||
"""
|
||||
if hasattr(self, '_created'):
|
||||
return
|
||||
self._created = True
|
||||
@ -258,15 +201,6 @@ class TabDownloadSettings(object):
|
||||
|
||||
class DownloadMission(object):
|
||||
def __init__(self, mgr, tab_id, _id, path, name, url, save_path):
|
||||
"""
|
||||
:param mgr: BrowserDownloadManager对象
|
||||
:param tab_id: 标签页id
|
||||
:param _id: 任务id
|
||||
:param path: 保存路径
|
||||
:param name: 文件名
|
||||
:param url: url
|
||||
:param save_path: 下载路径
|
||||
"""
|
||||
self._mgr = mgr
|
||||
self.url = url
|
||||
self.tab_id = tab_id
|
||||
@ -285,25 +219,16 @@ class DownloadMission(object):
|
||||
|
||||
@property
|
||||
def rate(self):
|
||||
"""以百分比形式返回下载进度"""
|
||||
return round((self.received_bytes / self.total_bytes) * 100, 2) if self.total_bytes else None
|
||||
|
||||
@property
|
||||
def is_done(self):
|
||||
"""返回任务是否在运行中"""
|
||||
return self._is_done
|
||||
|
||||
def cancel(self):
|
||||
"""取消该任务,如任务已完成,删除已下载的文件"""
|
||||
self._mgr.cancel(self)
|
||||
|
||||
def wait(self, show=True, timeout=None, cancel_if_timeout=True):
|
||||
"""等待任务结束
|
||||
:param show: 是否显示下载信息
|
||||
:param timeout: 超时时间(秒),为None则无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消任务
|
||||
:return: 等待成功返回完整路径,否则返回False
|
||||
"""
|
||||
if show:
|
||||
print(f'url:{self.url}')
|
||||
end_time = perf_counter()
|
||||
|
@ -9,9 +9,10 @@ from typing import Dict, Optional, Union, Literal
|
||||
|
||||
from .._base.browser import Chromium
|
||||
from .._pages.chromium_base import ChromiumBase
|
||||
# from .._pages.chromium_page import ChromiumPage
|
||||
|
||||
FILE_EXISTS = Literal['skip', 'rename', 'overwrite', 's', 'r', 'o']
|
||||
|
||||
|
||||
class DownloadManager(object):
|
||||
_browser: Chromium = ...
|
||||
_missions: Dict[str, DownloadMission] = ...
|
||||
@ -19,34 +20,107 @@ class DownloadManager(object):
|
||||
_flags: dict = ...
|
||||
_running: bool = ...
|
||||
|
||||
def __init__(self, browser: Chromium): ...
|
||||
def __init__(self, browser: Chromium):
|
||||
"""
|
||||
:param browser: Browser对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def missions(self) -> Dict[str, DownloadMission]: ...
|
||||
def missions(self) -> Dict[str, DownloadMission]:
|
||||
"""返回所有未完成的下载任务"""
|
||||
...
|
||||
|
||||
def set_path(self, tab: Union[str,ChromiumBase], path: str) -> None: ...
|
||||
def set_path(self, tab: Union[str, ChromiumBase], path: str) -> None:
|
||||
"""设置某个tab的下载路径
|
||||
:param tab: 页面对象
|
||||
:param path: 下载路径(绝对路径str)
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
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:
|
||||
"""设置某个tab的重命名文件名
|
||||
:param tab_id: tab id
|
||||
:param rename: 文件名,可不含后缀,会自动使用远程文件后缀
|
||||
:param suffix: 后缀名,显式设置后缀名,不使用远程文件后缀
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def set_file_exists(self, tab_id: str, mode: FILE_EXISTS) -> None: ...
|
||||
def set_file_exists(self, tab_id: str, mode: FILE_EXISTS) -> None:
|
||||
"""设置某个tab下载文件重名时执行的策略
|
||||
:param tab_id: tab id
|
||||
:param mode: 下载路径
|
||||
:return: 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:
|
||||
"""设置某个tab的重命名文件名
|
||||
:param tab_id: tab id
|
||||
:param flag: 等待标志
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def get_flag(self, tab_id: str) -> Union[bool, DownloadMission, None]: ...
|
||||
def get_flag(self, tab_id: str) -> Union[bool, DownloadMission, None]:
|
||||
"""获取tab下载等待标记
|
||||
:param tab_id: tab id
|
||||
:return: 任务对象或False
|
||||
"""
|
||||
...
|
||||
|
||||
def get_tab_missions(self, tab_id: str) -> list: ...
|
||||
def get_tab_missions(self, tab_id: str) -> list:
|
||||
"""获取某个tab正在下载的任务
|
||||
:param tab_id:
|
||||
:return: 下载任务组成的列表
|
||||
"""
|
||||
...
|
||||
|
||||
def set_done(self, mission: DownloadMission, state: str, final_path: str = None) -> None: ...
|
||||
def set_done(self,
|
||||
mission: DownloadMission,
|
||||
state: str,
|
||||
final_path: str = None) -> None:
|
||||
"""设置任务结束
|
||||
:param mission: 任务对象
|
||||
:param state: 任务状态
|
||||
:param final_path: 最终路径
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel(self, mission: DownloadMission) -> None: ...
|
||||
def cancel(self, mission: DownloadMission) -> None:
|
||||
"""取消任务
|
||||
:param mission: 任务对象
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def skip(self, mission: DownloadMission) -> None: ...
|
||||
def skip(self, mission: DownloadMission) -> None:
|
||||
"""跳过任务
|
||||
:param mission: 任务对象
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def clear_tab_info(self, tab_id: str) -> None: ...
|
||||
def clear_tab_info(self, tab_id: str) -> None:
|
||||
"""当tab关闭时清除有关信息
|
||||
:param tab_id: 标签页id
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _onDownloadWillBegin(self, **kwargs) -> None: ...
|
||||
def _onDownloadWillBegin(self, **kwargs) -> None:
|
||||
"""用于获取弹出新标签页触发的下载任务"""
|
||||
...
|
||||
|
||||
def _onDownloadProgress(self, **kwargs) -> None: ...
|
||||
def _onDownloadProgress(self, **kwargs) -> None:
|
||||
"""下载状态变化时执行"""
|
||||
...
|
||||
|
||||
|
||||
class TabDownloadSettings(object):
|
||||
@ -58,7 +132,11 @@ class TabDownloadSettings(object):
|
||||
path: Optional[str] = ...
|
||||
when_file_exists: str = ...
|
||||
|
||||
def __init__(self, tab_id: str): ...
|
||||
def __init__(self, tab_id: str):
|
||||
"""
|
||||
:param tab_id: tab id
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class DownloadMission(object):
|
||||
@ -75,15 +153,47 @@ class DownloadMission(object):
|
||||
save_path: str = ...
|
||||
_is_done: bool = ...
|
||||
|
||||
def __init__(self, mgr: DownloadManager, tab_id: str, _id: str, path: str, name: str, url: str,
|
||||
save_path: str): ...
|
||||
def __init__(self,
|
||||
mgr: DownloadManager,
|
||||
tab_id: str,
|
||||
_id: str,
|
||||
path: str,
|
||||
name: str,
|
||||
url: str,
|
||||
save_path: str):
|
||||
"""
|
||||
:param mgr: BrowserDownloadManager对象
|
||||
:param tab_id: 标签页id
|
||||
:param _id: 任务id
|
||||
:param path: 保存路径
|
||||
:param name: 文件名
|
||||
:param url: url
|
||||
:param save_path: 下载路径
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def rate(self) -> float: ...
|
||||
def rate(self) -> float:
|
||||
"""以百分比形式返回下载进度"""
|
||||
...
|
||||
|
||||
@property
|
||||
def is_done(self) -> bool: ...
|
||||
def is_done(self) -> bool:
|
||||
"""返回任务是否在运行中"""
|
||||
...
|
||||
|
||||
def cancel(self) -> None: ...
|
||||
def cancel(self) -> None:
|
||||
"""取消该任务,如任务已完成,删除已下载的文件"""
|
||||
...
|
||||
|
||||
def wait(self, show: bool = True, timeout=None, cancel_if_timeout=True) -> Union[bool, str]: ...
|
||||
def wait(self,
|
||||
show: bool = True,
|
||||
timeout=None,
|
||||
cancel_if_timeout=True) -> Union[bool, str]:
|
||||
"""等待任务结束
|
||||
:param show: 是否显示下载信息
|
||||
:param timeout: 超时时间(秒),为None则无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消任务
|
||||
:return: 等待成功返回完整路径,否则返回False
|
||||
"""
|
||||
...
|
||||
|
@ -22,9 +22,6 @@ class Listener(object):
|
||||
"""监听器基类"""
|
||||
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: ChromiumBase对象
|
||||
"""
|
||||
self._owner = owner
|
||||
self._address = owner.browser.address
|
||||
self._target_id = owner._target_id
|
||||
@ -41,7 +38,7 @@ class Listener(object):
|
||||
|
||||
self._targets = True
|
||||
self._is_regex = False
|
||||
self._method = ('GET', 'POST')
|
||||
self._method = {'GET', 'POST'}
|
||||
self._res_type = True
|
||||
|
||||
@property
|
||||
@ -50,15 +47,6 @@ class Listener(object):
|
||||
return self._targets
|
||||
|
||||
def set_targets(self, targets=True, is_regex=False, method=('GET', 'POST'), res_type=True):
|
||||
"""指定要等待的数据包
|
||||
:param targets: 要匹配的数据包url特征,可用list等传入多个,为True时获取所有
|
||||
:param is_regex: 设置的target是否正则表达式
|
||||
:param method: 设置监听的请求类型,可指定多个,为True时监听全部
|
||||
:param res_type: 设置监听的资源类型,可指定多个,为True时监听全部,可指定的值有:
|
||||
Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, Prefetch, EventSource, WebSocket,
|
||||
Manifest, SignedExchange, Ping, CSPViolationReport, Preflight, Other
|
||||
:return: None
|
||||
"""
|
||||
if targets is not None:
|
||||
if not isinstance(targets, (str, list, tuple, set)) and targets is not True:
|
||||
raise TypeError('targets只能是str、list、tuple、set、True。')
|
||||
@ -91,15 +79,6 @@ class Listener(object):
|
||||
raise TypeError('res_type参数只能是str、list、tuple、set、True类型。')
|
||||
|
||||
def start(self, targets=None, is_regex=None, method=None, res_type=None):
|
||||
"""拦截目标请求,每次拦截前清空结果
|
||||
:param targets: 要匹配的数据包url特征,可用list等传入多个,为True时获取所有
|
||||
:param is_regex: 设置的target是否正则表达式,为None时保持原来设置
|
||||
:param method: 设置监听的请求类型,可指定多个,默认('GET', 'POST'),为True时监听全部,为None时保持原来设置
|
||||
:param res_type: 设置监听的资源类型,可指定多个,默认为True时监听全部,为None时保持原来设置,可指定的值有:
|
||||
Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, Prefetch, EventSource, WebSocket,
|
||||
Manifest, SignedExchange, Ping, CSPViolationReport, Preflight, Other
|
||||
:return: None
|
||||
"""
|
||||
if targets is not None:
|
||||
if is_regex is None:
|
||||
is_regex = False
|
||||
@ -117,13 +96,6 @@ class Listener(object):
|
||||
self.listening = True
|
||||
|
||||
def wait(self, count=1, timeout=None, fit_count=True, raise_err=None):
|
||||
"""等待符合要求的数据包到达指定数量
|
||||
:param count: 需要捕捉的数据包数量
|
||||
:param timeout: 超时时间(秒),为None无限等待
|
||||
:param fit_count: 是否必须满足总数要求,发生超时,为True返回False,为False返回已捕捉到的数据包
|
||||
:param raise_err: 超时时是否抛出错误,为None时根据Settings设置
|
||||
:return: count为1时返回数据包对象,大于1时返回列表,超时且fit_count为True时返回False
|
||||
"""
|
||||
if not self.listening:
|
||||
raise RuntimeError('监听未启动或已暂停。')
|
||||
if not timeout:
|
||||
@ -157,12 +129,6 @@ class Listener(object):
|
||||
return [self._caught.get_nowait() for _ in range(count)]
|
||||
|
||||
def steps(self, count=None, timeout=None, gap=1):
|
||||
"""用于单步操作,可实现每收到若干个数据包执行一步操作(如翻页)
|
||||
:param count: 需捕获的数据包总数,为None表示无限
|
||||
:param timeout: 每个数据包等待时间(秒),为None表示无限
|
||||
:param gap: 每接收到多少个数据包返回一次数据
|
||||
:return: 用于在接收到监听目标时触发动作的可迭代对象
|
||||
"""
|
||||
if not self.listening:
|
||||
raise RuntimeError('监听未启动或已暂停。')
|
||||
caught = 0
|
||||
@ -181,7 +147,6 @@ class Listener(object):
|
||||
sleep(.03)
|
||||
|
||||
def stop(self):
|
||||
"""停止监听,清空已监听到的列表"""
|
||||
if self.listening:
|
||||
self.pause()
|
||||
self.clear()
|
||||
@ -189,10 +154,6 @@ class Listener(object):
|
||||
self._driver = None
|
||||
|
||||
def pause(self, clear=True):
|
||||
"""暂停监听
|
||||
:param clear: 是否清空已获取队列
|
||||
:return: None
|
||||
"""
|
||||
if self.listening:
|
||||
self._driver.set_callback('Network.requestWillBeSent', None)
|
||||
self._driver.set_callback('Network.responseReceived', None)
|
||||
@ -203,14 +164,12 @@ class Listener(object):
|
||||
self.clear()
|
||||
|
||||
def resume(self):
|
||||
"""继续暂停的监听"""
|
||||
if self.listening:
|
||||
return
|
||||
self._set_callback()
|
||||
self.listening = True
|
||||
|
||||
def clear(self):
|
||||
"""清空结果"""
|
||||
self._request_ids = {}
|
||||
self._extra_info_ids = {}
|
||||
self._caught = Queue(maxsize=0)
|
||||
@ -218,12 +177,6 @@ class Listener(object):
|
||||
self._running_targets = 0
|
||||
|
||||
def wait_silent(self, timeout=None, targets_only=False, limit=0):
|
||||
"""等待所有请求结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param targets_only: 是否只等待targets指定的请求结束
|
||||
:param limit: 剩下多少个连接时视为结束
|
||||
:return: 返回是否等待成功
|
||||
"""
|
||||
if not self.listening:
|
||||
raise RuntimeError('监听未启动或已暂停。')
|
||||
if timeout is None:
|
||||
@ -242,12 +195,6 @@ class Listener(object):
|
||||
return False
|
||||
|
||||
def _to_target(self, target_id, address, owner):
|
||||
"""切换监听的页面对象
|
||||
:param target_id: 新页面对象_target_id
|
||||
:param address: 新页面对象address
|
||||
:param owner: 新页面对象
|
||||
:return: None
|
||||
"""
|
||||
self._target_id = target_id
|
||||
self._address = address
|
||||
self._owner = owner
|
||||
@ -262,7 +209,6 @@ class Listener(object):
|
||||
self._set_callback()
|
||||
|
||||
def _set_callback(self):
|
||||
"""设置监听请求的回调函数"""
|
||||
self._driver.set_callback('Network.requestWillBeSent', self._requestWillBeSent)
|
||||
self._driver.set_callback('Network.requestWillBeSentExtraInfo', self._requestWillBeSentExtraInfo)
|
||||
self._driver.set_callback('Network.responseReceived', self._response_received)
|
||||
@ -271,7 +217,6 @@ class Listener(object):
|
||||
self._driver.set_callback('Network.loadingFailed', self._loading_failed)
|
||||
|
||||
def _requestWillBeSent(self, **kwargs):
|
||||
"""接收到请求时的回调函数"""
|
||||
self._running_requests += 1
|
||||
p = None
|
||||
if self._targets is True:
|
||||
@ -300,19 +245,16 @@ class Listener(object):
|
||||
self._extra_info_ids.setdefault(kwargs['requestId'], {})['obj'] = p if p else False
|
||||
|
||||
def _requestWillBeSentExtraInfo(self, **kwargs):
|
||||
"""接收到请求额外信息时的回调函数"""
|
||||
self._running_requests += 1
|
||||
self._extra_info_ids.setdefault(kwargs['requestId'], {})['request'] = kwargs
|
||||
|
||||
def _response_received(self, **kwargs):
|
||||
"""接收到返回信息时处理方法"""
|
||||
request = self._request_ids.get(kwargs['requestId'], None)
|
||||
if request:
|
||||
request._raw_response = kwargs['response']
|
||||
request._resource_type = kwargs['type']
|
||||
|
||||
def _responseReceivedExtraInfo(self, **kwargs):
|
||||
"""接收到返回额外信息时的回调函数"""
|
||||
self._running_requests -= 1
|
||||
r = self._extra_info_ids.get(kwargs['requestId'], None)
|
||||
if r:
|
||||
@ -327,7 +269,6 @@ class Listener(object):
|
||||
r['response'] = kwargs
|
||||
|
||||
def _loading_finished(self, **kwargs):
|
||||
"""请求完成时处理方法"""
|
||||
self._running_requests -= 1
|
||||
rid = kwargs['requestId']
|
||||
packet = self._request_ids.get(rid)
|
||||
@ -363,7 +304,6 @@ class Listener(object):
|
||||
self._running_targets -= 1
|
||||
|
||||
def _loading_failed(self, **kwargs):
|
||||
"""请求失败时的回调方法"""
|
||||
self._running_requests -= 1
|
||||
r_id = kwargs['requestId']
|
||||
data_packet = self._request_ids.get(r_id, None)
|
||||
@ -393,26 +333,19 @@ class Listener(object):
|
||||
|
||||
class FrameListener(Listener):
|
||||
def _requestWillBeSent(self, **kwargs):
|
||||
"""接收到请求时的回调函数"""
|
||||
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._owner._is_diff_domain and kwargs.get('frameId', None) != self._owner._frame_id:
|
||||
return
|
||||
super()._response_received(**kwargs)
|
||||
|
||||
|
||||
class DataPacket(object):
|
||||
"""返回的数据包管理类"""
|
||||
|
||||
def __init__(self, tab_id, target):
|
||||
"""
|
||||
:param tab_id: 产生这个数据包的tab的id
|
||||
:param target: 监听目标
|
||||
"""
|
||||
self.tab_id = tab_id
|
||||
self.target = target
|
||||
self.is_failed = False
|
||||
@ -479,10 +412,6 @@ class DataPacket(object):
|
||||
return self._fail_info
|
||||
|
||||
def wait_extra_info(self, timeout=None):
|
||||
"""等待额外的信息加载完成
|
||||
:param timeout: 超时时间(秒),None为无限等待
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if timeout is None:
|
||||
while self._responseExtraInfo is None:
|
||||
sleep(.1)
|
||||
@ -511,14 +440,12 @@ class Request(object):
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
"""以大小写不敏感字典返回headers数据"""
|
||||
if self._headers is None:
|
||||
self._headers = CaseInsensitiveDict(self._request['headers'])
|
||||
return self._headers
|
||||
|
||||
@property
|
||||
def postData(self):
|
||||
"""返回postData数据"""
|
||||
if self._postData is None:
|
||||
if self._raw_post_data:
|
||||
postData = self._raw_post_data
|
||||
@ -534,12 +461,10 @@ class Request(object):
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
"""以list形式返回发送的cookies"""
|
||||
return [c['cookie'] for c in self.extra_info.associatedCookies if not c['blockedReasons']]
|
||||
|
||||
@property
|
||||
def extra_info(self):
|
||||
"""返回额外数据"""
|
||||
return RequestExtraInfo(self._data_packet._request_extra_info or {})
|
||||
|
||||
|
||||
@ -557,19 +482,16 @@ class Response(object):
|
||||
|
||||
@property
|
||||
def headers(self):
|
||||
"""以大小写不敏感字典返回headers数据"""
|
||||
if self._headers is None:
|
||||
self._headers = CaseInsensitiveDict(self._response['headers'])
|
||||
return self._headers
|
||||
|
||||
@property
|
||||
def raw_body(self):
|
||||
"""返回未被处理的body文本"""
|
||||
return self._raw_body
|
||||
|
||||
@property
|
||||
def body(self):
|
||||
"""返回body内容,如果是json格式,自动进行转换,如果时图片格式,进行base64转换,其它格式直接返回文本"""
|
||||
if self._body is None:
|
||||
if self._is_base64_body:
|
||||
self._body = b64decode(self._raw_body)
|
||||
@ -593,7 +515,6 @@ class ExtraInfo(object):
|
||||
|
||||
@property
|
||||
def all_info(self):
|
||||
"""以dict形式返回所有额外信息"""
|
||||
return self._extra_info
|
||||
|
||||
def __getattr__(self, item):
|
||||
|
@ -19,21 +19,26 @@ __RES_TYPE__ = Literal['Document', 'Stylesheet', 'Image', 'Media', 'Font', 'Scri
|
||||
|
||||
|
||||
class Listener(object):
|
||||
_owner: ChromiumBase = ...
|
||||
_address: str = ...
|
||||
_target_id: str = ...
|
||||
_targets: Union[str, dict, True, None] = ...
|
||||
_method: Union[set, True] = ...
|
||||
_res_type: Union[set, True] = ...
|
||||
_caught: Optional[Queue] = ...
|
||||
_is_regex: bool = ...
|
||||
_driver: Optional[Driver] = ...
|
||||
_request_ids: Optional[dict] = ...
|
||||
_extra_info_ids: Optional[dict] = ...
|
||||
_running_requests: int = ...
|
||||
_running_targets: int = ...
|
||||
listening: bool = ...
|
||||
|
||||
def __init__(self, owner: ChromiumBase):
|
||||
self._owner: ChromiumBase = ...
|
||||
self._address: str = ...
|
||||
self._target_id: str = ...
|
||||
self._targets: Union[str, dict, None] = ...
|
||||
self._method: set = ...
|
||||
self._res_type: set = ...
|
||||
self._caught: Queue = ...
|
||||
self._is_regex: bool = ...
|
||||
self._driver: Driver = ...
|
||||
self._request_ids: dict = ...
|
||||
self._extra_info_ids: dict = ...
|
||||
self.listening: bool = ...
|
||||
self._running_requests: int = ...
|
||||
self._running_targets: int = ...
|
||||
"""
|
||||
:param owner: 页面对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def targets(self) -> Optional[set]: ...
|
||||
@ -42,42 +47,101 @@ class Listener(object):
|
||||
targets: Union[str, list, tuple, set, bool, None] = True,
|
||||
is_regex: Optional[bool] = False,
|
||||
method: Union[str, list, tuple, set, bool, None] = ('GET', 'POST'),
|
||||
res_type: Union[__RES_TYPE__, list, tuple, set, bool, None] = True) -> None: ...
|
||||
res_type: Union[__RES_TYPE__, list, tuple, set, bool, None] = True) -> None:
|
||||
"""指定要等待的数据包
|
||||
:param targets: 要匹配的数据包url特征,可用list等传入多个,为True时获取所有
|
||||
:param is_regex: 设置的target是否正则表达式
|
||||
:param method: 设置监听的请求类型,可指定多个,为True时监听全部
|
||||
:param res_type: 设置监听的资源类型,可指定多个,为True时监听全部,可指定的值有:
|
||||
Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, Prefetch, EventSource, WebSocket,
|
||||
Manifest, SignedExchange, Ping, CSPViolationReport, Preflight, Other
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def start(self,
|
||||
targets: Union[str, list, tuple, set, bool, None] = None,
|
||||
is_regex: Optional[bool] = None,
|
||||
method: Union[str, list, tuple, set, bool, None] = None,
|
||||
res_type: Union[__RES_TYPE__, list, tuple, set, bool, None] = None) -> None: ...
|
||||
|
||||
def stop(self) -> None: ...
|
||||
|
||||
def pause(self, clear: bool = True) -> None: ...
|
||||
|
||||
def resume(self) -> None: ...
|
||||
res_type: Union[__RES_TYPE__, list, tuple, set, bool, None] = None) -> None:
|
||||
"""拦截目标请求,每次拦截前清空结果
|
||||
:param targets: 要匹配的数据包url特征,可用list等传入多个,为True时获取所有
|
||||
:param is_regex: 设置的target是否正则表达式,为None时保持原来设置
|
||||
:param method: 设置监听的请求类型,可指定多个,默认('GET', 'POST'),为True时监听全部,为None时保持原来设置
|
||||
:param res_type: 设置监听的资源类型,可指定多个,默认为True时监听全部,为None时保持原来设置,可指定的值有:
|
||||
Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, Prefetch, EventSource, WebSocket,
|
||||
Manifest, SignedExchange, Ping, CSPViolationReport, Preflight, Other
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def wait(self,
|
||||
count: int = 1,
|
||||
timeout: float = None,
|
||||
fit_count: bool = True,
|
||||
raise_err: bool = None) -> Union[List[DataPacket], DataPacket, None]: ...
|
||||
raise_err: bool = None) -> Union[List[DataPacket], DataPacket, None]:
|
||||
"""等待符合要求的数据包到达指定数量
|
||||
:param count: 需要捕捉的数据包数量
|
||||
:param timeout: 超时时间(秒),为None无限等待
|
||||
:param fit_count: 是否必须满足总数要求,发生超时,为True返回False,为False返回已捕捉到的数据包
|
||||
:param raise_err: 超时时是否抛出错误,为None时根据Settings设置
|
||||
:return: count为1时返回数据包对象,大于1时返回列表,超时且fit_count为True时返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def steps(self,
|
||||
count: int = None,
|
||||
timeout: float = None,
|
||||
gap=1) -> Iterable[Union[DataPacket, List[DataPacket]]]: ...
|
||||
gap=1) -> Iterable[Union[DataPacket, List[DataPacket]]]:
|
||||
"""用于单步操作,可实现每收到若干个数据包执行一步操作(如翻页)
|
||||
:param count: 需捕获的数据包总数,为None表示无限
|
||||
:param timeout: 每个数据包等待时间(秒),为None表示无限
|
||||
:param gap: 每接收到多少个数据包返回一次数据
|
||||
:return: 用于在接收到监听目标时触发动作的可迭代对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def results(self) -> Union[DataPacket, Dict[str, List[DataPacket]], False]: ...
|
||||
def stop(self) -> None:
|
||||
"""停止监听,清空已监听到的列表"""
|
||||
...
|
||||
|
||||
def clear(self) -> None: ...
|
||||
def pause(self, clear: bool = True) -> None:
|
||||
"""暂停监听
|
||||
:param clear: 是否清空已获取队列
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def resume(self) -> None:
|
||||
"""继续暂停的监听"""
|
||||
...
|
||||
|
||||
def clear(self) -> None:
|
||||
"""清空监听到但还没返回的结果"""
|
||||
...
|
||||
|
||||
def wait_silent(self,
|
||||
timeout: float = None,
|
||||
targets_only: bool = False,
|
||||
limit: int = 0) -> bool: ...
|
||||
limit: int = 0) -> bool:
|
||||
"""等待所有请求结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param targets_only: 是否只等待targets指定的请求结束
|
||||
:param limit: 剩下多少个连接时视为结束
|
||||
:return: 返回是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _to_target(self, target_id: str, address: str, owner: ChromiumBase) -> None: ...
|
||||
def _to_target(self, target_id: str, address: str, owner: ChromiumBase) -> None:
|
||||
"""切换监听的页面对象
|
||||
:param target_id: 新页面对象_target_id
|
||||
:param address: 新页面对象address
|
||||
:param owner: 新页面对象
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _set_callback(self) -> None: ...
|
||||
|
||||
def _requestWillBeSent(self, **kwargs) -> None: ...
|
||||
|
||||
@ -91,34 +155,85 @@ class Listener(object):
|
||||
|
||||
def _loading_failed(self, **kwargs) -> None: ...
|
||||
|
||||
def _set_callback(self) -> None: ...
|
||||
|
||||
|
||||
class FrameListener(Listener):
|
||||
_owner: ChromiumFrame = ...
|
||||
_is_diff: bool = ...
|
||||
|
||||
def __init__(self, owner: ChromiumFrame):
|
||||
self._owner: ChromiumFrame = ...
|
||||
self._is_diff: bool = ...
|
||||
"""
|
||||
:param owner: ChromiumFrame对象
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class DataPacket(object):
|
||||
"""返回的数据包管理类"""
|
||||
"""数据包类"""
|
||||
|
||||
tab_id: str = ...
|
||||
target: str = ...
|
||||
is_failed: bool = ...
|
||||
_raw_request: Optional[dict] = ...
|
||||
_raw_response: Optional[dict] = ...
|
||||
_raw_post_data: Optional[str] = ...
|
||||
_raw_body: Optional[str] = ...
|
||||
_raw_fail_info: Optional[dict] = ...
|
||||
_base64_body: bool = ...
|
||||
_request: Optional[Request] = ...
|
||||
_response: Optional[Response] = ...
|
||||
_fail_info: Optional[FailInfo] = ...
|
||||
_resource_type: Optional[str] = ...
|
||||
_requestExtraInfo: Optional[dict] = ...
|
||||
_responseExtraInfo: Optional[dict] = ...
|
||||
|
||||
def __init__(self, tab_id: str, target: [str, bool]):
|
||||
self.tab_id: str = ...
|
||||
self.target: str = ...
|
||||
self.is_failed: bool = ...
|
||||
self._raw_request: Optional[dict] = ...
|
||||
self._raw_response: Optional[dict] = ...
|
||||
self._raw_post_data: str = ...
|
||||
self._raw_body: str = ...
|
||||
self._raw_fail_info: Optional[dict] = ...
|
||||
self._base64_body: bool = ...
|
||||
self._request: Request = ...
|
||||
self._response: Response = ...
|
||||
self._fail_info: Optional[FailInfo] = ...
|
||||
self._resource_type: str = ...
|
||||
self._requestExtraInfo: Optional[dict] = ...
|
||||
self._responseExtraInfo: Optional[dict] = ...
|
||||
"""
|
||||
:param tab_id: 产生这个数据包的tab的id
|
||||
:param target: 监听目标
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def url(self) -> str:
|
||||
"""请求网址"""
|
||||
...
|
||||
|
||||
@property
|
||||
def method(self) -> str:
|
||||
"""请求类型"""
|
||||
...
|
||||
|
||||
@property
|
||||
def frameId(self) -> str:
|
||||
"""发出请求的frame id"""
|
||||
...
|
||||
|
||||
@property
|
||||
def resourceType(self) -> str:
|
||||
"""资源类型"""
|
||||
...
|
||||
|
||||
@property
|
||||
def request(self) -> Request:
|
||||
"""数据"""
|
||||
...
|
||||
|
||||
@property
|
||||
def response(self) -> Response:
|
||||
"""Response数据"""
|
||||
...
|
||||
|
||||
@property
|
||||
def fail_info(self) -> Optional[FailInfo]:
|
||||
"""请求失败数据"""
|
||||
...
|
||||
|
||||
def wait_extra_info(self, timeout: float = None) -> bool:
|
||||
"""等待额外的信息加载完成
|
||||
:param timeout: 超时时间(秒),None为无限等待
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def _request_extra_info(self) -> Optional[dict]: ...
|
||||
@ -126,116 +241,142 @@ class DataPacket(object):
|
||||
@property
|
||||
def _response_extra_info(self) -> Optional[dict]: ...
|
||||
|
||||
@property
|
||||
def url(self) -> str: ...
|
||||
|
||||
@property
|
||||
def method(self) -> str: ...
|
||||
|
||||
@property
|
||||
def frameId(self) -> str: ...
|
||||
|
||||
@property
|
||||
def resourceType(self) -> str: ...
|
||||
|
||||
@property
|
||||
def request(self) -> Request: ...
|
||||
|
||||
@property
|
||||
def response(self) -> Response: ...
|
||||
|
||||
@property
|
||||
def fail_info(self) -> Optional[FailInfo]: ...
|
||||
|
||||
def wait_extra_info(self, timeout: float = None) -> bool: ...
|
||||
|
||||
|
||||
class Request(object):
|
||||
_data_packet: DataPacket = ...
|
||||
_request: dict = ...
|
||||
_raw_post_data: str = ...
|
||||
_postData: Optional[str] = ...
|
||||
|
||||
url: str = ...
|
||||
_headers: Union[CaseInsensitiveDict, None] = ...
|
||||
method: str = ...
|
||||
|
||||
urlFragment = ...
|
||||
hasPostData = ...
|
||||
postDataEntries = ...
|
||||
mixedContentType = ...
|
||||
initialPriority = ...
|
||||
referrerPolicy = ...
|
||||
isLinkPreload = ...
|
||||
trustTokenParams = ...
|
||||
isSameSite = ...
|
||||
urlFragment: str = ...
|
||||
hasPostData: bool = ...
|
||||
postDataEntries: List[dict] = ...
|
||||
mixedContentType: Literal['blockable', 'optionally-blockable', 'none'] = ...
|
||||
initialPriority: Literal['VeryLow', 'Low', 'Medium', 'High', 'VeryHigh'] = ...
|
||||
referrerPolicy: Literal['unsafe-url', 'no-referrer-when-downgrade', 'no-referrer', 'origin',
|
||||
'origin-when-cross-origin', 'same-origin', 'strict-origin', 'strict-origin-when-cross-origin'] = ...
|
||||
isLinkPreload: bool = ...
|
||||
trustTokenParams: dict = ...
|
||||
isSameSite: bool = ...
|
||||
|
||||
def __init__(self, data_packet: DataPacket, raw_request: dict, post_data: str):
|
||||
self._data_packet: DataPacket = ...
|
||||
self._request: dict = ...
|
||||
self._raw_post_data: str = ...
|
||||
self._postData: str = ...
|
||||
def __init__(self,
|
||||
data_packet: DataPacket,
|
||||
raw_request: dict,
|
||||
post_data: str):
|
||||
"""
|
||||
:param data_packet: DataPacket对象
|
||||
:param raw_request: 未处理的请求数据
|
||||
:param post_data: post发送的数据
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def headers(self) -> dict: ...
|
||||
def headers(self) -> dict:
|
||||
"""以大小写不敏感字典返回headers数据"""
|
||||
...
|
||||
|
||||
@property
|
||||
def postData(self) -> Any: ...
|
||||
def postData(self) -> Any:
|
||||
"""返回postData数据"""
|
||||
...
|
||||
|
||||
@property
|
||||
def cookies(self) -> List[dict]: ...
|
||||
def cookies(self) -> List[dict]:
|
||||
"""以list形式返回发送的cookies"""
|
||||
...
|
||||
|
||||
@property
|
||||
def extra_info(self) -> Optional[RequestExtraInfo]: ...
|
||||
def extra_info(self) -> Optional[RequestExtraInfo]:
|
||||
"""返回额外数据"""
|
||||
...
|
||||
|
||||
|
||||
class Response(object):
|
||||
url = ...
|
||||
status = ...
|
||||
statusText = ...
|
||||
headersText = ...
|
||||
mimeType = ...
|
||||
requestHeaders = ...
|
||||
requestHeadersText = ...
|
||||
connectionReused = ...
|
||||
_data_packet: DataPacket = ...
|
||||
_response: dict = ...
|
||||
_raw_body: str = ...
|
||||
_is_base64_body: bool = ...
|
||||
_body: Union[str, dict, bytes, None] = ...
|
||||
_headers: Union[dict, CaseInsensitiveDict, None] = ...
|
||||
|
||||
url: str = ...
|
||||
status: int = ...
|
||||
statusText: str = ...
|
||||
headersText: str = ...
|
||||
mimeType: str = ...
|
||||
requestHeaders: dict = ...
|
||||
requestHeadersText: str = ...
|
||||
connectionReused: bool = ...
|
||||
connectionId = ...
|
||||
remoteIPAddress = ...
|
||||
remotePort = ...
|
||||
fromDiskCache = ...
|
||||
fromServiceWorker = ...
|
||||
fromPrefetchCache = ...
|
||||
encodedDataLength = ...
|
||||
timing = ...
|
||||
serviceWorkerResponseSource = ...
|
||||
responseTime = ...
|
||||
cacheStorageCacheName = ...
|
||||
protocol = ...
|
||||
alternateProtocolUsage = ...
|
||||
securityState = ...
|
||||
securityDetails = ...
|
||||
remoteIPAddress: str = ...
|
||||
remotePort: int = ...
|
||||
fromDiskCache: bool = ...
|
||||
fromServiceWorker: bool = ...
|
||||
fromPrefetchCache: bool = ...
|
||||
fromEarlyHints: bool = ...
|
||||
serviceWorkerRouterInfo: dict = ...
|
||||
encodedDataLength: int = ...
|
||||
timing: dict = ...
|
||||
serviceWorkerResponseSource: Literal['cache-storage', 'http-cache', 'fallback-code', 'network'] = ...
|
||||
responseTime: float = ...
|
||||
cacheStorageCacheName: str = ...
|
||||
protocol: str = ...
|
||||
alternateProtocolUsage: Literal['alternativeJobWonWithoutRace', 'alternativeJobWonRace', 'mainJobWonRace',
|
||||
'mappingMissing', 'broken', 'dnsAlpnH3JobWonWithoutRace', 'dnsAlpnH3JobWonRace', 'unspecifiedReason'] = ...
|
||||
securityState: Literal['unknown', 'neutral', 'insecure', 'secure', 'info', 'insecure-broken'] = ...
|
||||
securityDetails: dict = ...
|
||||
|
||||
def __init__(self, data_packet: DataPacket, raw_response: dict, raw_body: str, base64_body: bool):
|
||||
self._data_packet: DataPacket = ...
|
||||
self._response: dict = ...
|
||||
self._raw_body: str = ...
|
||||
self._is_base64_body: bool = ...
|
||||
self._body: Union[str, dict, None] = ...
|
||||
self._headers: dict = ...
|
||||
def __init__(self,
|
||||
data_packet: DataPacket,
|
||||
raw_response: dict,
|
||||
raw_body: str,
|
||||
base64_body: bool):
|
||||
"""
|
||||
:param data_packet: DataPacket对象
|
||||
:param raw_response: 未处理的response信息
|
||||
:param raw_body: 未处理的body
|
||||
:param base64_body: body是否base64格式
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def extra_info(self) -> Optional[ResponseExtraInfo]: ...
|
||||
def headers(self) -> CaseInsensitiveDict:
|
||||
"""以大小写不敏感字典返回headers数据"""
|
||||
...
|
||||
|
||||
@property
|
||||
def headers(self) -> CaseInsensitiveDict: ...
|
||||
def raw_body(self) -> str:
|
||||
"""返回未被处理的body文本"""
|
||||
...
|
||||
|
||||
@property
|
||||
def raw_body(self) -> str: ...
|
||||
def body(self) -> Any:
|
||||
"""返回body内容,如果是json格式,自动进行转换,如果时图片格式,进行base64转换,其它格式直接返回文本"""
|
||||
...
|
||||
|
||||
@property
|
||||
def body(self) -> Any: ...
|
||||
def extra_info(self) -> Optional[ResponseExtraInfo]:
|
||||
"""额外信息"""
|
||||
...
|
||||
|
||||
|
||||
class ExtraInfo(object):
|
||||
_extra_info: dict = ...
|
||||
|
||||
def __init__(self, extra_info: dict):
|
||||
self._extra_info: dict = ...
|
||||
"""
|
||||
:param extra_info: dict格式信息
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def all_info(self) -> dict: ...
|
||||
def all_info(self) -> dict:
|
||||
"""以dict形式返回所有额外信息"""
|
||||
...
|
||||
|
||||
|
||||
class RequestExtraInfo(ExtraInfo):
|
||||
@ -261,10 +402,14 @@ class ResponseExtraInfo(ExtraInfo):
|
||||
class FailInfo(object):
|
||||
_data_packet: DataPacket
|
||||
_fail_info: dict
|
||||
_fail_info: float
|
||||
errorText: str
|
||||
canceled: bool
|
||||
blockedReason: Optional[str]
|
||||
corsErrorStatus: Optional[str]
|
||||
|
||||
def __init__(self, data_packet: DataPacket, fail_info: dict): ...
|
||||
def __init__(self, data_packet: DataPacket, fail_info: dict):
|
||||
"""
|
||||
:param data_packet: DataPacket对象
|
||||
:param fail_info: 返回的失败数据
|
||||
"""
|
||||
...
|
||||
|
@ -9,14 +9,10 @@
|
||||
|
||||
class ElementRect(object):
|
||||
def __init__(self, ele):
|
||||
"""
|
||||
:param ele: ChromiumElement
|
||||
"""
|
||||
self._ele = ele
|
||||
|
||||
@property
|
||||
def corners(self):
|
||||
"""返回元素四个角坐标,顺序:左上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
||||
vr = self._get_viewport_rect('border')
|
||||
r = self._ele.owner._run_cdp_loaded('Page.getLayoutMetrics')['visualViewport']
|
||||
sx = r['pageX']
|
||||
@ -25,53 +21,44 @@ class ElementRect(object):
|
||||
|
||||
@property
|
||||
def viewport_corners(self):
|
||||
"""返回元素四个角视口坐标,顺序:左上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
||||
r = self._get_viewport_rect('border')
|
||||
return (r[0], r[1]), (r[2], r[3]), (r[4], r[5]), (r[6], r[7])
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""返回元素大小,格式(宽, 高)"""
|
||||
border = self._ele.owner._run_cdp('DOM.getBoxModel', backendNodeId=self._ele._backend_id,
|
||||
nodeId=self._ele._node_id, objectId=self._ele._obj_id)['model']['border']
|
||||
return border[2] - border[0], border[5] - border[1]
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
"""返回元素左上角的绝对坐标"""
|
||||
return self._get_page_coord(*self.viewport_location)
|
||||
|
||||
@property
|
||||
def midpoint(self):
|
||||
"""返回元素中间点的绝对坐标"""
|
||||
return self._get_page_coord(*self.viewport_midpoint)
|
||||
|
||||
@property
|
||||
def click_point(self):
|
||||
"""返回元素接受点击的点的绝对坐标"""
|
||||
return self._get_page_coord(*self.viewport_click_point)
|
||||
|
||||
@property
|
||||
def viewport_location(self):
|
||||
"""返回元素左上角在视口中的坐标"""
|
||||
m = self._get_viewport_rect('border')
|
||||
return m[0], m[1]
|
||||
|
||||
@property
|
||||
def viewport_midpoint(self):
|
||||
"""返回元素中间点在视口中的坐标"""
|
||||
m = self._get_viewport_rect('border')
|
||||
return m[0] + (m[2] - m[0]) // 2, m[3] + (m[5] - m[3]) // 2
|
||||
|
||||
@property
|
||||
def viewport_click_point(self):
|
||||
"""返回元素接受点击的点视口坐标"""
|
||||
m = self._get_viewport_rect('padding')
|
||||
return self.viewport_midpoint[0], m[1] + 3
|
||||
|
||||
@property
|
||||
def screen_location(self):
|
||||
"""返回元素左上角在屏幕上坐标,左上角为(0, 0)"""
|
||||
vx, vy = self._ele.owner.rect.viewport_location
|
||||
ex, ey = self.viewport_location
|
||||
pr = self._ele.owner._run_js('return window.devicePixelRatio;')
|
||||
@ -79,7 +66,6 @@ class ElementRect(object):
|
||||
|
||||
@property
|
||||
def screen_midpoint(self):
|
||||
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
||||
vx, vy = self._ele.owner.rect.viewport_location
|
||||
ex, ey = self.viewport_midpoint
|
||||
pr = self._ele.owner._run_js('return window.devicePixelRatio;')
|
||||
@ -87,7 +73,6 @@ class ElementRect(object):
|
||||
|
||||
@property
|
||||
def screen_click_point(self):
|
||||
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
||||
vx, vy = self._ele.owner.rect.viewport_location
|
||||
ex, ey = self.viewport_click_point
|
||||
pr = self._ele.owner._run_js('return window.devicePixelRatio;')
|
||||
@ -95,20 +80,14 @@ class ElementRect(object):
|
||||
|
||||
@property
|
||||
def scroll_position(self):
|
||||
"""返回滚动条位置,格式:(x, y)"""
|
||||
r = self._ele._run_js('return this.scrollLeft.toString() + " " + this.scrollTop.toString();')
|
||||
w, h = r.split(' ')
|
||||
return int(w), int(h)
|
||||
|
||||
def _get_viewport_rect(self, quad):
|
||||
"""按照类型返回在可视窗口中的范围
|
||||
:param quad: 方框类型,margin border padding
|
||||
:return: 四个角坐标
|
||||
"""
|
||||
return self._ele.owner._run_cdp('DOM.getBoxModel', backendNodeId=self._ele._backend_id)['model'][quad]
|
||||
|
||||
def _get_page_coord(self, x, y):
|
||||
"""根据视口坐标获取绝对坐标"""
|
||||
r = self._ele.owner._run_cdp_loaded('Page.getLayoutMetrics')['visualViewport']
|
||||
sx = r['pageX']
|
||||
sy = r['pageY']
|
||||
@ -117,19 +96,14 @@ class ElementRect(object):
|
||||
|
||||
class TabRect(object):
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: Page对象和Tab对象
|
||||
"""
|
||||
self._owner = owner
|
||||
|
||||
@property
|
||||
def window_state(self):
|
||||
"""返回窗口状态:normal、fullscreen、maximized、minimized"""
|
||||
return self._get_window_rect()['windowState']
|
||||
|
||||
@property
|
||||
def window_location(self):
|
||||
"""返回窗口在屏幕上的坐标,左上角为(0, 0)"""
|
||||
r = self._get_window_rect()
|
||||
if r['windowState'] in ('maximized', 'fullscreen'):
|
||||
return 0, 0
|
||||
@ -137,7 +111,6 @@ class TabRect(object):
|
||||
|
||||
@property
|
||||
def window_size(self):
|
||||
"""返回窗口大小"""
|
||||
r = self._get_window_rect()
|
||||
if r['windowState'] == 'fullscreen':
|
||||
return r['width'], r['height']
|
||||
@ -148,14 +121,12 @@ class TabRect(object):
|
||||
|
||||
@property
|
||||
def page_location(self):
|
||||
"""返回页面左上角在屏幕中坐标,左上角为(0, 0)"""
|
||||
w, h = self.viewport_location
|
||||
r = self._get_page_rect()['layoutViewport']
|
||||
return w - r['pageX'], h - r['pageY']
|
||||
|
||||
@property
|
||||
def viewport_location(self):
|
||||
"""返回视口在屏幕中坐标,左上角为(0, 0)"""
|
||||
w_bl, h_bl = self.window_location
|
||||
w_bs, h_bs = self.window_size
|
||||
w_vs, h_vs = self.viewport_size_with_scrollbar
|
||||
@ -163,35 +134,29 @@ class TabRect(object):
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""返回页面总宽高,格式:(宽, 高)"""
|
||||
r = self._get_page_rect()['contentSize']
|
||||
return r['width'], r['height']
|
||||
|
||||
@property
|
||||
def viewport_size(self):
|
||||
"""返回视口宽高,不包括滚动条,格式:(宽, 高)"""
|
||||
r = self._get_page_rect()['visualViewport']
|
||||
return r['clientWidth'], r['clientHeight']
|
||||
|
||||
@property
|
||||
def viewport_size_with_scrollbar(self):
|
||||
"""返回视口宽高,包括滚动条,格式:(宽, 高)"""
|
||||
r = self._owner._run_js('return window.innerWidth.toString() + " " + window.innerHeight.toString();')
|
||||
w, h = r.split(' ')
|
||||
return int(w), int(h)
|
||||
|
||||
@property
|
||||
def scroll_position(self):
|
||||
"""返回滚动条位置,格式:(x, y)"""
|
||||
r = self._get_page_rect()['visualViewport']
|
||||
return r['pageX'], r['pageY']
|
||||
|
||||
def _get_page_rect(self):
|
||||
"""获取页面范围信息"""
|
||||
return self._owner._run_cdp_loaded('Page.getLayoutMetrics')
|
||||
|
||||
def _get_window_rect(self):
|
||||
"""获取窗口范围信息"""
|
||||
return self._owner.browser._driver.run('Browser.getWindowForTarget', targetId=self._owner.tab_id)['bounds']
|
||||
|
||||
|
||||
@ -199,51 +164,40 @@ class FrameRect(object):
|
||||
"""异域iframe使用"""
|
||||
|
||||
def __init__(self, frame):
|
||||
"""
|
||||
:param frame: ChromiumFrame对象
|
||||
"""
|
||||
self._frame = frame
|
||||
|
||||
@property
|
||||
def location(self):
|
||||
"""返回iframe元素左上角的绝对坐标"""
|
||||
return self._frame.frame_ele.rect.location
|
||||
|
||||
@property
|
||||
def viewport_location(self):
|
||||
"""返回元素在视口中坐标,左上角为(0, 0)"""
|
||||
return self._frame.frame_ele.rect.viewport_location
|
||||
|
||||
@property
|
||||
def screen_location(self):
|
||||
"""返回元素左上角在屏幕上坐标,左上角为(0, 0)"""
|
||||
return self._frame.frame_ele.rect.screen_location
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""返回frame内页面尺寸,格式:(宽, 高)"""
|
||||
w = self._frame.doc_ele._run_js('return this.body.scrollWidth')
|
||||
h = self._frame.doc_ele._run_js('return this.body.scrollHeight')
|
||||
return w, h
|
||||
|
||||
@property
|
||||
def viewport_size(self):
|
||||
"""返回视口宽高,格式:(宽, 高)"""
|
||||
return self._frame.frame_ele.rect.size
|
||||
|
||||
@property
|
||||
def corners(self):
|
||||
"""返回元素四个角坐标,顺序:左上、右上、右下、左下"""
|
||||
return self._frame.frame_ele.rect.corners
|
||||
|
||||
@property
|
||||
def viewport_corners(self):
|
||||
"""返回元素四个角视口坐标,顺序:左上、右上、右下、左下"""
|
||||
return self._frame.frame_ele.rect.viewport_corners
|
||||
|
||||
@property
|
||||
def scroll_position(self):
|
||||
"""返回滚动条位置,格式:(x, y)"""
|
||||
r = self._frame.doc_ele._run_js('return this.documentElement.scrollLeft.toString() + " " '
|
||||
'+ this.documentElement.scrollTop.toString();')
|
||||
w, h = r.split(' ')
|
||||
|
@ -17,113 +17,200 @@ from .._pages.mix_page import MixPage
|
||||
|
||||
|
||||
class ElementRect(object):
|
||||
_ele: ChromiumElement = ...
|
||||
def __init__(self, ele: ChromiumElement):
|
||||
self._ele: ChromiumElement = ...
|
||||
"""
|
||||
:param ele: ChromiumElement对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def size(self) -> Tuple[float, float]: ...
|
||||
def corners(self) -> Tuple[Tuple[float, float], ...]:
|
||||
"""返回元素四个角坐标,顺序:左上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
||||
...
|
||||
|
||||
@property
|
||||
def location(self) -> Tuple[float, float]: ...
|
||||
def viewport_corners(self) -> Tuple[Tuple[float, float], ...]:
|
||||
"""返回元素四个角视口坐标,顺序:左上、右上、右下、左下,没有大小的元素抛出NoRectError"""
|
||||
...
|
||||
|
||||
@property
|
||||
def midpoint(self) -> Tuple[float, float]: ...
|
||||
def size(self) -> Tuple[float, float]:
|
||||
"""返回元素大小,格式(宽, 高)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def click_point(self) -> Tuple[float, float]: ...
|
||||
def location(self) -> Tuple[float, float]:
|
||||
"""返回元素左上角的绝对坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_location(self) -> Tuple[float, float]: ...
|
||||
def midpoint(self) -> Tuple[float, float]:
|
||||
"""返回元素中间点的绝对坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_midpoint(self) -> Tuple[float, float]: ...
|
||||
def click_point(self) -> Tuple[float, float]:
|
||||
"""返回元素接受点击的点的绝对坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_click_point(self) -> Tuple[float, float]: ...
|
||||
def viewport_location(self) -> Tuple[float, float]:
|
||||
"""返回元素左上角在视口中的坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def screen_location(self) -> Tuple[float, float]: ...
|
||||
def viewport_midpoint(self) -> Tuple[float, float]:
|
||||
"""返回元素中间点在视口中的坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def screen_midpoint(self) -> Tuple[float, float]: ...
|
||||
def viewport_click_point(self) -> Tuple[float, float]:
|
||||
"""返回元素接受点击的点视口坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def screen_click_point(self) -> Tuple[float, float]: ...
|
||||
def screen_location(self) -> Tuple[float, float]:
|
||||
"""返回元素左上角在屏幕上坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def corners(self) -> Tuple[Tuple[float, float], ...]: ...
|
||||
def screen_midpoint(self) -> Tuple[float, float]:
|
||||
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_corners(self) -> Tuple[Tuple[float, float], ...]: ...
|
||||
def screen_click_point(self) -> Tuple[float, float]:
|
||||
"""返回元素中点在屏幕上坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def scroll_position(self) -> Tuple[float, float]: ...
|
||||
def scroll_position(self) -> Tuple[float, float]:
|
||||
"""返回滚动条位置,格式:(x, y)"""
|
||||
...
|
||||
|
||||
def _get_viewport_rect(self, quad: str) -> Union[list, None]: ...
|
||||
def _get_viewport_rect(self, quad: str) -> Union[list, None]:
|
||||
"""按照类型返回在可视窗口中的范围
|
||||
:param quad: 方框类型,margin border padding
|
||||
:return: 四个角坐标
|
||||
"""
|
||||
...
|
||||
|
||||
def _get_page_coord(self, x: float, y: float) -> Tuple[float, float]: ...
|
||||
def _get_page_coord(self, x: float, y: float) -> Tuple[float, float]:
|
||||
"""根据视口坐标获取绝对坐标
|
||||
:param x: 视口x坐标
|
||||
:param y: 视口y坐标
|
||||
:return: 坐标元组
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class TabRect(object):
|
||||
def __init__(self, owner: ChromiumBase):
|
||||
"""
|
||||
:param owner: Page对象和Tab对象
|
||||
"""
|
||||
self._owner: Union[ChromiumPage, ChromiumTab, MixPage, MixTab] = ...
|
||||
|
||||
@property
|
||||
def window_state(self) -> str: ...
|
||||
def window_state(self) -> str:
|
||||
"""返回窗口状态:normal、fullscreen、maximized、minimized"""
|
||||
...
|
||||
|
||||
@property
|
||||
def window_location(self) -> Tuple[int, int]: ...
|
||||
def window_location(self) -> Tuple[int, int]:
|
||||
"""返回窗口在屏幕上的坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def page_location(self) -> Tuple[int, int]: ...
|
||||
def window_size(self) -> Tuple[int, int]:
|
||||
"""返回窗口大小"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_location(self) -> Tuple[int, int]: ...
|
||||
def page_location(self) -> Tuple[int, int]:
|
||||
"""返回页面左上角在屏幕中坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def window_size(self) -> Tuple[int, int]: ...
|
||||
def viewport_location(self) -> Tuple[int, int]:
|
||||
"""返回视口在屏幕中坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def size(self) -> Tuple[int, int]: ...
|
||||
def size(self) -> Tuple[int, int]:
|
||||
"""返回页面总宽高,格式:(宽, 高)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_size(self) -> Tuple[int, int]: ...
|
||||
def viewport_size(self) -> Tuple[int, int]:
|
||||
"""返回视口宽高,不包括滚动条,格式:(宽, 高)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_size_with_scrollbar(self) -> Tuple[int, int]: ...
|
||||
def viewport_size_with_scrollbar(self) -> Tuple[int, int]:
|
||||
"""返回视口宽高,包括滚动条,格式:(宽, 高)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def scroll_position(self) -> Tuple[int, int]: ...
|
||||
def scroll_position(self) -> Tuple[int, int]:
|
||||
"""返回滚动条位置,格式:(x, y)"""
|
||||
...
|
||||
|
||||
def _get_page_rect(self) -> dict: ...
|
||||
def _get_page_rect(self) -> dict:
|
||||
"""获取页面范围信息"""
|
||||
...
|
||||
|
||||
def _get_window_rect(self) -> dict: ...
|
||||
def _get_window_rect(self) -> dict:
|
||||
"""获取窗口范围信息"""
|
||||
...
|
||||
|
||||
|
||||
class FrameRect(object):
|
||||
_frame: ChromiumFrame = ...
|
||||
|
||||
def __init__(self, frame: ChromiumFrame):
|
||||
self._frame: ChromiumFrame = ...
|
||||
"""
|
||||
:param frame: ChromiumFrame对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def location(self) -> Tuple[float, float]: ...
|
||||
def location(self) -> Tuple[float, float]:
|
||||
"""返回iframe元素左上角的绝对坐标"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_location(self) -> Tuple[float, float]: ...
|
||||
def viewport_location(self) -> Tuple[float, float]:
|
||||
"""返回元素在视口中坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def screen_location(self) -> Tuple[float, float]: ...
|
||||
def screen_location(self) -> Tuple[float, float]:
|
||||
"""返回元素左上角在屏幕上坐标,左上角为(0, 0)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def size(self) -> Tuple[float, float]: ...
|
||||
def size(self) -> Tuple[float, float]:
|
||||
"""返回frame内页面尺寸,格式:(宽, 高)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_size(self) -> Tuple[float, float]: ...
|
||||
def viewport_size(self) -> Tuple[float, float]:
|
||||
"""返回视口宽高,格式:(宽, 高)"""
|
||||
...
|
||||
|
||||
@property
|
||||
def corners(self) -> Tuple[Tuple[float, float], ...]: ...
|
||||
def corners(self) -> Tuple[Tuple[float, float], ...]:
|
||||
"""返回元素四个角坐标,顺序:左上、右上、右下、左下"""
|
||||
...
|
||||
|
||||
@property
|
||||
def viewport_corners(self) -> Tuple[Tuple[float, float], ...]: ...
|
||||
def viewport_corners(self) -> Tuple[Tuple[float, float], ...]:
|
||||
"""返回元素四个角视口坐标,顺序:左上、右上、右下、左下"""
|
||||
...
|
||||
|
||||
@property
|
||||
def scroll_position(self) -> Tuple[float, float]: ...
|
||||
def scroll_position(self) -> Tuple[float, float]:
|
||||
"""返回滚动条位置,格式:(x, y)"""
|
||||
...
|
||||
|
@ -25,75 +25,48 @@ class Scroller(object):
|
||||
self._wait_scrolled()
|
||||
|
||||
def to_top(self):
|
||||
"""滚动到顶端,水平位置不变"""
|
||||
self._run_js('{}.scrollTo({}.scrollLeft, 0);')
|
||||
return self._owner
|
||||
|
||||
def to_bottom(self):
|
||||
"""滚动到底端,水平位置不变"""
|
||||
self._run_js('{}.scrollTo({}.scrollLeft, {}.scrollHeight);')
|
||||
return self._owner
|
||||
|
||||
def to_half(self):
|
||||
"""滚动到垂直中间位置,水平位置不变"""
|
||||
self._run_js('{}.scrollTo({}.scrollLeft, {}.scrollHeight/2);')
|
||||
return self._owner
|
||||
|
||||
def to_rightmost(self):
|
||||
"""滚动到最右边,垂直位置不变"""
|
||||
self._run_js('{}.scrollTo({}.scrollWidth, {}.scrollTop);')
|
||||
return self._owner
|
||||
|
||||
def to_leftmost(self):
|
||||
"""滚动到最左边,垂直位置不变"""
|
||||
self._run_js('{}.scrollTo(0, {}.scrollTop);')
|
||||
return self._owner
|
||||
|
||||
def to_location(self, x, y):
|
||||
"""滚动到指定位置
|
||||
:param x: 水平距离
|
||||
:param y: 垂直距离
|
||||
:return: None
|
||||
"""
|
||||
self._run_js(f'{{}}.scrollTo({x}, {y});')
|
||||
return self._owner
|
||||
|
||||
def up(self, pixel=300):
|
||||
"""向上滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
pixel = -pixel
|
||||
self._run_js(f'{{}}.scrollBy(0, {pixel});')
|
||||
return self._owner
|
||||
|
||||
def down(self, pixel=300):
|
||||
"""向下滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
self._run_js(f'{{}}.scrollBy(0, {pixel});')
|
||||
return self._owner
|
||||
|
||||
def left(self, pixel=300):
|
||||
"""向左滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
pixel = -pixel
|
||||
self._run_js(f'{{}}.scrollBy({pixel}, 0);')
|
||||
return self._owner
|
||||
|
||||
def right(self, pixel=300):
|
||||
"""向右滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
self._run_js(f'{{}}.scrollBy({pixel}, 0);')
|
||||
return self._owner
|
||||
|
||||
def _wait_scrolled(self):
|
||||
"""等待滚动结束"""
|
||||
if not self._wait_complete:
|
||||
return
|
||||
|
||||
@ -118,44 +91,26 @@ class Scroller(object):
|
||||
|
||||
class ElementScroller(Scroller):
|
||||
def to_see(self, center=None):
|
||||
"""滚动页面直到元素可见
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
self._owner.owner.scroll.to_see(self._owner, center=center)
|
||||
return self._owner
|
||||
|
||||
def to_center(self):
|
||||
"""元素尽量滚动到视口中间"""
|
||||
self._owner.owner.scroll.to_see(self._owner, center=True)
|
||||
return self._owner
|
||||
|
||||
|
||||
class PageScroller(Scroller):
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: 页面对象
|
||||
"""
|
||||
super().__init__(owner)
|
||||
self._t1 = 'window'
|
||||
self._t2 = 'document.documentElement'
|
||||
|
||||
def to_see(self, loc_or_ele, center=None):
|
||||
"""滚动页面直到元素可见
|
||||
:param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
ele = self._owner._ele(loc_or_ele)
|
||||
self._to_see(ele, center)
|
||||
return self._owner
|
||||
|
||||
def _to_see(self, ele, center):
|
||||
"""执行滚动页面直到元素可见
|
||||
:param ele: 元素对象
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
txt = 'true' if center else 'false'
|
||||
ele._run_js(f'this.scrollIntoViewIfNeeded({txt});')
|
||||
if center or (center is not False and ele.states.is_covered):
|
||||
@ -173,19 +128,14 @@ class PageScroller(Scroller):
|
||||
|
||||
|
||||
class FrameScroller(PageScroller):
|
||||
def __init__(self, frame):
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param frame: ChromiumFrame对象
|
||||
:param owner: ChromiumFrame对象
|
||||
"""
|
||||
super().__init__(frame.doc_ele)
|
||||
super().__init__(owner.doc_ele)
|
||||
self._t1 = self._t2 = 'this.documentElement'
|
||||
|
||||
def to_see(self, loc_or_ele, center=None):
|
||||
"""滚动页面直到元素可见
|
||||
:param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
ele = self._owner._ele(loc_or_ele)
|
||||
self._to_see(ele, center)
|
||||
return self._owner
|
||||
|
@ -16,116 +16,304 @@ from .._pages.tabs import ChromiumTab, MixTab
|
||||
|
||||
|
||||
class Scroller(object):
|
||||
_owner: Union[ChromiumBase, ChromiumElement] = ...
|
||||
_t1: str = ...
|
||||
_t2: str = ...
|
||||
_owner: Union[ChromiumBase, ChromiumElement] = ...
|
||||
_wait_complete: bool = ...
|
||||
|
||||
def __init__(self, owner: Union[ChromiumBase, ChromiumElement]): ...
|
||||
|
||||
def to_top(self) -> None:
|
||||
"""滚动到顶端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_bottom(self) -> None:
|
||||
"""滚动到底端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_half(self) -> None:
|
||||
"""滚动到垂直中间位置,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_rightmost(self) -> None:
|
||||
"""滚动到最右边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def to_leftmost(self) -> None:
|
||||
"""滚动到最左边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def to_location(self, x: int, y: int) -> None:
|
||||
"""滚动到指定位置
|
||||
:param x: 水平距离
|
||||
:param y: 垂直距离
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def up(self, pixel: int = 300) -> None:
|
||||
"""向上滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def down(self, pixel: int = 300) -> None:
|
||||
"""向下滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def left(self, pixel: int = 300) -> None:
|
||||
"""向左滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self, pixel: int = 300) -> None:
|
||||
"""向右滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _run_js(self, js: str): ...
|
||||
|
||||
def to_top(self) -> None: ...
|
||||
|
||||
def to_bottom(self) -> None: ...
|
||||
|
||||
def to_half(self) -> None: ...
|
||||
|
||||
def to_rightmost(self) -> None: ...
|
||||
|
||||
def to_leftmost(self) -> None: ...
|
||||
|
||||
def to_location(self, x: int, y: int) -> None: ...
|
||||
|
||||
def up(self, pixel: int = 300) -> None: ...
|
||||
|
||||
def down(self, pixel: int = 300) -> None: ...
|
||||
|
||||
def left(self, pixel: int = 300) -> None: ...
|
||||
|
||||
def right(self, pixel: int = 300) -> None: ...
|
||||
|
||||
def _wait_scrolled(self) -> None: ...
|
||||
def _wait_scrolled(self) -> None:
|
||||
"""等待滚动结束"""
|
||||
...
|
||||
|
||||
|
||||
class ElementScroller(Scroller):
|
||||
_owner: ChromiumElement = ...
|
||||
|
||||
def to_see(self, center: Union[bool, None] = None) -> ChromiumElement: ...
|
||||
def __init__(self, owner: ChromiumElement):
|
||||
"""
|
||||
:param owner: 元素对象
|
||||
"""
|
||||
...
|
||||
|
||||
def to_center(self) -> ChromiumElement: ...
|
||||
def to_see(self, center: Union[bool, None] = None) -> ChromiumElement:
|
||||
"""滚动页面直到元素可见
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def to_top(self) -> ChromiumElement: ...
|
||||
def to_center(self) -> ChromiumElement:
|
||||
"""元素尽量滚动到视口中间"""
|
||||
...
|
||||
|
||||
def to_bottom(self) -> ChromiumElement: ...
|
||||
def to_top(self) -> ChromiumElement:
|
||||
"""滚动到顶端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_half(self) -> ChromiumElement: ...
|
||||
def to_bottom(self) -> ChromiumElement:
|
||||
"""滚动到底端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_rightmost(self) -> ChromiumElement: ...
|
||||
def to_half(self) -> ChromiumElement:
|
||||
"""滚动到垂直中间位置,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_leftmost(self) -> ChromiumElement: ...
|
||||
def to_rightmost(self) -> ChromiumElement:
|
||||
"""滚动到最右边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def to_location(self, x: int, y: int) -> ChromiumElement: ...
|
||||
def to_leftmost(self) -> ChromiumElement:
|
||||
"""滚动到最左边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def up(self, pixel: int = 300) -> ChromiumElement: ...
|
||||
def to_location(self, x: int, y: int) -> ChromiumElement:
|
||||
"""滚动到指定位置
|
||||
:param x: 水平距离
|
||||
:param y: 垂直距离
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def down(self, pixel: int = 300) -> ChromiumElement: ...
|
||||
def up(self, pixel: int = 300) -> ChromiumElement:
|
||||
"""向上滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def left(self, pixel: int = 300) -> ChromiumElement: ...
|
||||
def down(self, pixel: int = 300) -> ChromiumElement:
|
||||
"""向下滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self, pixel: int = 300) -> ChromiumElement: ...
|
||||
def left(self, pixel: int = 300) -> ChromiumElement:
|
||||
"""向左滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self, pixel: int = 300) -> ChromiumElement:
|
||||
"""向右滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class PageScroller(Scroller):
|
||||
def __init__(self, owner: Union[ChromiumBase, ChromiumElement]): ...
|
||||
_owner: Union[ChromiumBase, ChromiumElement] = ...
|
||||
|
||||
def __init__(self, owner: Union[ChromiumBase, ChromiumElement]):
|
||||
"""
|
||||
:param owner: 页面对象
|
||||
"""
|
||||
...
|
||||
|
||||
def to_see(self,
|
||||
loc_or_ele: Union[str, tuple, ChromiumElement],
|
||||
center: Union[bool, None] = None) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
center: Union[bool, None] = None) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动页面直到元素可见
|
||||
:param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def to_top(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def to_top(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动到顶端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_bottom(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def to_bottom(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动到底端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_half(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def to_half(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动到垂直中间位置,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_rightmost(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def to_rightmost(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动到最右边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def to_leftmost(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def to_leftmost(self) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动到最左边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def to_location(self, x: int, y: int) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def to_location(self, x: int, y: int) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""滚动到指定位置
|
||||
:param x: 水平距离
|
||||
:param y: 垂直距离
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def up(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def up(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""向上滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def down(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def down(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""向下滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def left(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def left(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""向左滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]: ...
|
||||
def right(self, pixel: int = 300) -> Union[ChromiumTab, MixTab, ChromiumPage, MixPage]:
|
||||
"""向右滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _to_see(self, ele: ChromiumElement, center: Union[bool, None]) -> None: ...
|
||||
def _to_see(self, ele: ChromiumElement, center: Union[bool, None]) -> None:
|
||||
"""执行滚动页面直到元素可见
|
||||
:param ele: 元素对象
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class FrameScroller(PageScroller):
|
||||
def __init__(self, frame: ChromiumFrame): ...
|
||||
_owner: ChromiumElement = ...
|
||||
|
||||
def to_top(self) -> ChromiumFrame: ...
|
||||
def __init__(self, owner: ChromiumFrame): ...
|
||||
|
||||
def to_bottom(self) -> ChromiumFrame: ...
|
||||
def to_see(self,
|
||||
loc_or_ele: Union[str, tuple, ChromiumElement],
|
||||
center: Union[bool, None] = None) -> ChromiumFrame:
|
||||
"""滚动页面直到元素可见
|
||||
:param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串
|
||||
:param center: 是否尽量滚动到页面正中,为None时如果被遮挡,则滚动到页面正中
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def to_half(self) -> ChromiumFrame: ...
|
||||
def to_top(self) -> ChromiumFrame:
|
||||
"""滚动到顶端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_rightmost(self) -> ChromiumFrame: ...
|
||||
def to_bottom(self) -> ChromiumFrame:
|
||||
"""滚动到底端,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_leftmost(self) -> ChromiumFrame: ...
|
||||
def to_half(self) -> ChromiumFrame:
|
||||
"""滚动到垂直中间位置,水平位置不变"""
|
||||
...
|
||||
|
||||
def to_location(self, x: int, y: int) -> ChromiumFrame: ...
|
||||
def to_rightmost(self) -> ChromiumFrame:
|
||||
"""滚动到最右边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def up(self, pixel: int = 300) -> ChromiumFrame: ...
|
||||
def to_leftmost(self) -> ChromiumFrame:
|
||||
"""滚动到最左边,垂直位置不变"""
|
||||
...
|
||||
|
||||
def down(self, pixel: int = 300) -> ChromiumFrame: ...
|
||||
def to_location(self, x: int, y: int) -> ChromiumFrame:
|
||||
"""滚动到指定位置
|
||||
:param x: 水平距离
|
||||
:param y: 垂直距离
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def left(self, pixel: int = 300) -> ChromiumFrame: ...
|
||||
def up(self, pixel: int = 300) -> ChromiumFrame:
|
||||
"""向上滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self, pixel: int = 300) -> ChromiumFrame: ...
|
||||
def down(self, pixel: int = 300) -> ChromiumFrame:
|
||||
"""向下滚动若干像素,水平位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def to_see(self, loc_or_ele, center=None) -> ChromiumFrame: ...
|
||||
def left(self, pixel: int = 300) -> ChromiumFrame:
|
||||
"""向左滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def right(self, pixel: int = 300) -> ChromiumFrame:
|
||||
"""向右滚动若干像素,垂直位置不变
|
||||
:param pixel: 滚动的像素
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
@ -12,57 +12,38 @@ class SelectElement(object):
|
||||
"""用于处理 select 标签"""
|
||||
|
||||
def __init__(self, ele):
|
||||
"""
|
||||
:param ele: select 元素对象
|
||||
"""
|
||||
if ele.tag != 'select':
|
||||
raise TypeError("select方法只能在<select>元素使用。")
|
||||
|
||||
self._ele = ele
|
||||
|
||||
def __call__(self, text_or_index, timeout=None):
|
||||
"""选定下拉列表中子元素
|
||||
:param text_or_index: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
||||
:param timeout: 超时时间(秒),不输入默认实用页面超时时间
|
||||
:return: None
|
||||
"""
|
||||
para_type = 'index' if isinstance(text_or_index, int) else 'text'
|
||||
timeout = timeout if timeout is not None else self._ele.owner.timeout
|
||||
return self._select(text_or_index, para_type, timeout=timeout)
|
||||
|
||||
@property
|
||||
def is_multi(self):
|
||||
"""返回是否多选表单"""
|
||||
return self._ele.attr('multiple') is not None
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
"""返回所有选项元素组成的列表"""
|
||||
return [i for i in self._ele.eles('xpath://option') if not isinstance(i, int)]
|
||||
|
||||
@property
|
||||
def selected_option(self):
|
||||
"""返回第一个被选中的option元素
|
||||
:return: ChromiumElement对象或None
|
||||
"""
|
||||
ele = self._ele._run_js('return this.options[this.selectedIndex];')
|
||||
return ele
|
||||
|
||||
@property
|
||||
def selected_options(self):
|
||||
"""返回所有被选中的option元素列表
|
||||
:return: ChromiumElement对象组成的列表
|
||||
"""
|
||||
return [x for x in self.options if x.states.is_selected]
|
||||
|
||||
def all(self):
|
||||
"""全选"""
|
||||
if not self.is_multi:
|
||||
raise TypeError("只能在多选菜单执行此操作。")
|
||||
return self._by_loc('tag:option', 1, False)
|
||||
|
||||
def invert(self):
|
||||
"""反选"""
|
||||
if not self.is_multi:
|
||||
raise TypeError("只能对多项选框执行反选。")
|
||||
change = False
|
||||
@ -74,96 +55,41 @@ class SelectElement(object):
|
||||
self._dispatch_change()
|
||||
|
||||
def clear(self):
|
||||
"""清除所有已选项"""
|
||||
if not self.is_multi:
|
||||
raise TypeError("只能在多选菜单执行此操作。")
|
||||
return self._by_loc('tag:option', 1, True)
|
||||
|
||||
def by_text(self, text, timeout=None):
|
||||
"""此方法用于根据text值选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param text: text属性值,传入list或tuple可选择多项
|
||||
:param timeout: 超时时间(秒),为None默认使用页面超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
return self._select(text, 'text', False, timeout)
|
||||
|
||||
def by_value(self, value, timeout=None):
|
||||
"""此方法用于根据value值选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param value: value属性值,传入list或tuple可选择多项
|
||||
:param timeout: 超时时间,为None默认使用页面超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
return self._select(value, 'value', False, timeout)
|
||||
|
||||
def by_index(self, index, timeout=None):
|
||||
"""此方法用于根据index值选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可选择多项
|
||||
:param timeout: 超时时间,为None默认使用页面超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
return self._select(index, 'index', False, timeout)
|
||||
|
||||
def by_locator(self, locator, timeout=None):
|
||||
"""用定位符选择指定的项
|
||||
:param locator: 定位符
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
return self._by_loc(locator, timeout)
|
||||
|
||||
def by_option(self, option):
|
||||
"""选中单个或多个option元素
|
||||
:param option: option元素或它们组成的列表
|
||||
:return: None
|
||||
"""
|
||||
self._select_options(option, 'true')
|
||||
|
||||
def cancel_by_text(self, text, timeout=None):
|
||||
"""此方法用于根据text值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param text: 文本,传入list或tuple可取消多项
|
||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||
:return: 是否取消成功
|
||||
"""
|
||||
return self._select(text, 'text', True, timeout)
|
||||
|
||||
def cancel_by_value(self, value, timeout=None):
|
||||
"""此方法用于根据value值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param value: value属性值,传入list或tuple可取消多项
|
||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||
:return: 是否取消成功
|
||||
"""
|
||||
return self._select(value, 'value', True, timeout)
|
||||
|
||||
def cancel_by_index(self, index, timeout=None):
|
||||
"""此方法用于根据index值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可取消多项
|
||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||
:return: 是否取消成功
|
||||
"""
|
||||
return self._select(index, 'index', True, timeout)
|
||||
|
||||
def cancel_by_locator(self, locator, timeout=None):
|
||||
"""用定位符取消选择指定的项
|
||||
:param locator: 定位符
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
return self._by_loc(locator, timeout, True)
|
||||
|
||||
def cancel_by_option(self, option):
|
||||
"""取消选中单个或多个option元素
|
||||
:param option: option元素或它们组成的列表
|
||||
:return: None
|
||||
"""
|
||||
self._select_options(option, 'false')
|
||||
|
||||
def _by_loc(self, loc, timeout=None, cancel=False):
|
||||
"""用定位符取消选择指定的项
|
||||
:param loc: 定位符
|
||||
:param timeout: 超时时间
|
||||
:param cancel: 是否取消选择
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
eles = self._ele.eles(loc, timeout)
|
||||
if not eles:
|
||||
return False
|
||||
@ -176,12 +102,6 @@ class SelectElement(object):
|
||||
return True
|
||||
|
||||
def _select(self, condition, para_type='text', cancel=False, timeout=None):
|
||||
"""选定或取消选定下拉列表中子元素
|
||||
:param condition: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
||||
:param para_type: 参数类型,可选 'text'、'value'、'index'
|
||||
:param cancel: 是否取消选择
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
if not self.is_multi and isinstance(condition, (list, tuple)):
|
||||
raise TypeError('单选列表只能传入str格式。')
|
||||
|
||||
@ -195,13 +115,6 @@ class SelectElement(object):
|
||||
return self._index(condition, mode, timeout)
|
||||
|
||||
def _text_value(self, condition, para_type, mode, timeout):
|
||||
"""执行text和value搜索
|
||||
:param condition: 条件set
|
||||
:param para_type: 参数类型,可选 'text'、'value'
|
||||
:param mode: 'true' 或 'false'
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
ok = False
|
||||
text_len = len(condition)
|
||||
eles = []
|
||||
@ -224,12 +137,6 @@ class SelectElement(object):
|
||||
return False
|
||||
|
||||
def _index(self, condition, mode, timeout):
|
||||
"""执行index搜索
|
||||
:param condition: 条件set
|
||||
:param mode: 'true' 或 'false'
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
ok = False
|
||||
condition = [int(i) for i in condition]
|
||||
text_len = abs(max(condition, key=abs))
|
||||
@ -249,11 +156,6 @@ class SelectElement(object):
|
||||
return False
|
||||
|
||||
def _select_options(self, option, mode):
|
||||
"""选中或取消某个选项
|
||||
:param option: options元素对象
|
||||
:param mode: 选中还是取消
|
||||
:return: None
|
||||
"""
|
||||
if isinstance(option, (list, tuple, set)):
|
||||
if not self.is_multi and len(option) > 1:
|
||||
option = option[:1]
|
||||
@ -265,5 +167,4 @@ class SelectElement(object):
|
||||
self._dispatch_change()
|
||||
|
||||
def _dispatch_change(self):
|
||||
"""触发修改动作"""
|
||||
self._ele._run_js('this.dispatchEvent(new CustomEvent("change", {bubbles: true}));')
|
||||
|
@ -5,69 +5,213 @@
|
||||
@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved.
|
||||
@License : BSD 3-Clause.
|
||||
"""
|
||||
from typing import Union, Tuple, List
|
||||
from typing import Union, Tuple, List, Optional
|
||||
|
||||
from .._elements.chromium_element import ChromiumElement
|
||||
|
||||
|
||||
class SelectElement(object):
|
||||
_ele: ChromiumElement = ...
|
||||
def __init__(self, ele: ChromiumElement):
|
||||
self._ele: ChromiumElement = ...
|
||||
"""
|
||||
:param ele: <select>元素对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, text_or_index: Union[str, int, list, tuple], timeout: float = None) -> bool: ...
|
||||
def __call__(self,
|
||||
text_or_index: Union[str, int, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""选定下拉列表中子元素
|
||||
:param text_or_index: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
||||
:param timeout: 超时时间(秒),不输入默认实用页面超时时间
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def is_multi(self) -> bool: ...
|
||||
def is_multi(self) -> bool:
|
||||
"""返回是否多选表单"""
|
||||
...
|
||||
|
||||
@property
|
||||
def options(self) -> List[ChromiumElement]: ...
|
||||
def options(self) -> List[ChromiumElement]:
|
||||
"""返回所有选项元素组成的列表"""
|
||||
...
|
||||
|
||||
@property
|
||||
def selected_option(self) -> Union[ChromiumElement, None]: ...
|
||||
def selected_option(self) -> Optional[ChromiumElement]:
|
||||
"""返回第一个被选中的<option>元素"""
|
||||
...
|
||||
|
||||
@property
|
||||
def selected_options(self) -> List[ChromiumElement]: ...
|
||||
def selected_options(self) -> List[ChromiumElement]:
|
||||
"""返回所有被选中的<option>元素列表"""
|
||||
...
|
||||
|
||||
def clear(self) -> None: ...
|
||||
def all(self) -> None:
|
||||
"""全选"""
|
||||
...
|
||||
|
||||
def all(self) -> None: ...
|
||||
def invert(self) -> None:
|
||||
"""反选"""
|
||||
...
|
||||
|
||||
def by_text(self, text: Union[str, list, tuple], timeout: float = None) -> bool: ...
|
||||
def clear(self) -> None:
|
||||
"""清除所有已选项"""
|
||||
...
|
||||
|
||||
def by_value(self, value: Union[str, list, tuple], timeout: float = None) -> bool: ...
|
||||
def by_text(self,
|
||||
text: Union[str, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""此方法用于根据text值选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param text: text属性值,传入list或tuple可选择多项
|
||||
:param timeout: 超时时间(秒),为None默认使用页面超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def by_index(self, index: Union[int, list, tuple], timeout: float = None) -> bool: ...
|
||||
def by_value(self,
|
||||
value: Union[str, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""此方法用于根据value值选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param value: value属性值,传入list或tuple可选择多项
|
||||
:param timeout: 超时时间,为None默认使用页面超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def by_locator(self, locator: Union[Tuple[str, str], str], timeout: float = None) -> bool: ...
|
||||
def by_index(self,
|
||||
index: Union[int, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""此方法用于根据index值选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可选择多项
|
||||
:param timeout: 超时时间,为None默认使用页面超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None: ...
|
||||
def by_locator(self,
|
||||
locator: Union[Tuple[str, str], str],
|
||||
timeout: float = None) -> bool:
|
||||
"""用定位符选择指定的项
|
||||
:param locator: 定位符
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel_by_text(self, text: Union[str, list, tuple], timeout: float = None) -> bool: ...
|
||||
def by_option(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None:
|
||||
"""选中单个或多个<option>元素
|
||||
:param option: <option>元素或它们组成的列表
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel_by_value(self, value: Union[str, list, tuple], timeout: float = None) -> bool: ...
|
||||
def cancel_by_text(self,
|
||||
text: Union[str, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""此方法用于根据text值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param text: 文本,传入list或tuple可取消多项
|
||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||
:return: 是否取消成功
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel_by_index(self, index: Union[int, list, tuple], timeout: float = None) -> bool: ...
|
||||
def cancel_by_value(self,
|
||||
value: Union[str, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""此方法用于根据value值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param value: value属性值,传入list或tuple可取消多项
|
||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||
:return: 是否取消成功
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel_by_locator(self, locator: Union[Tuple[str, str], str], timeout: float = None) -> bool: ...
|
||||
def cancel_by_index(self,
|
||||
index: Union[int, list, tuple],
|
||||
timeout: float = None) -> bool:
|
||||
"""此方法用于根据index值取消选择项。当元素是多选列表时,可以接收list或tuple
|
||||
:param index: 序号,从1开始,可传入负数获取倒数第几个,传入list或tuple可取消多项
|
||||
:param timeout: 超时时间,不输入默认实用页面超时时间
|
||||
:return: 是否取消成功
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel_by_locator(self,
|
||||
locator: Union[Tuple[str, str], str],
|
||||
timeout: float = None) -> bool:
|
||||
"""用定位符取消选择指定的项
|
||||
:param locator: 定位符
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def cancel_by_option(self,
|
||||
option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None: ...
|
||||
option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]]) -> None:
|
||||
"""取消选中单个或多个<option>元素
|
||||
:param option: <option>元素或它们组成的列表
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def invert(self) -> None: ...
|
||||
|
||||
def _by_loc(self, loc: Union[str, Tuple[str, str]], timeout: float = None, cancel: bool = False) -> bool: ...
|
||||
def _by_loc(self,
|
||||
loc: Union[str, Tuple[str, str]],
|
||||
timeout: float = None,
|
||||
cancel: bool = False) -> bool:
|
||||
"""用定位符取消选择指定的项
|
||||
:param loc: 定位符
|
||||
:param timeout: 超时时间
|
||||
:param cancel: 是否取消选择
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _select(self,
|
||||
condition: Union[str, int, list, tuple] = None,
|
||||
para_type: str = 'text',
|
||||
cancel: bool = False,
|
||||
timeout: float = None) -> bool: ...
|
||||
timeout: float = None) -> bool:
|
||||
"""选定或取消选定下拉列表中子元素
|
||||
:param condition: 根据文本、值选或序号择选项,若允许多选,传入list或tuple可多选
|
||||
:param para_type: 参数类型,可选 'text'、'value'、'index'
|
||||
:param cancel: 是否取消选择
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _text_value(self, condition: Union[list, set], para_type: str, mode: str, timeout: float) -> bool: ...
|
||||
def _text_value(self,
|
||||
condition: Union[list, set],
|
||||
para_type: str,
|
||||
mode: str,
|
||||
timeout: float) -> bool:
|
||||
"""执行text和value搜索
|
||||
:param condition: 条件set
|
||||
:param para_type: 参数类型,可选 'text'、'value'
|
||||
:param mode: 'true' 或 'false'
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _index(self, condition: set, mode: str, timeout: float) -> bool: ...
|
||||
def _index(self, condition: set, mode: str, timeout: float) -> bool:
|
||||
"""执行index搜索
|
||||
:param condition: 条件set
|
||||
:param mode: 'true' 或 'false'
|
||||
:param timeout: 超时时间
|
||||
:return: 是否选择成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _select_options(self, option: Union[ChromiumElement, List[ChromiumElement], Tuple[ChromiumElement]],
|
||||
mode: str) -> None: ...
|
||||
mode: str) -> None:
|
||||
"""选中或取消某个选项
|
||||
:param option: options元素对象
|
||||
:param mode: 选中还是取消
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _dispatch_change(self) -> None: ...
|
||||
def _dispatch_change(self) -> None:
|
||||
"""触发修改动作"""
|
||||
...
|
||||
|
@ -19,33 +19,19 @@ from ..errors import ElementLostError, JavaScriptError
|
||||
|
||||
class BaseSetter(object):
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: BasePage对象
|
||||
"""
|
||||
self._owner = owner
|
||||
|
||||
def NoneElement_value(self, value=None, on_off=True):
|
||||
"""设置空元素是否返回设定值
|
||||
:param value: 返回的设定值
|
||||
:param on_off: 是否启用
|
||||
:return: None
|
||||
"""
|
||||
self._owner._none_ele_return_value = on_off
|
||||
self._owner._none_ele_value = value
|
||||
|
||||
def retry_times(self, times):
|
||||
"""设置连接失败重连次数"""
|
||||
self._owner.retry_times = times
|
||||
|
||||
def retry_interval(self, interval):
|
||||
"""设置连接失败重连间隔"""
|
||||
self._owner.retry_interval = interval
|
||||
|
||||
def download_path(self, path):
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
if path is None:
|
||||
path = '.'
|
||||
self._owner._download_path = str(Path(path).absolute())
|
||||
@ -61,130 +47,61 @@ class SessionPageSetter(BaseSetter):
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
"""返回用于设置cookies的对象"""
|
||||
if self._cookies_setter is None:
|
||||
self._cookies_setter = SessionCookiesSetter(self._owner)
|
||||
return self._cookies_setter
|
||||
|
||||
def download_path(self, path):
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
super().download_path(path)
|
||||
if self._owner._DownloadKit:
|
||||
self._owner._DownloadKit.set.goal_path(self._owner._download_path)
|
||||
|
||||
def timeout(self, second):
|
||||
"""设置连接超时时间
|
||||
:param second: 秒数
|
||||
:return: None
|
||||
"""
|
||||
self._owner._timeout = second
|
||||
|
||||
def encoding(self, encoding, set_all=True):
|
||||
"""设置编码
|
||||
:param encoding: 编码名称,如果要取消之前的设置,传入None
|
||||
:param set_all: 是否设置对象参数,为False则只设置当前Response
|
||||
:return: None
|
||||
"""
|
||||
if set_all:
|
||||
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._owner._headers = CaseInsensitiveDict(format_headers(headers))
|
||||
|
||||
def header(self, name, value):
|
||||
"""设置headers中一个项
|
||||
:param name: 设置名称
|
||||
:param value: 设置值
|
||||
:return: None
|
||||
"""
|
||||
self._owner._headers[name] = value
|
||||
|
||||
def user_agent(self, ua):
|
||||
"""设置user agent
|
||||
:param ua: user agent
|
||||
:return: None
|
||||
"""
|
||||
self._owner._headers['user-agent'] = ua
|
||||
|
||||
def proxies(self, http=None, https=None):
|
||||
"""设置proxies参数
|
||||
:param http: http代理地址
|
||||
:param https: https代理地址
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.proxies = {'http': http, 'https': https}
|
||||
|
||||
def auth(self, auth):
|
||||
"""设置认证元组或对象
|
||||
:param auth: 认证元组或对象
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.auth = auth
|
||||
|
||||
def hooks(self, hooks):
|
||||
"""设置回调方法
|
||||
:param hooks: 回调方法
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.hooks = hooks
|
||||
|
||||
def params(self, params):
|
||||
"""设置查询参数字典
|
||||
:param params: 查询参数字典
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.params = params
|
||||
|
||||
def verify(self, on_off):
|
||||
"""设置是否验证SSL证书
|
||||
:param on_off: 是否验证 SSL 证书
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.verify = on_off
|
||||
|
||||
def cert(self, cert):
|
||||
"""SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组
|
||||
:param cert: 证书路径或元组
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.cert = cert
|
||||
|
||||
def stream(self, on_off):
|
||||
"""设置是否使用流式响应内容
|
||||
:param on_off: 是否使用流式响应内容
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.stream = on_off
|
||||
|
||||
def trust_env(self, on_off):
|
||||
"""设置是否信任环境
|
||||
:param on_off: 是否信任环境
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.trust_env = on_off
|
||||
|
||||
def max_redirects(self, times):
|
||||
"""设置最大重定向次数
|
||||
:param times: 最大重定向次数
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.max_redirects = times
|
||||
|
||||
def add_adapter(self, url, adapter):
|
||||
"""添加适配器
|
||||
:param url: 适配器对应url
|
||||
:param adapter: 适配器对象
|
||||
:return: None
|
||||
"""
|
||||
self._owner.session.mount(url, adapter)
|
||||
|
||||
|
||||
@ -200,16 +117,9 @@ class BrowserBaseSetter(BaseSetter):
|
||||
|
||||
@property
|
||||
def load_mode(self):
|
||||
"""返回用于设置页面加载策略的对象"""
|
||||
return LoadMode(self._owner)
|
||||
|
||||
def timeouts(self, base=None, page_load=None, script=None):
|
||||
"""设置超时时间,单位为秒
|
||||
:param base: 基本等待时间,除页面加载和脚本超时,其它等待默认使用
|
||||
:param page_load: 页面加载超时时间
|
||||
:param script: 脚本运行超时时间
|
||||
:return: None
|
||||
"""
|
||||
if base is not None:
|
||||
self._owner.timeouts.base = base
|
||||
|
||||
@ -224,40 +134,21 @@ class BrowserSetter(BrowserBaseSetter):
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
"""返回用于设置cookies的对象"""
|
||||
if self._cookies_setter is None:
|
||||
self._cookies_setter = BrowserCookiesSetter(self._owner)
|
||||
return self._cookies_setter
|
||||
|
||||
def auto_handle_alert(self, on_off=True, accept=True):
|
||||
"""设置是否启用自动处理弹窗
|
||||
:param on_off: bool表示开或关
|
||||
:param accept: bool表示确定还是取消
|
||||
:return: None
|
||||
"""
|
||||
Settings.auto_handle_alert = accept if on_off else None
|
||||
|
||||
def download_path(self, path):
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
super().download_path(path)
|
||||
self._owner._dl_mgr.set_path('browser', self._owner._download_path)
|
||||
|
||||
def download_file_name(self, name=None, suffix=None):
|
||||
"""设置下一个被下载文件的名称
|
||||
:param name: 文件名,可不含后缀,会自动使用远程文件后缀
|
||||
:param suffix: 后缀名,显式设置后缀名,不使用远程文件后缀
|
||||
:return: None
|
||||
"""
|
||||
self._owner._dl_mgr.set_rename('browser', name, suffix)
|
||||
|
||||
def when_download_file_exists(self, mode):
|
||||
"""设置当存在同名文件时的处理方式
|
||||
:param mode: 可在 'rename', 'overwrite', 'skip', 'r', 'o', 's'中选择
|
||||
:return: None
|
||||
"""
|
||||
types = {'rename': 'rename', 'overwrite': 'overwrite', 'skip': 'skip', 'r': 'rename', 'o': 'overwrite',
|
||||
's': 'skip'}
|
||||
mode = types.get(mode, mode)
|
||||
@ -265,48 +156,30 @@ class BrowserSetter(BrowserBaseSetter):
|
||||
raise ValueError(f'''mode参数只能是 '{"', '".join(types.keys())}' 之一,现在是:{mode}''')
|
||||
self._owner._dl_mgr.set_file_exists('browser', mode)
|
||||
|
||||
# ---------- 即将废弃 ----------
|
||||
def tab_to_front(self, tab_or_id):
|
||||
"""激活标签页使其处于最前面
|
||||
:param tab_or_id: 标签页对象或id
|
||||
:return: None
|
||||
"""
|
||||
if not isinstance(tab_or_id, str): # 传入Tab对象
|
||||
tab_or_id = tab_or_id.tab_id
|
||||
self._owner.activate_tab(tab_or_id)
|
||||
|
||||
|
||||
class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
|
||||
@property
|
||||
def scroll(self):
|
||||
"""返回用于设置页面滚动设置的对象"""
|
||||
return PageScrollSetter(self._owner.scroll)
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
"""返回用于设置cookies的对象"""
|
||||
if self._cookies_setter is None:
|
||||
self._cookies_setter = CookiesSetter(self._owner)
|
||||
return self._cookies_setter
|
||||
|
||||
def headers(self, headers):
|
||||
self._owner._run_cdp('Network.enable')
|
||||
self._owner._run_cdp('Network.setExtraHTTPHeaders', headers=format_headers(headers))
|
||||
|
||||
def user_agent(self, ua, platform=None):
|
||||
"""为当前tab设置user agent,只在当前tab有效
|
||||
:param ua: user agent字符串
|
||||
:param platform: platform字符串
|
||||
:return: None
|
||||
"""
|
||||
keys = {'userAgent': ua}
|
||||
if platform:
|
||||
keys['platform'] = platform
|
||||
self._owner._run_cdp('Emulation.setUserAgentOverride', **keys)
|
||||
|
||||
def session_storage(self, item, value):
|
||||
"""设置或删除某项sessionStorage信息
|
||||
:param item: 要设置的项
|
||||
:param value: 项的值,设置为False时,删除该项
|
||||
:return: None
|
||||
"""
|
||||
self._owner._run_cdp_loaded('DOMStorage.enable')
|
||||
i = self._owner._run_cdp('Storage.getStorageKeyForFrame', frameId=self._owner._frame_id)['storageKey']
|
||||
if value is False:
|
||||
@ -318,11 +191,6 @@ class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
self._owner._run_cdp_loaded('DOMStorage.disable')
|
||||
|
||||
def local_storage(self, item, value):
|
||||
"""设置或删除某项localStorage信息
|
||||
:param item: 要设置的项
|
||||
:param value: 项的值,设置为False时,删除该项
|
||||
:return: None
|
||||
"""
|
||||
self._owner._run_cdp_loaded('DOMStorage.enable')
|
||||
i = self._owner._run_cdp('Storage.getStorageKeyForFrame', frameId=self._owner._frame_id)['storageKey']
|
||||
if value is False:
|
||||
@ -334,10 +202,6 @@ class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
self._owner._run_cdp_loaded('DOMStorage.disable')
|
||||
|
||||
def upload_files(self, files):
|
||||
"""等待上传的文件路径
|
||||
:param files: 文件路径列表或字符串,字符串时多个文件用回车分隔
|
||||
:return: None
|
||||
"""
|
||||
if not self._owner._upload_list:
|
||||
self._owner.driver.set_callback('Page.fileChooserOpened', self._owner._onFileChooserOpened)
|
||||
self._owner._run_cdp('Page.setInterceptFileChooserDialog', enabled=True)
|
||||
@ -348,27 +212,10 @@ class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
files = (files,)
|
||||
self._owner._upload_list = [str(Path(i).absolute()) for i in files]
|
||||
|
||||
def headers(self, headers):
|
||||
"""设置固定发送的headers
|
||||
:param headers: dict格式的headers数据,或从浏览器复制的headers文本(\n分行)
|
||||
:return: None
|
||||
"""
|
||||
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):
|
||||
"""设置是否启用自动处理弹窗
|
||||
:param on_off: bool表示开或关
|
||||
:param accept: bool表示确定还是取消
|
||||
:return: None
|
||||
"""
|
||||
self._owner._alert.auto = accept if on_off else None
|
||||
|
||||
def blocked_urls(self, urls):
|
||||
"""设置要忽略的url
|
||||
:param urls: 要忽略的url,可用*通配符,可输入多个,传入None时清空已设置的内容
|
||||
:return: None
|
||||
"""
|
||||
if not urls:
|
||||
urls = []
|
||||
elif isinstance(urls, str):
|
||||
@ -381,39 +228,22 @@ class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
|
||||
class TabSetter(ChromiumBaseSetter):
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: 标签页对象
|
||||
"""
|
||||
super().__init__(owner)
|
||||
|
||||
@property
|
||||
def window(self):
|
||||
"""返回用于设置浏览器窗口的对象"""
|
||||
return WindowSetter(self._owner)
|
||||
|
||||
def download_path(self, path):
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
super().download_path(path)
|
||||
self._owner.browser._dl_mgr.set_path(self._owner, self._owner._download_path)
|
||||
if self._owner._DownloadKit:
|
||||
self._owner._DownloadKit.set.goal_path(self._owner._download_path)
|
||||
|
||||
def download_file_name(self, name=None, suffix=None):
|
||||
"""设置下一个被下载文件的名称
|
||||
:param name: 文件名,可不含后缀,会自动使用远程文件后缀
|
||||
:param suffix: 后缀名,显式设置后缀名,不使用远程文件后缀
|
||||
:return: None
|
||||
"""
|
||||
self._owner.browser._dl_mgr.set_rename(self._owner.tab_id, name, suffix)
|
||||
|
||||
def when_download_file_exists(self, mode):
|
||||
"""设置当存在同名文件时的处理方式
|
||||
:param mode: 可在 'rename', 'overwrite', 'skip', 'r', 'o', 's'中选择
|
||||
:return: None
|
||||
"""
|
||||
types = {'rename': 'rename', 'overwrite': 'overwrite', 'skip': 'skip', 'r': 'rename', 'o': 'overwrite',
|
||||
's': 'skip'}
|
||||
mode = types.get(mode, mode)
|
||||
@ -422,7 +252,6 @@ class TabSetter(ChromiumBaseSetter):
|
||||
self._owner.browser._dl_mgr.set_file_exists(self._owner.tab_id, mode)
|
||||
|
||||
def activate(self):
|
||||
"""使标签页处于最前面"""
|
||||
self._owner.browser.activate_tab(self._owner.tab_id)
|
||||
|
||||
|
||||
@ -457,29 +286,11 @@ class ChromiumPageSetter(TabSetter):
|
||||
self._owner.browser._download_path = self._owner._download_path
|
||||
|
||||
def auto_handle_alert(self, on_off=True, accept=True, all_tabs=False):
|
||||
"""设置是否启用自动处理弹窗
|
||||
:param on_off: bool表示开或关
|
||||
:param accept: bool表示确定还是取消
|
||||
:param all_tabs: 是否为全局设置
|
||||
:return: None
|
||||
"""
|
||||
if all_tabs:
|
||||
Settings.auto_handle_alert = on_off
|
||||
else:
|
||||
self._owner._alert.auto = accept if on_off else None
|
||||
|
||||
# ---------- 即将废弃 ----------
|
||||
def tab_to_front(self, tab_or_id=None):
|
||||
"""激活标签页使其处于最前面
|
||||
:param tab_or_id: 标签页对象或id,为None表示当前标签页
|
||||
:return: None
|
||||
"""
|
||||
if not tab_or_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._owner.browser.activate_tab(tab_or_id)
|
||||
|
||||
|
||||
class MixPageSetter(ChromiumPageSetter):
|
||||
def __init__(self, owner):
|
||||
@ -495,17 +306,12 @@ class MixPageSetter(ChromiumPageSetter):
|
||||
return self._cookies_setter
|
||||
|
||||
def headers(self, headers):
|
||||
"""设置固定发送的headers
|
||||
:param headers: dict格式的headers数据
|
||||
:return: None
|
||||
"""
|
||||
if self._owner.mode == 's':
|
||||
self._session_setter.headers(headers)
|
||||
else:
|
||||
self._chromium_setter.headers(headers)
|
||||
|
||||
def user_agent(self, ua, platform=None):
|
||||
"""设置user agent,d模式下只有当前tab有效"""
|
||||
if self._owner.mode == 's':
|
||||
self._session_setter.user_agent(ua)
|
||||
else:
|
||||
@ -520,35 +326,23 @@ class MixTabSetter(TabSetter):
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
"""返回用于设置cookies的对象"""
|
||||
if self._cookies_setter is None:
|
||||
self._cookies_setter = MixPageCookiesSetter(self._owner)
|
||||
return self._cookies_setter
|
||||
|
||||
def headers(self, headers):
|
||||
"""设置固定发送的headers
|
||||
:param headers: dict格式的headers数据
|
||||
:return: None
|
||||
"""
|
||||
if self._owner._has_session:
|
||||
self._session_setter.headers(headers)
|
||||
if self._owner._has_driver:
|
||||
self._chromium_setter.headers(headers)
|
||||
|
||||
def user_agent(self, ua, platform=None):
|
||||
"""设置user agent,d模式下只有当前tab有效"""
|
||||
if self._owner._has_session:
|
||||
self._session_setter.user_agent(ua)
|
||||
if self._owner._has_driver:
|
||||
self._chromium_setter.user_agent(ua, platform)
|
||||
|
||||
def timeouts(self, base=None, page_load=None, script=None):
|
||||
"""设置超时时间,单位为秒
|
||||
:param base: 基本等待时间,除页面加载和脚本超时,其它等待默认使用
|
||||
:param page_load: 页面加载超时时间
|
||||
:param script: 脚本运行超时时间
|
||||
:return: None
|
||||
"""
|
||||
super().timeouts(base=base, page_load=page_load, script=script)
|
||||
if base is not None:
|
||||
self._owner._timeout = base
|
||||
@ -556,17 +350,9 @@ class MixTabSetter(TabSetter):
|
||||
|
||||
class ChromiumElementSetter(object):
|
||||
def __init__(self, ele):
|
||||
"""
|
||||
:param ele: ChromiumElement
|
||||
"""
|
||||
self._ele = ele
|
||||
|
||||
def attr(self, name, value=''):
|
||||
"""设置元素attribute属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
try:
|
||||
self._ele.owner._run_cdp('DOM.setAttributeValue',
|
||||
nodeId=self._ele._node_id, name=name, value=str(value))
|
||||
@ -576,63 +362,30 @@ class ChromiumElementSetter(object):
|
||||
nodeId=self._ele._node_id, name=name, value=str(value))
|
||||
|
||||
def property(self, name, value):
|
||||
"""设置元素property属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
value = value.replace('"', r'\"')
|
||||
self._ele._run_js(f'this.{name}="{value}";')
|
||||
|
||||
def style(self, name, value):
|
||||
"""设置元素style样式
|
||||
:param name: 样式名称
|
||||
:param value: 样式值
|
||||
:return: None
|
||||
"""
|
||||
try:
|
||||
self._ele._run_js(f'this.style.{name}="{value}";')
|
||||
except JavaScriptError:
|
||||
raise ValueError(f'设置失败,请检查属性名{name}')
|
||||
|
||||
def innerHTML(self, html):
|
||||
"""设置元素innerHTML
|
||||
:param html: html文本
|
||||
:return: None
|
||||
"""
|
||||
self.property('innerHTML', html)
|
||||
|
||||
def value(self, value):
|
||||
"""设置元素value值
|
||||
:param value: value值
|
||||
:return: None
|
||||
"""
|
||||
self.property('value', value)
|
||||
|
||||
|
||||
class ChromiumFrameSetter(ChromiumBaseSetter):
|
||||
def attr(self, name, value):
|
||||
"""设置frame元素attribute属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
self._owner.frame_ele.set.attr(name, value)
|
||||
|
||||
def property(self, name, value):
|
||||
"""设置元素property属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
self._owner.frame_ele.set.property(name=name, value=value)
|
||||
|
||||
def style(self, name, value):
|
||||
"""设置元素style样式
|
||||
:param name: 样式名称
|
||||
:param value: 样式值
|
||||
:return: None
|
||||
"""
|
||||
self._owner.frame_ele.set.style(name=name, value=value)
|
||||
|
||||
|
||||
@ -640,16 +393,9 @@ class LoadMode(object):
|
||||
"""用于设置页面加载策略的类"""
|
||||
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: ChromiumBase对象
|
||||
"""
|
||||
self._owner = owner
|
||||
|
||||
def __call__(self, value):
|
||||
"""设置加载策略
|
||||
:param value: 可选 'normal', 'eager', 'none'
|
||||
:return: None
|
||||
"""
|
||||
if value.lower() not in ('normal', 'eager', 'none'):
|
||||
raise ValueError("只能选择 'normal', 'eager', 'none'。")
|
||||
self._owner._load_mode = value
|
||||
@ -657,43 +403,29 @@ class LoadMode(object):
|
||||
self._owner.browser._load_mode = value
|
||||
|
||||
def normal(self):
|
||||
"""设置页面加载策略为normal"""
|
||||
self.__call__('normal')
|
||||
|
||||
def eager(self):
|
||||
"""设置页面加载策略为eager"""
|
||||
self.__call__('eager')
|
||||
|
||||
def none(self):
|
||||
"""设置页面加载策略为none"""
|
||||
self.__call__('none')
|
||||
|
||||
|
||||
class PageScrollSetter(object):
|
||||
def __init__(self, scroll):
|
||||
"""
|
||||
:param scroll: PageScroller对象
|
||||
"""
|
||||
self._scroll = scroll
|
||||
|
||||
def wait_complete(self, on_off=True):
|
||||
"""设置滚动命令后是否等待完成
|
||||
:param on_off: 开或关
|
||||
:return: None
|
||||
"""
|
||||
if not isinstance(on_off, bool):
|
||||
raise TypeError('on_off必须为bool。')
|
||||
self._scroll._wait_complete = on_off
|
||||
|
||||
def smooth(self, on_off=True):
|
||||
"""设置页面滚动是否平滑滚动
|
||||
:param on_off: 开或关
|
||||
:return: None
|
||||
"""
|
||||
if not isinstance(on_off, bool):
|
||||
raise TypeError('on_off必须为bool。')
|
||||
b = 'smooth' if on_off else 'auto'
|
||||
self._scroll._driver._run_js(f'document.documentElement.style.setProperty("scroll-behavior","{b}");')
|
||||
self._scroll._owner._run_js(f'document.documentElement.style.setProperty("scroll-behavior","{b}");')
|
||||
self._scroll._wait_complete = on_off
|
||||
|
||||
|
||||
@ -701,46 +433,34 @@ class WindowSetter(object):
|
||||
"""用于设置窗口大小的类"""
|
||||
|
||||
def __init__(self, owner):
|
||||
"""
|
||||
:param owner: 页面对象
|
||||
"""
|
||||
self._owner = owner
|
||||
self._window_id = self._get_info()['windowId']
|
||||
|
||||
def max(self):
|
||||
"""窗口最大化"""
|
||||
s = self._get_info()['bounds']['windowState']
|
||||
if s in ('fullscreen', 'minimized'):
|
||||
self._perform({'windowState': 'normal'})
|
||||
self._perform({'windowState': 'maximized'})
|
||||
|
||||
def mini(self):
|
||||
"""窗口最小化"""
|
||||
s = self._get_info()['bounds']['windowState']
|
||||
if s == 'fullscreen':
|
||||
self._perform({'windowState': 'normal'})
|
||||
self._perform({'windowState': 'minimized'})
|
||||
|
||||
def full(self):
|
||||
"""设置窗口为全屏"""
|
||||
s = self._get_info()['bounds']['windowState']
|
||||
if s == 'minimized':
|
||||
self._perform({'windowState': 'normal'})
|
||||
self._perform({'windowState': 'fullscreen'})
|
||||
|
||||
def normal(self):
|
||||
"""设置窗口为常规模式"""
|
||||
s = self._get_info()['bounds']['windowState']
|
||||
if s == 'fullscreen':
|
||||
self._perform({'windowState': 'normal'})
|
||||
self._perform({'windowState': 'normal'})
|
||||
|
||||
def size(self, width=None, height=None):
|
||||
"""设置窗口大小
|
||||
:param width: 窗口宽度
|
||||
:param height: 窗口高度
|
||||
:return: None
|
||||
"""
|
||||
if width or height:
|
||||
s = self._get_info()['bounds']['windowState']
|
||||
if s != 'normal':
|
||||
@ -751,11 +471,6 @@ class WindowSetter(object):
|
||||
self._perform({'width': width, 'height': height})
|
||||
|
||||
def location(self, x=None, y=None):
|
||||
"""设置窗口在屏幕中的位置,相对左上角坐标
|
||||
:param x: 距离顶部距离
|
||||
:param y: 距离左边距离
|
||||
:return: None
|
||||
"""
|
||||
if x is not None or y is not None:
|
||||
self.normal()
|
||||
info = self._get_info()['bounds']
|
||||
@ -763,8 +478,13 @@ class WindowSetter(object):
|
||||
y = y if y is not None else info['top']
|
||||
self._perform({'left': x - 8, 'top': y})
|
||||
|
||||
def hide(self):
|
||||
show_or_hide_browser(self._owner, hide=True)
|
||||
|
||||
def show(self):
|
||||
show_or_hide_browser(self._owner, hide=False)
|
||||
|
||||
def _get_info(self):
|
||||
"""获取窗口位置及大小信息"""
|
||||
for _ in range(50):
|
||||
try:
|
||||
return self._owner._run_cdp('Browser.getWindowForTarget')
|
||||
@ -773,33 +493,7 @@ class WindowSetter(object):
|
||||
raise RuntimeError('获取窗口信息失败。')
|
||||
|
||||
def _perform(self, bounds):
|
||||
"""执行改变窗口大小操作
|
||||
:param bounds: 控制数据
|
||||
:return: None
|
||||
"""
|
||||
try:
|
||||
self._owner._run_cdp('Browser.setWindowBounds', windowId=self._window_id, bounds=bounds)
|
||||
except:
|
||||
raise RuntimeError('浏览器全屏或最小化状态时请先调用set.window.normal()恢复正常状态。')
|
||||
|
||||
# ------------即将废除----------
|
||||
|
||||
def maximized(self):
|
||||
"""窗口最大化"""
|
||||
self.max()
|
||||
|
||||
def minimized(self):
|
||||
"""窗口最小化"""
|
||||
self.mini()
|
||||
|
||||
def fullscreen(self):
|
||||
"""设置窗口为全屏"""
|
||||
self.full()
|
||||
|
||||
def hide(self):
|
||||
"""隐藏浏览器窗口,只在Windows系统可用"""
|
||||
show_or_hide_browser(self._owner, hide=True)
|
||||
|
||||
def show(self):
|
||||
"""显示浏览器窗口,只在Windows系统可用"""
|
||||
show_or_hide_browser(self._owner, hide=False)
|
||||
|
@ -27,16 +27,44 @@ FILE_EXISTS = Literal['skip', 'rename', 'overwrite', 's', 'r', 'o']
|
||||
|
||||
|
||||
class BaseSetter(object):
|
||||
_owner: Union[Chromium, BasePage] = ...
|
||||
|
||||
def __init__(self, owner: Union[Chromium, BasePage]):
|
||||
self._owner: Union[Chromium, BasePage] = ...
|
||||
"""
|
||||
:param 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:
|
||||
"""设置空元素是否返回设定值
|
||||
:param value: 返回的设定值
|
||||
:param on_off: 是否启用
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def retry_times(self, times: int) -> None: ...
|
||||
def retry_times(self, times: int) -> None:
|
||||
"""设置连接失败重连次数
|
||||
:param times: 重试次数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def retry_interval(self, interval: float) -> None: ...
|
||||
def retry_interval(self, interval: float) -> None:
|
||||
"""设置连接失败重连间隔
|
||||
:param interval: 重试间隔
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def download_path(self, path: Union[str, Path, None]) -> None: ...
|
||||
def download_path(self, path: Union[str, Path, None]) -> None:
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class SessionPageSetter(BaseSetter):
|
||||
@ -46,52 +74,146 @@ class SessionPageSetter(BaseSetter):
|
||||
def __init__(self, owner: SessionPage): ...
|
||||
|
||||
@property
|
||||
def cookies(self) -> SessionCookiesSetter: ...
|
||||
def cookies(self) -> SessionCookiesSetter:
|
||||
"""返回用于设置cookies的对象"""
|
||||
...
|
||||
|
||||
def retry_times(self, times: int) -> None: ...
|
||||
def download_path(self, path: Union[str, Path, None]) -> None:
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def retry_interval(self, interval: float) -> None: ...
|
||||
def timeout(self, second: float) -> None:
|
||||
"""设置连接超时时间
|
||||
:param second: 秒数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def download_path(self, path: Union[str, Path, None]) -> None: ...
|
||||
def encoding(self, encoding: Union[str, None], set_all: bool = True) -> None:
|
||||
"""设置编码
|
||||
:param encoding: 编码名称,如果要取消之前的设置,传入None
|
||||
:param set_all: 是否设置对象参数,为False则只设置当前Response
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def timeout(self, second: float) -> None: ...
|
||||
def headers(self, headers: Union[str, dict]) -> None:
|
||||
"""设置通用的headers
|
||||
:param headers: dict形式的headers
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def encoding(self, encoding: Union[str, None], set_all: bool = True) -> None: ...
|
||||
def header(self, name: str, value: str) -> None:
|
||||
"""设置headers中一个项
|
||||
:param name: 设置名称
|
||||
:param value: 设置值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def headers(self, headers: Union[str, dict]) -> None: ...
|
||||
def user_agent(self, ua: str) -> None:
|
||||
"""设置user agent
|
||||
:param ua: user agent
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def header(self, name: str, value: str) -> None: ...
|
||||
def proxies(self, http: str = None, https: str = None) -> None:
|
||||
"""设置proxies参数
|
||||
:param http: http代理地址
|
||||
:param https: https代理地址
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def user_agent(self, ua: str) -> None: ...
|
||||
def auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) -> None:
|
||||
"""设置认证元组或对象
|
||||
:param auth: 认证元组或对象
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def proxies(self, http: str = None, https: str = None) -> None: ...
|
||||
def hooks(self, hooks: Union[dict, None]) -> None:
|
||||
"""设置回调方法
|
||||
:param hooks: 回调方法
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) -> None: ...
|
||||
def params(self, params: Union[dict, None]) -> None:
|
||||
"""设置查询参数字典
|
||||
:param params: 查询参数字典
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def hooks(self, hooks: Union[dict, None]) -> None: ...
|
||||
def verify(self, on_off: Union[bool, None]) -> None:
|
||||
"""设置是否验证SSL证书
|
||||
:param on_off: 是否验证 SSL 证书
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def params(self, params: Union[dict, None]) -> None: ...
|
||||
def cert(self, cert: Union[str, Tuple[str, str], None]) -> None:
|
||||
"""SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组
|
||||
:param cert: 证书路径或元组
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def verify(self, on_off: Union[bool, None]) -> None: ...
|
||||
def stream(self, on_off: Union[bool, None]) -> None:
|
||||
"""设置是否使用流式响应内容
|
||||
:param on_off: 是否使用流式响应内容
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def cert(self, cert: Union[str, Tuple[str, str], None]) -> None: ...
|
||||
def trust_env(self, on_off: Union[bool, None]) -> None:
|
||||
"""设置是否信任环境
|
||||
:param on_off: 是否信任环境
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def stream(self, on_off: Union[bool, None]) -> None: ...
|
||||
def max_redirects(self, times: Union[int, None]) -> None:
|
||||
"""设置最大重定向次数
|
||||
:param times: 最大重定向次数
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def trust_env(self, on_off: Union[bool, None]) -> None: ...
|
||||
|
||||
def max_redirects(self, times: Union[int, None]) -> None: ...
|
||||
|
||||
def add_adapter(self, url: str, adapter: HTTPAdapter) -> None: ...
|
||||
def add_adapter(self, url: str, adapter: HTTPAdapter) -> None:
|
||||
"""添加适配器
|
||||
:param url: 适配器对应url
|
||||
:param adapter: 适配器对象
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class BrowserBaseSetter(BaseSetter):
|
||||
_cookies_setter: Optional[CookiesSetter] = ...
|
||||
|
||||
@property
|
||||
def load_mode(self) -> LoadMode: ...
|
||||
def load_mode(self) -> LoadMode:
|
||||
"""返回用于设置页面加载策略的对象"""
|
||||
...
|
||||
|
||||
def timeouts(self, base=None, page_load=None, script=None) -> None: ...
|
||||
def timeouts(self,
|
||||
base=None,
|
||||
page_load=None,
|
||||
script=None) -> None:
|
||||
"""设置超时时间,单位为秒
|
||||
:param base: 基本等待时间,除页面加载和脚本超时,其它等待默认使用
|
||||
:param page_load: 页面加载超时时间
|
||||
:param script: 脚本运行超时时间
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class BrowserSetter(BrowserBaseSetter):
|
||||
@ -99,15 +221,43 @@ class BrowserSetter(BrowserBaseSetter):
|
||||
_cookies_setter: BrowserCookiesSetter = ...
|
||||
|
||||
@property
|
||||
def cookies(self) -> BrowserCookiesSetter: ...
|
||||
def cookies(self) -> BrowserCookiesSetter:
|
||||
"""返回用于设置cookies的对象"""
|
||||
...
|
||||
|
||||
def auto_handle_alert(self, on_off: bool = True, accept: bool = True): ...
|
||||
def auto_handle_alert(self,
|
||||
on_off: bool = True,
|
||||
accept: bool = True):
|
||||
"""设置是否启用自动处理弹窗
|
||||
:param on_off: bool表示开或关
|
||||
:param accept: bool表示确定还是取消
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def download_path(self, path: Union[Path, str, None]): ...
|
||||
def download_path(self, path: Union[Path, str, None]):
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def download_file_name(self, name: str = None, suffix: str = None): ...
|
||||
def download_file_name(self,
|
||||
name: str = None,
|
||||
suffix: str = None):
|
||||
"""设置下一个被下载文件的名称
|
||||
:param name: 文件名,可不含后缀,会自动使用远程文件后缀
|
||||
:param suffix: 后缀名,显式设置后缀名,不使用远程文件后缀
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def when_download_file_exists(self, mode: FILE_EXISTS): ...
|
||||
def when_download_file_exists(self, mode: FILE_EXISTS):
|
||||
"""设置当存在同名文件时的处理方式
|
||||
:param mode: 可在 'rename', 'overwrite', 'skip', 'r', 'o', 's'中选择
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
@ -117,47 +267,134 @@ class ChromiumBaseSetter(BrowserBaseSetter):
|
||||
def __init__(self, owner): ...
|
||||
|
||||
@property
|
||||
def scroll(self) -> PageScrollSetter: ...
|
||||
def scroll(self) -> PageScrollSetter:
|
||||
"""返回用于设置页面滚动设置的对象"""
|
||||
...
|
||||
|
||||
@property
|
||||
def cookies(self) -> CookiesSetter: ...
|
||||
def cookies(self) -> CookiesSetter:
|
||||
"""返回用于设置cookies的对象"""
|
||||
...
|
||||
|
||||
def user_agent(self, ua: str, platform: str = None) -> None: ...
|
||||
def headers(self, headers: Union[dict, str]) -> None:
|
||||
"""设置固定发送的headers
|
||||
:param headers: dict格式的headers数据,或从浏览器复制的headers文本(\n分行)
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def session_storage(self, item: str, value: Union[str, bool]) -> None: ...
|
||||
def user_agent(self, ua: str, platform: str = None) -> None:
|
||||
"""为当前tab设置user agent,只在当前tab有效
|
||||
:param ua: user agent字符串
|
||||
:param platform: platform字符串
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def local_storage(self, item: str, value: Union[str, bool]) -> None: ...
|
||||
def session_storage(self, item: str, value: Union[str, bool]) -> None:
|
||||
"""设置或删除某项sessionStorage信息
|
||||
:param item: 要设置的项
|
||||
:param value: 项的值,设置为False时,删除该项
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def headers(self, headers: Union[dict, str]) -> None: ...
|
||||
def local_storage(self, item: str, value: Union[str, bool]) -> None:
|
||||
"""设置或删除某项localStorage信息
|
||||
:param item: 要设置的项
|
||||
:param value: 项的值,设置为False时,删除该项
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def auto_handle_alert(self, on_off: bool = True, accept: bool = True) -> None: ...
|
||||
def upload_files(self, files: Union[str, Path, list, tuple]) -> None:
|
||||
"""等待上传的文件路径
|
||||
:param files: 文件路径列表或字符串,字符串时多个文件用回车分隔
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def upload_files(self, files: Union[str, Path, list, tuple]) -> None: ...
|
||||
def auto_handle_alert(self,
|
||||
on_off: bool = True,
|
||||
accept: bool = True) -> None:
|
||||
"""设置是否启用自动处理弹窗
|
||||
:param on_off: bool表示开或关
|
||||
:param accept: bool表示确定还是取消
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def blocked_urls(self, urls: Union[list, tuple, str, None]) -> None: ...
|
||||
def blocked_urls(self, urls: Union[list, tuple, str, None]) -> None:
|
||||
"""设置要忽略的url
|
||||
:param urls: 要忽略的url,可用*通配符,可输入多个,传入None时清空已设置的内容
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class TabSetter(ChromiumBaseSetter):
|
||||
_owner: ChromiumTab = ...
|
||||
|
||||
def __init__(self, owner: Union[ChromiumTab, MixTab, MixPage, ChromiumPage]): ...
|
||||
def __init__(self, owner: Union[ChromiumTab, MixTab, MixPage, ChromiumPage]):
|
||||
"""
|
||||
:param owner: 标签页对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def window(self) -> WindowSetter: ...
|
||||
def window(self) -> WindowSetter:
|
||||
"""返回用于设置浏览器窗口的对象"""
|
||||
...
|
||||
|
||||
def download_path(self, path: Union[str, Path, None]) -> None: ...
|
||||
def download_path(self, path: Union[str, Path, None]) -> None:
|
||||
"""设置下载路径
|
||||
:param path: 下载路径
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def download_file_name(self, name: str = None, suffix: str = None) -> None: ...
|
||||
def download_file_name(self,
|
||||
name: str = None,
|
||||
suffix: str = None) -> None:
|
||||
"""设置下一个被下载文件的名称
|
||||
:param name: 文件名,可不含后缀,会自动使用远程文件后缀
|
||||
:param suffix: 后缀名,显式设置后缀名,不使用远程文件后缀
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def when_download_file_exists(self, mode: FILE_EXISTS) -> None: ...
|
||||
def when_download_file_exists(self, mode: FILE_EXISTS) -> None:
|
||||
"""设置当存在同名文件时的处理方式
|
||||
:param mode: 可在 'rename', 'overwrite', 'skip', 'r', 'o', 's'中选择
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def activate(self) -> None: ...
|
||||
def activate(self) -> None:
|
||||
"""使标签页处于最前面"""
|
||||
...
|
||||
|
||||
|
||||
class ChromiumPageSetter(TabSetter):
|
||||
_owner: ChromiumPage = ...
|
||||
|
||||
def auto_handle_alert(self, on_off: bool = True, accept: bool = True, all_tabs: bool = False) -> None: ...
|
||||
def __init__(self, owner: ChromiumPage):
|
||||
"""
|
||||
:param owner: ChromiumPage对象
|
||||
"""
|
||||
...
|
||||
|
||||
def auto_handle_alert(self,
|
||||
on_off: bool = True,
|
||||
accept: bool = True,
|
||||
all_tabs: bool = False) -> None:
|
||||
"""设置是否启用自动处理弹窗
|
||||
:param on_off: bool表示开或关
|
||||
:param accept: bool表示确定还是取消
|
||||
:param all_tabs: 是否为全局设置
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class MixPageSetter(ChromiumPageSetter):
|
||||
@ -165,9 +402,11 @@ class MixPageSetter(ChromiumPageSetter):
|
||||
_session_setter: SessionPageSetter = ...
|
||||
_chromium_setter: ChromiumPageSetter = ...
|
||||
|
||||
def user_agent(self, ua: str, platform: str = None) -> None: ...
|
||||
|
||||
def headers(self, headers: Union[str, dict]) -> None: ...
|
||||
def __init__(self, owner: MixPage):
|
||||
"""
|
||||
:param owner: MixPage对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def cookies(self) -> MixPageCookiesSetter: ...
|
||||
@ -178,81 +417,216 @@ class MixTabSetter(TabSetter):
|
||||
_session_setter: SessionPageSetter = ...
|
||||
_chromium_setter: ChromiumBaseSetter = ...
|
||||
|
||||
def user_agent(self, ua: str, platform: str = None) -> None: ...
|
||||
|
||||
def headers(self, headers: Union[str, dict]) -> None: ...
|
||||
def __init__(self, owner: MixTab):
|
||||
"""
|
||||
:param owner: MixTab对象
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def cookies(self) -> MixPageCookiesSetter: ...
|
||||
def cookies(self) -> MixPageCookiesSetter:
|
||||
"""返回用于设置cookies的对象"""
|
||||
...
|
||||
|
||||
def timeouts(self, base: float = None, page_load: float = None, script: float = None) -> None: ...
|
||||
def timeouts(self,
|
||||
base: float = None,
|
||||
page_load: float = None,
|
||||
script: float = None) -> None:
|
||||
"""设置超时时间,单位为秒
|
||||
:param base: 基本等待时间,除页面加载和脚本超时,其它等待默认使用
|
||||
:param page_load: 页面加载超时时间
|
||||
:param script: 脚本运行超时时间
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class ChromiumElementSetter(object):
|
||||
_ele: ChromiumElement = ...
|
||||
|
||||
def __init__(self, ele: ChromiumElement):
|
||||
self._ele: ChromiumElement = ...
|
||||
"""
|
||||
:param ele: ChromiumElement
|
||||
"""
|
||||
...
|
||||
|
||||
def attr(self, name: str, value: str = '') -> None: ...
|
||||
def attr(self, name: str, value: str = '') -> None:
|
||||
"""设置元素attribute属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def property(self, name: str, value: str) -> None: ...
|
||||
def property(self, name: str, value: str) -> None:
|
||||
"""设置元素property属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def style(self, name: str, value: str) -> None: ...
|
||||
def style(self, name: str, value: str) -> None:
|
||||
"""设置元素style样式
|
||||
:param name: 样式名称
|
||||
:param value: 样式值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def innerHTML(self, html: str) -> None: ...
|
||||
def innerHTML(self, html: str) -> None:
|
||||
"""设置元素innerHTML
|
||||
:param html: html文本
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def value(self, value: str) -> None: ...
|
||||
def value(self, value: str) -> None:
|
||||
"""设置元素value值
|
||||
:param value: value值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class ChromiumFrameSetter(ChromiumBaseSetter):
|
||||
_owner: ChromiumFrame = ...
|
||||
|
||||
def attr(self, name: str, value: str) -> None: ...
|
||||
def attr(self, name: str, value: str) -> None:
|
||||
"""设置frame元素attribute属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def property(self, name, value) -> None:
|
||||
"""设置元素property属性
|
||||
:param name: 属性名
|
||||
:param value: 属性值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def style(self, name, value) -> None:
|
||||
"""设置元素style样式
|
||||
:param name: 样式名称
|
||||
:param value: 样式值
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class LoadMode(object):
|
||||
_owner: Union[Chromium, ChromiumBase] = ...
|
||||
|
||||
def __init__(self, owner: Union[Chromium, ChromiumBase]): ...
|
||||
def __init__(self, owner: Union[Chromium, ChromiumBase]):
|
||||
"""
|
||||
:param owner: ChromiumBase对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, value: str) -> None: ...
|
||||
def __call__(self, value: str) -> None:
|
||||
"""设置加载策略
|
||||
:param value: 可选 'normal', 'eager', 'none'
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def normal(self) -> None: ...
|
||||
def normal(self) -> None:
|
||||
"""设置页面加载策略为normal"""
|
||||
...
|
||||
|
||||
def eager(self) -> None: ...
|
||||
def eager(self) -> None:
|
||||
"""设置页面加载策略为eager"""
|
||||
...
|
||||
|
||||
def none(self) -> None: ...
|
||||
def none(self) -> None:
|
||||
"""设置页面加载策略为none"""
|
||||
...
|
||||
|
||||
|
||||
class PageScrollSetter(object):
|
||||
_scroll: PageScroller = ...
|
||||
|
||||
def __init__(self, scroll: PageScroller):
|
||||
self._scroll: PageScroller = ...
|
||||
"""
|
||||
:param scroll: PageScroller对象
|
||||
"""
|
||||
...
|
||||
|
||||
def wait_complete(self, on_off: bool = True): ...
|
||||
def wait_complete(self, on_off: bool = True):
|
||||
"""设置滚动命令后是否等待完成
|
||||
:param on_off: 开或关
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def smooth(self, on_off: bool = True): ...
|
||||
def smooth(self, on_off: bool = True):
|
||||
"""设置页面滚动是否平滑滚动
|
||||
:param on_off: 开或关
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class WindowSetter(object):
|
||||
def __init__(self, owner: ChromiumBase):
|
||||
self._owner: ChromiumBase = ...
|
||||
self._window_id: str = ...
|
||||
_owner: ChromiumBase = ...
|
||||
_window_id: str = ...
|
||||
|
||||
def max(self) -> None: ...
|
||||
def __init__(self, owner: Union[ChromiumTab, ChromiumPage]):
|
||||
"""
|
||||
:param owner: Tab或Page对象
|
||||
"""
|
||||
...
|
||||
|
||||
def mini(self) -> None: ...
|
||||
def max(self) -> None:
|
||||
"""窗口最大化"""
|
||||
...
|
||||
|
||||
def full(self) -> None: ...
|
||||
def mini(self) -> None:
|
||||
"""窗口最小化"""
|
||||
...
|
||||
|
||||
def normal(self) -> None: ...
|
||||
def full(self) -> None:
|
||||
"""设置窗口为全屏"""
|
||||
...
|
||||
|
||||
def size(self, width: int = None, height: int = None) -> None: ...
|
||||
def normal(self) -> None:
|
||||
"""设置窗口为常规模式"""
|
||||
...
|
||||
|
||||
def location(self, x: int = None, y: int = None) -> None: ...
|
||||
def size(self, width: int = None, height: int = None) -> None:
|
||||
"""设置窗口大小
|
||||
:param width: 窗口宽度
|
||||
:param height: 窗口高度
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _get_info(self) -> dict: ...
|
||||
def location(self, x: int = None, y: int = None) -> None:
|
||||
"""设置窗口在屏幕中的位置,相对左上角坐标
|
||||
:param x: 距离顶部距离
|
||||
:param y: 距离左边距离
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def _perform(self, bounds: dict) -> None: ...
|
||||
def hide(self) -> None:
|
||||
"""隐藏浏览器窗口,只在Windows系统可用"""
|
||||
...
|
||||
|
||||
def hide(self) -> None: ...
|
||||
def show(self) -> None:
|
||||
"""显示浏览器窗口,只在Windows系统可用"""
|
||||
...
|
||||
|
||||
def show(self) -> None: ...
|
||||
def _get_info(self) -> dict:
|
||||
"""获取窗口位置及大小信息"""
|
||||
...
|
||||
|
||||
def _perform(self, bounds: dict) -> None:
|
||||
"""执行改变窗口大小操作
|
||||
:param bounds: 控制数据
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
@ -17,11 +17,6 @@ class OriginWaiter(object):
|
||||
self._owner = owner
|
||||
|
||||
def __call__(self, second, scope=None):
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
if scope is None:
|
||||
sleep(second)
|
||||
else:
|
||||
@ -33,12 +28,6 @@ class OriginWaiter(object):
|
||||
class BrowserWaiter(OriginWaiter):
|
||||
|
||||
def new_tab(self, timeout=None, curr_tab=None, raise_err=None):
|
||||
"""等待新标签页出现
|
||||
:param timeout: 超时时间(秒),为None则使用页面对象timeout属性
|
||||
:param curr_tab: 指定当前最新的tab对象或tab id,用于判断新tab出现,为None自动获取
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等到新标签页返回其id,否则返回False
|
||||
"""
|
||||
if not curr_tab:
|
||||
curr_tab = self._owner.tab_ids[0]
|
||||
elif hasattr(curr_tab, '_type'):
|
||||
@ -57,11 +46,6 @@ class BrowserWaiter(OriginWaiter):
|
||||
return False
|
||||
|
||||
def download_begin(self, timeout=None, cancel_it=False):
|
||||
"""等待浏览器下载开始,可将其拦截
|
||||
:param timeout: 超时时间(秒),None使用页面对象超时时间
|
||||
:param cancel_it: 是否取消该任务
|
||||
:return: 成功返回任务对象,失败返回False
|
||||
"""
|
||||
if not self._owner._dl_mgr._running:
|
||||
raise RuntimeError('此功能需显式设置下载路径才能使用。使用set.download_path()方法、配置对象或ini文件均可。')
|
||||
self._owner._dl_mgr.set_flag('browser', False if cancel_it else True)
|
||||
@ -81,11 +65,6 @@ class BrowserWaiter(OriginWaiter):
|
||||
return r
|
||||
|
||||
def all_downloads_done(self, timeout=None, cancel_if_timeout=True):
|
||||
"""等待所有浏览器下载任务结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消剩余任务
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if not self._owner._dl_mgr._running:
|
||||
raise RuntimeError('此功能需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
if not timeout:
|
||||
@ -112,22 +91,10 @@ class BrowserWaiter(OriginWaiter):
|
||||
class BaseWaiter(OriginWaiter):
|
||||
|
||||
def ele_deleted(self, loc_or_ele, timeout=None, raise_err=None):
|
||||
"""等待元素从DOM中删除
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
ele = self._owner._ele(loc_or_ele, raise_err=False, timeout=0)
|
||||
return ele.wait.deleted(timeout, raise_err=raise_err) if ele else True
|
||||
|
||||
def ele_displayed(self, loc_or_ele, timeout=None, raise_err=None):
|
||||
"""等待元素变成显示状态
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self._owner.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
@ -141,12 +108,6 @@ class BaseWaiter(OriginWaiter):
|
||||
return ele.wait.displayed(timeout, raise_err=raise_err)
|
||||
|
||||
def ele_hidden(self, loc_or_ele, timeout=None, raise_err=None):
|
||||
"""等待元素变成隐藏状态
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self._owner.timeout
|
||||
end_time = perf_counter() + timeout
|
||||
@ -160,13 +121,6 @@ class BaseWaiter(OriginWaiter):
|
||||
return ele.wait.hidden(timeout, raise_err=raise_err)
|
||||
|
||||
def eles_loaded(self, locators, timeout=None, any_one=False, raise_err=None):
|
||||
"""等待元素加载到DOM,可等待全部或任意一个
|
||||
:param locators: 要等待的元素,输入定位符,用list输入多个
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param any_one: 是否等待到一个就返回
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回True,失败返回False
|
||||
"""
|
||||
|
||||
def _find(loc, driver):
|
||||
r = driver.run('DOM.performSearch', query=loc, includeUserAgentShadowDOM=True)
|
||||
@ -211,23 +165,12 @@ class BaseWaiter(OriginWaiter):
|
||||
return False
|
||||
|
||||
def load_start(self, timeout=None, raise_err=None):
|
||||
"""等待页面开始加载
|
||||
:param timeout: 超时时间(秒),为None时使用页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._loading(timeout=timeout, gap=.002, raise_err=raise_err)
|
||||
|
||||
def doc_loaded(self, timeout=None, raise_err=None):
|
||||
"""等待页面加载完成
|
||||
:param timeout: 超时时间(秒),为None时使用页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._loading(timeout=timeout, start=False, raise_err=raise_err)
|
||||
|
||||
def upload_paths_inputted(self):
|
||||
"""等待自动填写上传文件路径"""
|
||||
end_time = perf_counter() + self._owner.timeout
|
||||
while perf_counter() < end_time:
|
||||
if not self._owner._upload_list:
|
||||
@ -236,11 +179,6 @@ class BaseWaiter(OriginWaiter):
|
||||
return False
|
||||
|
||||
def download_begin(self, timeout=None, cancel_it=False):
|
||||
"""等待浏览器下载开始,可将其拦截
|
||||
:param timeout: 超时时间(秒),None使用页面对象超时时间
|
||||
:param cancel_it: 是否取消该任务
|
||||
:return: 成功返回任务对象,失败返回False
|
||||
"""
|
||||
if not self._owner.browser._dl_mgr._running:
|
||||
raise RuntimeError('此功能需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
self._owner.browser._dl_mgr.set_flag(self._owner.tab_id, False if cancel_it else True)
|
||||
@ -260,34 +198,12 @@ class BaseWaiter(OriginWaiter):
|
||||
return r
|
||||
|
||||
def url_change(self, text, exclude=False, timeout=None, raise_err=None):
|
||||
"""等待url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
return self._owner if self._change('url', text, exclude, timeout, raise_err) else False
|
||||
|
||||
def title_change(self, text, exclude=False, timeout=None, raise_err=None):
|
||||
"""等待title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
return self._owner if self._change('title', text, exclude, timeout, raise_err) else False
|
||||
|
||||
def _change(self, arg, text, exclude=False, timeout=None, raise_err=None):
|
||||
"""等待指定属性变成包含或不包含指定文本
|
||||
:param arg: 要被匹配的属性
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当属性不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
|
||||
def do():
|
||||
if arg == 'url':
|
||||
@ -317,13 +233,6 @@ class BaseWaiter(OriginWaiter):
|
||||
return False
|
||||
|
||||
def _loading(self, timeout=None, start=True, gap=.01, raise_err=None):
|
||||
"""等待页面开始加载或加载完成
|
||||
:param timeout: 超时时间(秒),为None时使用页面timeout属性
|
||||
:param start: 等待开始还是结束
|
||||
:param gap: 间隔秒数
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self._owner.timeout
|
||||
timeout = .1 if timeout <= 0 else timeout
|
||||
@ -343,11 +252,6 @@ class TabWaiter(BaseWaiter):
|
||||
"""标签页对象等待对象"""
|
||||
|
||||
def downloads_done(self, timeout=None, cancel_if_timeout=True):
|
||||
"""等待所有浏览器下载任务结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消剩余任务
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
if not self._owner.browser._dl_mgr._running:
|
||||
raise RuntimeError('此功能需显式设置下载路径(使用set.download_path()方法、配置对象或ini文件均可)。')
|
||||
if not timeout:
|
||||
@ -371,7 +275,6 @@ class TabWaiter(BaseWaiter):
|
||||
return True
|
||||
|
||||
def alert_closed(self):
|
||||
"""等待弹出框关闭"""
|
||||
while not self._owner.states.has_alert:
|
||||
sleep(.2)
|
||||
while self._owner.states.has_alert:
|
||||
@ -382,19 +285,9 @@ class PageWaiter(TabWaiter):
|
||||
"""ChromiumPage和MixPage的等待对象"""
|
||||
|
||||
def new_tab(self, timeout=None, raise_err=None):
|
||||
"""等待新标签页出现
|
||||
:param timeout: 超时时间(秒),为None则使用页面对象timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等到新标签页返回其id,否则返回False
|
||||
"""
|
||||
return self._owner.browser.wait.new_tab(timeout=timeout, raise_err=raise_err)
|
||||
|
||||
def all_downloads_done(self, timeout=None, cancel_if_timeout=True):
|
||||
"""等待所有浏览器下载任务结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消剩余任务
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
return self._owner.browser.wait.all_downloads_done(timeout=timeout, cancel_if_timeout=cancel_if_timeout)
|
||||
|
||||
|
||||
@ -407,71 +300,30 @@ class ElementWaiter(OriginWaiter):
|
||||
|
||||
@property
|
||||
def _timeout(self):
|
||||
"""返回超时设置"""
|
||||
return self._ele.owner.timeout
|
||||
|
||||
def deleted(self, timeout=None, raise_err=None):
|
||||
"""等待元素从dom删除
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
return self._wait_state('is_alive', False, timeout, raise_err, err_text='等待元素被删除失败。')
|
||||
|
||||
def displayed(self, timeout=None, raise_err=None):
|
||||
"""等待元素从dom显示
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
return self._wait_state('is_displayed', True, timeout, raise_err, err_text='等待元素显示失败。')
|
||||
|
||||
def hidden(self, timeout=None, raise_err=None):
|
||||
"""等待元素从dom隐藏
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
return self._wait_state('is_displayed', False, timeout, raise_err, err_text='等待元素隐藏失败。')
|
||||
|
||||
def covered(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素被遮盖
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回覆盖元素id,返回False
|
||||
"""
|
||||
return self._wait_state('is_covered', True, timeout, raise_err, err_text='等待元素被覆盖失败。')
|
||||
|
||||
def not_covered(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素不被遮盖
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
return self._wait_state('is_covered', False, timeout, raise_err, err_text='等待元素不被覆盖失败。')
|
||||
|
||||
def enabled(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素变成可用
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
return self._wait_state('is_enabled', True, timeout, raise_err, err_text='等待元素变成可用失败。')
|
||||
|
||||
def disabled(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素变成不可用
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
return self._wait_state('is_enabled', False, timeout, raise_err, err_text='等待元素变成不可用失败。')
|
||||
|
||||
def disabled_or_deleted(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素变成不可用或从DOM移除
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
if not self._ele.states.is_enabled or not self._ele.states.is_alive:
|
||||
return self._ele
|
||||
|
||||
@ -488,13 +340,20 @@ class ElementWaiter(OriginWaiter):
|
||||
else:
|
||||
return False
|
||||
|
||||
def clickable(self, wait_moved=True, timeout=None, raise_err=None):
|
||||
if timeout is None:
|
||||
timeout = self._timeout
|
||||
t1 = perf_counter()
|
||||
r = self._wait_state('is_clickable', True, timeout, raise_err, err_text='等待元素可点击失败(等{}秒)。')
|
||||
r = self.stop_moving(timeout=timeout - perf_counter() + t1) if wait_moved and r else r
|
||||
if raise_err and not r:
|
||||
raise WaitTimeoutError(f'等待元素可点击失败(等{timeout}秒)。')
|
||||
return r
|
||||
|
||||
def has_rect(self, timeout=None, raise_err=None):
|
||||
return self._wait_state('has_rect', True, timeout, raise_err, err_text='等待元素拥有大小及位置失败(等{}秒)。')
|
||||
|
||||
def stop_moving(self, timeout=None, gap=.1, raise_err=None):
|
||||
"""等待当前元素停止运动
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param gap: 检测间隔时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self._timeout
|
||||
if timeout <= 0:
|
||||
@ -524,39 +383,7 @@ class ElementWaiter(OriginWaiter):
|
||||
else:
|
||||
return False
|
||||
|
||||
def clickable(self, wait_moved=True, timeout=None, raise_err=None):
|
||||
"""等待当前元素可被点击
|
||||
:param wait_moved: 是否等待元素运动结束
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = self._timeout
|
||||
t1 = perf_counter()
|
||||
r = self._wait_state('is_clickable', True, timeout, raise_err, err_text='等待元素可点击失败(等{}秒)。')
|
||||
r = self.stop_moving(timeout=timeout - perf_counter() + t1) if wait_moved and r else r
|
||||
if raise_err and not r:
|
||||
raise WaitTimeoutError(f'等待元素可点击失败(等{timeout}秒)。')
|
||||
return r
|
||||
|
||||
def has_rect(self, timeout=None, raise_err=None):
|
||||
"""等待当前元素有大小及位置属性
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素四角坐标(左上 右上 右下 左下),失败返回False
|
||||
"""
|
||||
return self._wait_state('has_rect', True, timeout, raise_err, err_text='等待元素拥有大小及位置失败(等{}秒)。')
|
||||
|
||||
def _wait_state(self, attr, mode=False, timeout=None, raise_err=None, err_text=None):
|
||||
"""等待元素某个元素状态到达指定状态
|
||||
:param attr: 状态名称
|
||||
:param mode: 等待True还是False
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:param err_text: 抛出错误时显示的信息
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
a = self._ele.states.__getattribute__(attr)
|
||||
if (a and mode) or (not a and not mode):
|
||||
return self._ele if isinstance(a, bool) else a
|
||||
@ -584,5 +411,4 @@ class FrameWaiter(BaseWaiter, ElementWaiter):
|
||||
|
||||
@property
|
||||
def _timeout(self):
|
||||
"""返回超时设置"""
|
||||
return self._owner.timeout
|
||||
|
@ -5,7 +5,7 @@
|
||||
@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved.
|
||||
@License : BSD 3-Clause.
|
||||
"""
|
||||
from typing import Union, Tuple, List
|
||||
from typing import Union, Tuple, List, Any
|
||||
|
||||
from .downloader import DownloadMission
|
||||
from .._base.browser import Chromium
|
||||
@ -18,28 +18,63 @@ from .._pages.tabs import ChromiumTab, MixTab
|
||||
|
||||
|
||||
class OriginWaiter(object):
|
||||
_owner = ...
|
||||
_owner: Any = ...
|
||||
|
||||
def __init__(self, owner): ...
|
||||
def __init__(self, owner: Any): ...
|
||||
|
||||
def __call__(self, second: float, scope: float = None): ...
|
||||
def __call__(self, second: float, scope: float = None):
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class BrowserWaiter(OriginWaiter):
|
||||
_owner: Chromium = ...
|
||||
|
||||
def __init__(self, owner: Chromium): ...
|
||||
def __init__(self, owner: Chromium):
|
||||
"""
|
||||
:param owner: Chromium对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, second: float, scope: float = None) -> Chromium: ...
|
||||
|
||||
def download_begin(self, timeout: float = None, cancel_it: bool = False) -> DownloadMission: ...
|
||||
def __call__(self, second: float, scope: float = None) -> Chromium:
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def new_tab(self,
|
||||
timeout: float = None,
|
||||
curr_tab: Union[str, ChromiumTab] = None,
|
||||
raise_err: bool = None) -> Union[str, bool]: ...
|
||||
raise_err: bool = None) -> Union[str, bool]:
|
||||
"""等待新标签页出现
|
||||
:param timeout: 超时时间(秒),为None则使用页面对象timeout属性
|
||||
:param curr_tab: 指定当前最新的tab对象或tab id,用于判断新tab出现,为None自动获取
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等到新标签页返回其id,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def all_downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool: ...
|
||||
def download_begin(self, timeout: float = None, cancel_it: bool = False) -> DownloadMission:
|
||||
"""等待浏览器下载开始,可将其拦截
|
||||
:param timeout: 超时时间(秒),None使用页面对象超时时间
|
||||
:param cancel_it: 是否取消该任务
|
||||
:return: 成功返回任务对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def all_downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool:
|
||||
"""等待所有浏览器下载任务结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消剩余任务
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class BaseWaiter(OriginWaiter):
|
||||
@ -48,131 +83,417 @@ class BaseWaiter(OriginWaiter):
|
||||
def ele_deleted(self,
|
||||
loc_or_ele: Union[str, tuple, ChromiumElement],
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待元素从DOM中删除
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def ele_displayed(self,
|
||||
loc_or_ele: Union[str, tuple, ChromiumElement],
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待元素变成显示状态
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def ele_hidden(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待元素变成隐藏状态
|
||||
:param loc_or_ele: 要等待的元素,可以是已有元素、定位符
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def eles_loaded(self,
|
||||
locators: Union[Tuple[str, str], str, list, tuple],
|
||||
timeout: float = None,
|
||||
any_one: bool = False,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待元素加载到DOM,可等待全部或任意一个
|
||||
:param locators: 要等待的元素,输入定位符,用list输入多个
|
||||
:param timeout: 超时时间(秒),默认读取页面超时时间
|
||||
:param any_one: 是否等待到一个就返回
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回True,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def _loading(self, timeout: float = None, start: bool = True, gap: float = .01, raise_err: bool = None) -> bool: ...
|
||||
def load_start(self, timeout: float = None, raise_err: bool = None) -> bool:
|
||||
"""等待页面开始加载
|
||||
:param timeout: 超时时间(秒),为None时使用页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def load_start(self, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
def doc_loaded(self, timeout: float = None, raise_err: bool = None) -> bool:
|
||||
"""等待页面加载完成
|
||||
:param timeout: 超时时间(秒),为None时使用页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def doc_loaded(self, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
def upload_paths_inputted(self) -> bool:
|
||||
"""等待自动填写上传文件路径"""
|
||||
...
|
||||
|
||||
def upload_paths_inputted(self) -> bool: ...
|
||||
def download_begin(self, timeout: float = None, cancel_it: bool = False) -> Union[DownloadMission, bool]:
|
||||
"""等待浏览器下载开始,可将其拦截
|
||||
:param timeout: 超时时间(秒),None使用页面对象超时时间
|
||||
:param cancel_it: 是否取消该任务
|
||||
:return: 成功返回任务对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def download_begin(self, timeout: float = None, cancel_it: bool = False) -> Union[DownloadMission, bool]: ...
|
||||
def url_change(self,
|
||||
text: str,
|
||||
exclude: bool = False,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool: ...
|
||||
|
||||
def url_change(self, text: str, exclude: bool = False, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
|
||||
def title_change(self, text: str, exclude: bool = False, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
def title_change(self,
|
||||
text: str,
|
||||
exclude: bool = False,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def _change(self, arg: str, text: str, exclude: bool = False, timeout: float = None,
|
||||
raise_err: bool = None) -> bool: ...
|
||||
raise_err: bool = None) -> bool:
|
||||
"""等待指定属性变成包含或不包含指定文本
|
||||
:param arg: 要被匹配的属性
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当属性不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def _loading(self, timeout: float = None, start: bool = True, gap: float = .01, raise_err: bool = None) -> bool:
|
||||
"""等待页面开始加载或加载完成
|
||||
:param timeout: 超时时间(秒),为None时使用页面timeout属性
|
||||
:param start: 等待开始还是结束
|
||||
:param gap: 间隔秒数
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class TabWaiter(BaseWaiter):
|
||||
_owner: Union[ChromiumTab, MixTab] = ...
|
||||
|
||||
def __init__(self, owner: Union[ChromiumTab, MixTab]): ...
|
||||
def __init__(self, owner: Union[ChromiumTab, MixTab]):
|
||||
"""
|
||||
:param owner: Tab对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, second: float, scope: float = None) -> Union[ChromiumTab, MixTab]: ...
|
||||
def __call__(self, second: float, scope: float = None) -> Union[ChromiumTab, MixTab]:
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool: ...
|
||||
def downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool:
|
||||
"""等待所有浏览器下载任务结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消剩余任务
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def alert_closed(self) -> None: ...
|
||||
def alert_closed(self) -> None:
|
||||
"""等待弹出框关闭"""
|
||||
...
|
||||
|
||||
def url_change(self, text: str, exclude: bool = False,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumTab, MixTab]: ...
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumTab, MixTab]:
|
||||
"""等待url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def title_change(self, text: str, exclude: bool = False,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumTab, MixTab]: ...
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumTab, MixTab]:
|
||||
"""等待title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class PageWaiter(TabWaiter):
|
||||
_owner: Union[ChromiumPage, MixPage] = ...
|
||||
|
||||
def __init__(self, owner: Union[ChromiumPage, MixPage]): ...
|
||||
def __init__(self, owner: Union[ChromiumPage, MixPage]):
|
||||
"""
|
||||
:param owner: Page对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, second: float, scope: float = None) -> Union[ChromiumPage, MixPage]: ...
|
||||
def __call__(self, second: float, scope: float = None) -> Union[ChromiumPage, MixPage]:
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def new_tab(self, timeout: float = None, raise_err: bool = None) -> Union[str, bool]: ...
|
||||
def new_tab(self, timeout: float = None, raise_err: bool = None) -> Union[str, bool]:
|
||||
"""等待新标签页出现
|
||||
:param timeout: 超时时间(秒),为None则使用页面对象timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等到新标签页返回其id,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def all_downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool: ...
|
||||
def all_downloads_done(self, timeout: float = None, cancel_if_timeout: bool = True) -> bool:
|
||||
"""等待所有浏览器下载任务结束
|
||||
:param timeout: 超时时间(秒),为None时无限等待
|
||||
:param cancel_if_timeout: 超时时是否取消剩余任务
|
||||
:return: 是否等待成功
|
||||
"""
|
||||
...
|
||||
|
||||
def url_change(self, text: str, exclude: bool = False,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumPage, MixPage]: ...
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumPage, MixPage]:
|
||||
"""等待url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def title_change(self, text: str, exclude: bool = False,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumPage, MixPage]: ...
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumPage, MixPage]:
|
||||
"""等待title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class ElementWaiter(OriginWaiter):
|
||||
_owner: ChromiumElement = ...
|
||||
_ele: ChromiumElement = ...
|
||||
|
||||
def __init__(self, owner: ChromiumElement): ...
|
||||
def __init__(self, owner: ChromiumElement):
|
||||
"""
|
||||
:param owner: ChromiumElement对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, second: float, scope: float = None) -> ChromiumElement: ...
|
||||
def __call__(self,
|
||||
second: float,
|
||||
scope: float = None) -> ChromiumElement:
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
@property
|
||||
def _timeout(self) -> float: ...
|
||||
def _timeout(self) -> float:
|
||||
"""返回超时设置"""
|
||||
...
|
||||
|
||||
def deleted(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def deleted(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待元素从dom删除
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def displayed(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def displayed(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待元素从dom显示
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def hidden(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def hidden(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待元素从dom隐藏
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def covered(self, timeout: float = None, raise_err: bool = None) -> Union[False, int]: ...
|
||||
def covered(self, timeout: float = None, raise_err: bool = None) -> Union[False, int]:
|
||||
"""等待当前元素被遮盖
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回覆盖元素id,返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def not_covered(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def not_covered(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待当前元素不被遮盖
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def enabled(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def enabled(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待当前元素变成可用
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def disabled(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def disabled(self, timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待当前元素变成不可用
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def disabled_or_deleted(self, timeout: float = None, raise_err: bool = None) -> bool:
|
||||
"""等待当前元素变成不可用或从DOM移除
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def clickable(self, wait_moved: bool = True,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
timeout: float = None, raise_err: bool = None) -> Union[ChromiumElement, False]:
|
||||
"""等待当前元素可被点击
|
||||
:param wait_moved: 是否等待元素运动结束
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def has_rect(self,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> Union[False, List[Tuple[float, float]]]: ...
|
||||
raise_err: bool = None) -> Union[False, List[Tuple[float, float]]]:
|
||||
"""等待当前元素有大小及位置属性
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素四角坐标(左上 右上 右下 左下),失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def disabled_or_deleted(self, timeout: float = None, raise_err: bool = None) -> bool: ...
|
||||
|
||||
def stop_moving(self, timeout: float = None, gap: float = .1, raise_err: bool = None) -> Union[ChromiumElement, False]: ...
|
||||
def stop_moving(self, timeout: float = None, gap: float = .1, raise_err: bool = None) -> Union[
|
||||
ChromiumElement, False]:
|
||||
"""等待当前元素停止运动
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param gap: 检测间隔时间
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def _wait_state(self,
|
||||
attr: str,
|
||||
mode: bool = False,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None,
|
||||
err_text: str = None) -> Union[ChromiumElement, False]: ...
|
||||
err_text: str = None) -> Union[ChromiumElement, False]:
|
||||
"""等待元素某个元素状态到达指定状态
|
||||
:param attr: 状态名称
|
||||
:param mode: 等待True还是False
|
||||
:param timeout: 超时时间(秒),为None使用元素所在页面timeout属性
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:param err_text: 抛出错误时显示的信息
|
||||
:return: 成功返回元素对象,失败返回False
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class FrameWaiter(BaseWaiter, ElementWaiter):
|
||||
_owner: ChromiumFrame = ...
|
||||
|
||||
def __init__(self, owner: ChromiumFrame): ...
|
||||
def __init__(self, owner: ChromiumFrame):
|
||||
"""
|
||||
:param owner: ChromiumFrame对象
|
||||
"""
|
||||
...
|
||||
|
||||
def __call__(self, second: float, scope: float = None) -> ChromiumFrame: ...
|
||||
def __call__(self,
|
||||
second: float,
|
||||
scope: float = None) -> ChromiumFrame:
|
||||
"""等待若干秒,如传入两个参数,等待时间为这两个数间的一个随机数
|
||||
:param second: 秒数
|
||||
:param scope: 随机数范围
|
||||
:return: None
|
||||
"""
|
||||
...
|
||||
|
||||
def url_change(self, text: str, exclude: bool = False,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumFrame]: ...
|
||||
def url_change(self,
|
||||
text: str,
|
||||
exclude: bool = False,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> Union[False, ChromiumFrame]:
|
||||
"""等待url变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当url不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒)
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
||||
def title_change(self, text: str, exclude: bool = False,
|
||||
timeout: float = None, raise_err: bool = None) -> Union[False, ChromiumFrame]: ...
|
||||
def title_change(self,
|
||||
text: str,
|
||||
exclude: bool = False,
|
||||
timeout: float = None,
|
||||
raise_err: bool = None) -> Union[False, ChromiumFrame]:
|
||||
"""等待title变成包含或不包含指定文本
|
||||
:param text: 用于识别的文本
|
||||
:param exclude: 是否排除,为True时当title不包含text指定文本时返回True
|
||||
:param timeout: 超时时间(秒),为None使用页面设置
|
||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||
:return: 等待成功返回页面对象,否则返回False
|
||||
"""
|
||||
...
|
||||
|
Loading…
x
Reference in New Issue
Block a user