4.0.0b29(+)

增加disconnect()方法;
优化查找元素逻辑;
修复动作链按键超时问题;
This commit is contained in:
g1879 2023-12-25 18:00:13 +08:00
parent d8a85d361e
commit e86ac7517d
19 changed files with 263 additions and 237 deletions

View File

@ -13,4 +13,4 @@ from ._configs.chromium_options import ChromiumOptions
from ._configs.session_options import SessionOptions
__all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__']
__version__ = '4.0.0b28'
__version__ = '4.0.0b29'

View File

@ -144,7 +144,7 @@ class DrissionElement(BaseElement):
"""返回直接子元素元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param index: 第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 直接子元素或节点文本组成的列表
"""
@ -174,7 +174,7 @@ class DrissionElement(BaseElement):
"""返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 前面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素
"""
@ -194,7 +194,7 @@ class DrissionElement(BaseElement):
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 后面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素
"""
@ -214,7 +214,7 @@ class DrissionElement(BaseElement):
"""返回前面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 前面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素前面的某个元素或节点
"""
@ -234,7 +234,7 @@ class DrissionElement(BaseElement):
"""返回后面的一个兄弟元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 后面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素后面的某个元素或节点
"""
@ -253,7 +253,7 @@ class DrissionElement(BaseElement):
def children(self, filter_loc='', timeout=None, ele_only=True):
"""返回直接子元素元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 直接子元素或节点文本组成的列表
"""
@ -272,7 +272,7 @@ class DrissionElement(BaseElement):
def prevs(self, filter_loc='', timeout=None, ele_only=True):
"""返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素或节点文本组成的列表
"""
@ -281,7 +281,7 @@ class DrissionElement(BaseElement):
def nexts(self, filter_loc='', timeout=None, ele_only=True):
"""返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素或节点文本组成的列表
"""
@ -290,7 +290,7 @@ class DrissionElement(BaseElement):
def befores(self, filter_loc='', timeout=None, ele_only=True):
"""返回后面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素前面的元素或节点组成的列表
"""
@ -300,7 +300,7 @@ class DrissionElement(BaseElement):
def afters(self, filter_loc='', timeout=None, ele_only=True):
"""返回前面全部兄弟元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素后面的元素或节点组成的列表
"""
@ -314,7 +314,7 @@ class DrissionElement(BaseElement):
:param filter_loc: 用于筛选的查询语法
:param direction: 'following' 'preceding'查找的方向
:param brother: 查找范围在同级查找还是整个dom前后查找
:param timeout: 查找等待时间
:param timeout: 查找等待时间
:return: 元素对象或字符串
"""
if index is not None and index < 1:

View File

@ -160,7 +160,7 @@ class Browser(object):
def quit(self, timeout=5, force=False):
"""关闭浏览器
:param timeout: 等待浏览器关闭超时时间
:param timeout: 等待浏览器关闭超时时间
:param force: 是否立刻强制终止进程
:return: None
"""

View File

@ -3,13 +3,14 @@
@Author : g1879
@Contact : g1879@qq.com
"""
from json import dumps, loads
from json import dumps, loads, JSONDecodeError
from queue import Queue, Empty
from threading import Thread, Event
from time import perf_counter
from requests import get
from websocket import WebSocketTimeoutException, WebSocketConnectionClosedException, create_connection
from websocket import (WebSocketTimeoutException, WebSocketConnectionClosedException, create_connection,
WebSocketException)
class Driver(object):
@ -74,7 +75,7 @@ class Driver(object):
except (OSError, WebSocketConnectionClosedException):
self.method_results.pop(ws_id, None)
return None
return {'error': {'message': 'page closed'}}
while not self._stopped.is_set():
try:
@ -102,7 +103,7 @@ class Driver(object):
msg = loads(msg_json)
except WebSocketTimeoutException:
continue
except:
except (WebSocketException, OSError, WebSocketConnectionClosedException, JSONDecodeError):
self.stop()
return
@ -119,10 +120,10 @@ class Driver(object):
if 'method' in msg:
if msg['method'].startswith('Page.javascriptDialog'):
self.alert_flag = msg['method'].endswith('Opening')
if msg['method'] in self.immediate_event_handlers:
function = self.immediate_event_handlers.get(msg['method'])
if function:
function(**msg['params'])
function = self.immediate_event_handlers.get(msg['method'])
if function:
Thread(target=function, kwargs=msg['params']).start()
# function(**msg['params'])
else:
self.event_queue.put(msg)
@ -154,12 +155,10 @@ class Driver(object):
:return: 执行结果
"""
if self._stopped.is_set():
return {'error': 'tab closed', 'type': 'tab_closed'}
return {'error': 'page closed', 'type': 'page_closed'}
timeout = kwargs.pop('_timeout', 15)
result = self._send({'method': _method, 'params': kwargs}, timeout=timeout)
if result is None:
return {'error': 'tab closed', 'type': 'tab_closed'}
if 'result' not in result and 'error' in result:
return {'error': result['error']['message'], 'type': result.get('type', 'call_method_error'),
'method': _method, 'args': kwargs}
@ -169,8 +168,7 @@ class Driver(object):
def start(self):
"""启动连接"""
self._stopped.clear()
self._ws = create_connection(self._websocket_url, enable_multithread=True,
suppress_origin=True)
self._ws = create_connection(self._websocket_url, enable_multithread=True, suppress_origin=True)
self._recv_th.start()
self._handle_event_th.start()
return True

View File

@ -80,7 +80,7 @@ class ChromiumElement(DrissionElement):
def __call__(self, loc_or_str, timeout=None):
"""在内部查找元素
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:param timeout: 超时时间
:return: ChromiumElement对象或属性文本
"""
return self.ele(loc_or_str, timeout)
@ -214,31 +214,31 @@ class ChromiumElement(DrissionElement):
"""
return super().parent(level_or_loc, index)
def child(self, filter_loc='', index=1, timeout=0, ele_only=True):
def child(self, filter_loc='', index=1, timeout=None, ele_only=True):
"""返回当前元素的一个符合条件的直接子元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 直接子元素或节点文本
"""
return super().child(filter_loc, index, timeout, ele_only=ele_only)
def prev(self, filter_loc='', index=1, timeout=0, ele_only=True):
def prev(self, filter_loc='', index=1, timeout=None, ele_only=True):
"""返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 前面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素或节点文本
"""
return super().prev(filter_loc, index, timeout, ele_only=ele_only)
def next(self, filter_loc='', index=1, timeout=0, ele_only=True):
def next(self, filter_loc='', index=1, timeout=None, ele_only=True):
"""返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素或节点文本
"""
@ -249,7 +249,7 @@ class ChromiumElement(DrissionElement):
查找范围不限同级元素而是整个DOM文档
:param filter_loc: 用于筛选的查询语法
:param index: 前面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素前面的某个元素或节点
"""
@ -260,34 +260,34 @@ class ChromiumElement(DrissionElement):
查找范围不限同级元素而是整个DOM文档
:param filter_loc: 用于筛选的查询语法
:param index: 第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素后面的某个元素或节点
"""
return super().after(filter_loc, index, timeout, ele_only=ele_only)
def children(self, filter_loc='', timeout=0, ele_only=True):
def children(self, filter_loc='', timeout=None, ele_only=True):
"""返回当前元素符合条件的直接子元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 直接子元素或节点文本组成的列表
"""
return super().children(filter_loc, timeout, ele_only=ele_only)
def prevs(self, filter_loc='', timeout=0, ele_only=True):
def prevs(self, filter_loc='', timeout=None, ele_only=True):
"""返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素或节点文本组成的列表
"""
return super().prevs(filter_loc, timeout, ele_only=ele_only)
def nexts(self, filter_loc='', timeout=0, ele_only=True):
def nexts(self, filter_loc='', timeout=None, ele_only=True):
"""返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 兄弟元素或节点文本组成的列表
"""
@ -297,7 +297,7 @@ class ChromiumElement(DrissionElement):
"""返回文档中当前元素前面符合条件的元素或节点组成的列表,可用查询语法筛选
查找范围不限同级元素而是整个DOM文档
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素前面的元素或节点组成的列表
"""
@ -307,7 +307,7 @@ class ChromiumElement(DrissionElement):
"""返回文档中当前元素后面符合条件的元素或节点组成的列表,可用查询语法筛选
查找范围不限同级元素而是整个DOM文档
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素后面的元素或节点组成的列表
"""
@ -367,7 +367,7 @@ class ChromiumElement(DrissionElement):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: 运行的结果
"""
return run_js(self, script, as_expr, self.page.timeouts.script if timeout is None else timeout, args)
@ -377,7 +377,7 @@ class ChromiumElement(DrissionElement):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: None
"""
from threading import Thread
@ -387,7 +387,7 @@ class ChromiumElement(DrissionElement):
def ele(self, loc_or_str, timeout=None):
"""返回当前元素下级符合条件的第一个元素、属性或节点文本
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象或属性文本
"""
return self._ele(loc_or_str, timeout, method='ele()')
@ -395,7 +395,7 @@ class ChromiumElement(DrissionElement):
def eles(self, loc_or_str, timeout=None):
"""返回当前元素下级所有符合条件的子元素、属性或节点文本
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象或属性文本组成的列表
"""
return self._ele(loc_or_str, timeout=timeout, single=False)
@ -429,7 +429,7 @@ class ChromiumElement(DrissionElement):
def _find_elements(self, loc_or_str, timeout=None, single=True, relative=False, raise_err=None):
"""返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间
:param timeout: 查找元素超时时间
:param single: True则返回第一个False则返回全部
:param relative: WebPage用的表示是否相对定位的参数
:param raise_err: 找不到元素是是否抛出异常为None时根据全局设置
@ -449,7 +449,7 @@ class ChromiumElement(DrissionElement):
def get_src(self, timeout=None, base64_to_bytes=True):
"""返回元素src资源base64的可转为bytes返回其它返回str
:param timeout: 等待资源加载的超时时间
:param timeout: 等待资源加载的超时时间
:param base64_to_bytes: 为True时如果是base64数据转换为bytes格式
:return: 资源内容
"""
@ -532,7 +532,7 @@ class ChromiumElement(DrissionElement):
"""保存图片或其它有src属性的元素的资源
:param path: 文件保存路径为None时保存到当前文件夹
:param name: 文件名称为None时从资源url获取
:param timeout: 等待资源加载的超时时间
:param timeout: 等待资源加载的超时时间
:return: 返回保存路径
"""
data = self.get_src(timeout=timeout)
@ -603,7 +603,6 @@ class ChromiumElement(DrissionElement):
if clear and vals not in ('\n', '\ue007'):
self.clear(by_js=False)
else:
self.wait.has_rect()
self._input_focus()
input_text_or_keys(self.page, vals)
@ -793,7 +792,7 @@ class ShadowRoot(BaseElement):
"""在内部查找元素
ele2 = ele1('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:param timeout: 超时时间
:return: 元素对象或属性文本
"""
return self.ele(loc_or_str, timeout)
@ -825,7 +824,7 @@ class ShadowRoot(BaseElement):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: 运行的结果
"""
return run_js(self, script, as_expr, self.page.timeouts.script if timeout is None else timeout, args)
@ -835,7 +834,7 @@ class ShadowRoot(BaseElement):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: None
"""
from threading import Thread
@ -986,7 +985,7 @@ class ShadowRoot(BaseElement):
def ele(self, loc_or_str, timeout=None):
"""返回当前元素下级符合条件的第一个元素
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象
"""
return self._ele(loc_or_str, timeout, method='ele()')
@ -994,7 +993,7 @@ class ShadowRoot(BaseElement):
def eles(self, loc_or_str, timeout=None):
"""返回当前元素下级所有符合条件的子元素
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:param timeout: 查找元素超时时间默认与元素所在页面等待时间一致
:return: ChromiumElement对象组成的列表
"""
return self._ele(loc_or_str, timeout=timeout, single=False)
@ -1020,7 +1019,7 @@ class ShadowRoot(BaseElement):
def _find_elements(self, loc_or_str, timeout=None, single=True, relative=False, raise_err=None):
"""返回当前元素下级符合条件的子元素、属性或节点文本,默认返回第一个
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间
:param timeout: 查找元素超时时间
:param single: True则返回第一个False则返回全部
:param relative: WebPage用的表示是否相对定位的参数
:param raise_err: 找不到元素是是否抛出异常为None时根据全局设置
@ -1030,42 +1029,47 @@ class ShadowRoot(BaseElement):
if loc[0] == 'css selector' and str(loc[1]).startswith(':root'):
loc = loc[0], loc[1][5:]
result = None
timeout = timeout if timeout is not None else self.page.timeout
end_time = perf_counter() + timeout
while perf_counter() <= end_time:
def do_find():
if loc[0] == 'css selector':
if single:
nod_id = self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=loc[1])['nodeId']
result = make_chromium_ele(self.page, node_id=nod_id) if nod_id else NoneElement(self.page)
if nod_id:
r = make_chromium_ele(self.page, node_id=nod_id)
return None if r is False else r
else:
nod_ids = self.page.run_cdp('DOM.querySelectorAll', nodeId=self._node_id, selector=loc[1])['nodeId']
result = make_chromium_eles(self.page, node_ids=nod_ids, single=False)
r = make_chromium_eles(self.page, node_ids=nod_ids, single=False)
return None if r is False else r
else:
eles = make_session_ele(self.html).eles(loc)
if not eles:
result = NoneElement(self.page) if single else eles
continue
return None
css = [i.css_path[61:] for i in eles]
if single:
node_id = self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=css[0])['nodeId']
result = make_chromium_ele(self.page, node_id=node_id) if node_id else NoneElement(self.page)
r = make_chromium_ele(self.page, node_id=node_id)
return None if r is False else r
else:
result = []
for i in css:
node_id = self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=i)['nodeId']
if node_id:
result.append(make_chromium_ele(self.page, node_id=node_id))
node_ids = [self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=i)['nodeId']
for i in css]
if 0 in node_ids:
return None
r = make_chromium_eles(self.page, node_ids=node_ids, single=False)
return None if r is False else r
if result:
break
timeout = timeout if timeout is not None else self.page.timeout
end_time = perf_counter() + timeout
result = do_find()
while result is None and perf_counter() <= end_time:
sleep(.1)
result = do_find()
return result
if result:
return result
return NoneElement(self.page) if single else []
def _get_node_id(self, obj_id):
"""返回元素node id"""
@ -1087,7 +1091,7 @@ def find_in_chromium_ele(ele, loc, single=True, timeout=None, relative=True):
:param ele: ChromiumElement对象
:param loc: 元素定位元组
:param single: True则返回第一个False则返回全部
:param timeout: 查找元素超时时间
:param timeout: 查找元素超时时间
:param relative: WebPage用于标记是否相对定位使用
:return: 返回ChromiumElement元素或它们组成的列表
"""
@ -1119,45 +1123,57 @@ def find_by_xpath(ele, xpath, single, timeout, relative=True):
:param ele: 在此元素中查找
:param xpath: 查找语句
:param single: 是否只返回第一个结果
:param timeout: 超时时间
:param timeout: 超时时间
:param relative: 是否相对定位
:return: ChromiumElement或其组成的列表
"""
type_txt = '9' if single else '7'
node_txt = 'this.contentDocument' if ele.tag in __FRAME_ELEMENT__ and not relative else 'this'
js = make_js_for_find_ele_by_xpath(xpath, type_txt, node_txt)
r = ele.page.run_cdp_loaded('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
if r['result']['type'] == 'string':
return r['result']['value']
ele.page.wait.load_complete()
def do_find():
res = ele.page.run_cdp('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
if res['result']['type'] == 'string':
return res['result']['value']
if 'exceptionDetails' in res:
if 'The result is not a node set' in res['result']['description']:
js1 = make_js_for_find_ele_by_xpath(xpath, '1', node_txt)
res = ele.page.run_cdp('Runtime.callFunctionOn', functionDeclaration=js1, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
return res['result']['value']
else:
raise SyntaxError(f'查询语句错误:\n{res}')
if res['result']['subtype'] == 'null' or res['result']['description'] in ('NodeList(0)', 'Array(0)'):
return None
if single:
r = make_chromium_ele(ele.page, obj_id=res['result']['objectId'])
return None if r is False else r
if 'exceptionDetails' in r:
if 'The result is not a node set' in r['result']['description']:
js = make_js_for_find_ele_by_xpath(xpath, '1', node_txt)
r = ele.page.run_cdp_loaded('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
return r['result']['value']
else:
raise SyntaxError(f'查询语句错误:\n{r}')
# from pprint import pprint
# for i in ele.page.run_cdp('Runtime.getProperties',
# objectId=res['result']['objectId'],
# ownProperties=True)['result'][:-1]:
# pprint(i)
r = [make_chromium_ele(ele.page, obj_id=i['value']['objectId']) if i['value']['type'] == 'object' else
i['value']['value'] for i in ele.page.run_cdp('Runtime.getProperties',
objectId=res['result']['objectId'],
ownProperties=True)['result'][:-1]]
return None if not r or r is False in r else r
end_time = perf_counter() + timeout
while ((r['result']['subtype'] == 'null' or r['result']['description'] in ('NodeList(0)', 'Array(0)'))
and perf_counter() < end_time):
r = ele.page.run_cdp_loaded('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
result = do_find()
while result is None and perf_counter() < end_time:
sleep(.1)
result = do_find()
if single:
return NoneElement(ele.page) if r['result']['subtype'] == 'null' \
else make_chromium_ele(ele.page, obj_id=r['result']['objectId'])
if r['result']['description'] in ('NodeList(0)', 'Array(0)'):
return []
else:
r = ele.page.run_cdp_loaded('Runtime.getProperties', objectId=r['result']['objectId'],
ownProperties=True)['result']
return [make_chromium_ele(ele.page, obj_id=i['value']['objectId'])
if i['value']['type'] == 'object' else i['value']['value']
for i in r[:-1]]
if result:
return result
return NoneElement(ele.page) if single else []
def find_by_css(ele, selector, single, timeout):
@ -1165,35 +1181,45 @@ def find_by_css(ele, selector, single, timeout):
:param ele: 在此元素中查找
:param selector: 查找语句
:param single: 是否只返回第一个结果
:param timeout: 超时时间
:param timeout: 超时时间
:return: ChromiumElement或其组成的列表
"""
selector = selector.replace('"', r'\"')
find_all = '' if single else 'All'
node_txt = 'this.contentDocument' if ele.tag in ('iframe', 'frame', 'shadow-root') else 'this'
js = f'function(){{return {node_txt}.querySelector{find_all}("{selector}");}}'
r = ele.page.run_cdp_loaded('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
ele.page.wait.load_complete()
def do_find():
res = ele.page.run_cdp('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
if 'exceptionDetails' in res:
raise SyntaxError(f'查询语句错误:\n{res}')
if res['result']['subtype'] == 'null' or res['result']['description'] in ('NodeList(0)', 'Array(0)'):
return None
if single:
r = make_chromium_ele(ele.page, obj_id=res['result']['objectId'])
return None if r is False else r
else:
node_ids = [i['value']['objectId'] for i in ele.page.run_cdp('Runtime.getProperties',
objectId=res['result']['objectId'],
ownProperties=True)['result'][:-1]]
r = make_chromium_eles(ele.page, obj_ids=node_ids, single=False, ele_only=False)
return None if r is False else r
end_time = perf_counter() + timeout
while ('exceptionDetails' in r or r['result']['subtype'] == 'null' or
r['result']['description'] in ('NodeList(0)', 'Array(0)')) and perf_counter() < end_time:
r = ele.page.run_cdp_loaded('Runtime.callFunctionOn', functionDeclaration=js, objectId=ele._obj_id,
returnByValue=False, awaitPromise=True, userGesture=True)
result = do_find()
while result is None and perf_counter() < end_time:
sleep(.1)
result = do_find()
if 'exceptionDetails' in r:
raise SyntaxError(f'查询语句错误:\n{r}')
if single:
return NoneElement(ele.page) if r['result']['subtype'] == 'null' \
else make_chromium_ele(ele.page, obj_id=r['result']['objectId'])
if r['result']['description'] in ('NodeList(0)', 'Array(0)'):
return []
else:
r = ele.page.run_cdp_loaded('Runtime.getProperties', objectId=r['result']['objectId'],
ownProperties=True)['result']
return [make_chromium_ele(ele.page, obj_id=i['value']['objectId']) for i in r]
if result:
return result
return NoneElement(ele.page) if single else []
def make_chromium_ele(page, node_id=None, obj_id=None):
@ -1201,18 +1227,24 @@ def make_chromium_ele(page, node_id=None, obj_id=None):
:param page: ChromiumPage对象
:param node_id: 元素的node id
:param obj_id: 元素的object id
:return: ChromiumElement对象或ChromiumFrame对象
:return: ChromiumElement对象或ChromiumFrame对象生成失败返回False
"""
if node_id:
node = page.run_cdp('DOM.describeNode', nodeId=node_id)
node = page.driver.run('DOM.describeNode', nodeId=node_id)
if 'error' in node:
return False
if node['node']['nodeName'] in ('#text', '#comment'):
# todo: Node()
return node['node']['nodeValue']
backend_id = node['node']['backendNodeId']
obj_id = page.run_cdp('DOM.resolveNode', nodeId=node_id)['object']['objectId']
if 'error' in obj_id:
return False
elif obj_id:
node = page.run_cdp('DOM.describeNode', objectId=obj_id)
node = page.driver.run('DOM.describeNode', objectId=obj_id)
if 'error' in node:
return False
if node['node']['nodeName'] in ('#text', '#comment'):
# todo: Node()
return node['node']['nodeValue']
@ -1220,12 +1252,12 @@ def make_chromium_ele(page, node_id=None, obj_id=None):
node_id = node['node']['nodeId']
else:
raise ElementLostError
return False
ele = ChromiumElement(page, obj_id=obj_id, node_id=node_id, backend_id=backend_id)
if ele.tag in __FRAME_ELEMENT__:
from .._pages.chromium_frame import ChromiumFrame
ele = ChromiumFrame(page, ele)
ele = ChromiumFrame(page, ele, node)
return ele
@ -1237,14 +1269,16 @@ def make_chromium_eles(page, node_ids=None, obj_ids=None, single=True, ele_only=
:param obj_ids: 元素的object id
:param single: 是否获取但个元素
:param ele_only: 是否只要ele
:return: ChromiumElement对象或ChromiumFrame对象
:return: ChromiumElement对象或ChromiumFrame对象生成失败返回False
"""
nodes = []
if node_ids:
for node_id in node_ids:
if not node_id:
return False
node = page.run_cdp('DOM.describeNode', nodeId=node_id)
node = page.driver.run('DOM.describeNode', nodeId=node_id)
if 'error' in node:
return False
if node['node']['nodeName'] in ('#text', '#comment'):
if ele_only:
continue
@ -1254,11 +1288,14 @@ def make_chromium_eles(page, node_ids=None, obj_ids=None, single=True, ele_only=
else:
nodes.append(node['node']['nodeValue'])
obj_id = page.run_cdp('DOM.resolveNode', nodeId=node_id)['object']['objectId']
obj_id = page.driver.run('DOM.resolveNode', nodeId=node_id)
if 'error' in obj_id:
return False
obj_id = obj_id['object']['objectId']
ele = ChromiumElement(page, obj_id=obj_id, node_id=node_id, backend_id=node['node']['backendNodeId'])
if ele.tag in __FRAME_ELEMENT__:
from .._pages.chromium_frame import ChromiumFrame
ele = ChromiumFrame(page, ele)
ele = ChromiumFrame(page, ele, node)
if single:
return ele
nodes.append(ele)
@ -1267,7 +1304,9 @@ def make_chromium_eles(page, node_ids=None, obj_ids=None, single=True, ele_only=
for obj_id in obj_ids:
if not obj_id:
return False
node = page.run_cdp('DOM.describeNode', objectId=obj_id)
node = page.driver.run('DOM.describeNode', objectId=obj_id)
if 'error' in node:
return False
if node['node']['nodeName'] in ('#text', '#comment'):
if ele_only:
continue
@ -1281,7 +1320,7 @@ def make_chromium_eles(page, node_ids=None, obj_ids=None, single=True, ele_only=
backend_id=node['node']['backendNodeId'])
if ele.tag in __FRAME_ELEMENT__:
from .._pages.chromium_frame import ChromiumFrame
ele = ChromiumFrame(page, ele)
ele = ChromiumFrame(page, ele, node)
if single:
return ele
nodes.append(ele)
@ -1336,7 +1375,7 @@ def run_js(page_or_ele, script, as_expr=False, timeout=None, args=None):
:param page_or_ele: 页面对象或元素对象
:param script: js文本
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: 超时时间
:param timeout: 超时时间
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:return: js执行结果
"""
@ -1409,16 +1448,17 @@ def parse_js_result(page, ele, result):
elif class_name == 'HTMLDocument':
return result
else:
return make_chromium_eles(page, obj_ids=(result['objectId'],))
r = make_chromium_ele(page, obj_id=result['objectId'])
if r is False:
raise ElementLostError
return r
elif sub_type == 'array':
r = page.run_cdp('Runtime.getProperties', objectId=result['objectId'],
ownProperties=True)['result']
r = page.run_cdp('Runtime.getProperties', objectId=result['objectId'], ownProperties=True)['result']
return [parse_js_result(page, ele, result=i['value']) for i in r[:-1]]
elif 'objectId' in result and result['className'].lower() == 'object': # dict
r = page.run_cdp('Runtime.getProperties', objectId=result['objectId'],
ownProperties=True)['result']
r = page.run_cdp('Runtime.getProperties', objectId=result['objectId'], ownProperties=True)['result']
return {i['name']: parse_js_result(page, ele, result=i['value']) for i in r}
else:

View File

@ -99,19 +99,19 @@ class ChromiumElement(DrissionElement):
def child(self,
filter_loc: Union[tuple, str, int] = '',
index: int = 1,
timeout: float = 0,
timeout: float = None,
ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ...
def prev(self,
filter_loc: Union[tuple, str, int] = '',
index: int = 1,
timeout: float = 0,
timeout: float = None,
ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ...
def next(self,
filter_loc: Union[tuple, str, int] = '',
index: int = 1,
timeout: float = 0,
timeout: float = None,
ele_only: bool = True) -> Union[ChromiumElement, str, NoneElement]: ...
def before(self,
@ -128,17 +128,17 @@ class ChromiumElement(DrissionElement):
def children(self,
filter_loc: Union[tuple, str] = '',
timeout: float = 0,
timeout: float = None,
ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ...
def prevs(self,
filter_loc: Union[tuple, str] = '',
timeout: float = 0,
timeout: float = None,
ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ...
def nexts(self,
filter_loc: Union[tuple, str] = '',
timeout: float = 0,
timeout: float = None,
ele_only: bool = True) -> List[Union[ChromiumElement, str]]: ...
def befores(self,
@ -315,12 +315,12 @@ def find_by_css(ele: ChromiumElement, selector: str, single: bool,
timeout: float) -> Union[ChromiumElement, List[ChromiumElement], NoneElement]: ...
def make_chromium_ele(page: Union[ChromiumPage, WebPage, ChromiumTab, ChromiumFrame],
def make_chromium_ele(page: Union[ChromiumBase, ChromiumPage, WebPage, ChromiumTab, ChromiumFrame],
node_id: int = ...,
obj_id: str = ...) -> Union[ChromiumElement, ChromiumFrame, str]: ...
def make_chromium_eles(page: Union[ChromiumPage, WebPage, ChromiumTab, ChromiumFrame],
def make_chromium_eles(page: Union[ChromiumBase, ChromiumPage, WebPage, ChromiumTab, ChromiumFrame],
node_ids: Union[tuple, list] = None,
obj_ids: Union[tuple, list] = None,
single: bool = True,

View File

@ -194,7 +194,7 @@ def test_connect(ip, port, timeout=30):
"""测试浏览器是否可用
:param ip: 浏览器ip
:param port: 浏览器端口
:param timeout: 超时时间
:param timeout: 超时时间
:return: None
"""
end_time = perf_counter() + timeout

View File

@ -419,7 +419,7 @@ def send_key(page, modifier, key):
'unmodifiedText': text,
'location': description['location'],
'isKeypad': description['location'] == 3,
'_ignore': AlertExistsError, '_timeout': 1}
'_ignore': AlertExistsError}
page.run_cdp('Input.dispatchKeyEvent', **data)
data['type'] = 'keyUp'

View File

@ -192,7 +192,7 @@ def wait_until(page, condition, timeout=10, poll=0.1, raise_err=True):
"""等待返回值不为False或空直到超时
:param page: DrissionPage对象
:param condition: 等待条件返回值不为False则停止等待
:param timeout: 超时时间
:param timeout: 超时时间
:param poll: 轮询间隔
:param raise_err: 是否抛出异常
:return: DP Element or bool
@ -267,7 +267,7 @@ def raise_error(result, ignore=None):
'No node with given id found', 'Node with given id does not belong to the document',
'No node found for given backend id'):
r = ElementLostError()
elif error in ('tab closed', 'No target with given id found'):
elif error in ('page closed', 'No target with given id found'):
r = PageClosedError()
elif error == 'timeout':
r = TimeoutError(f'超时。\n错误:{result["error"]}\nmethod{result["method"]}\nargs{result["args"]}\n'

View File

@ -38,7 +38,7 @@ class ChromiumBase(BasePage):
"""
:param address: 浏览器 ip:port
:param tab_id: 要控制的标签页id不指定默认为激活的
:param timeout: 超时时间
:param timeout: 超时时间
"""
super().__init__()
self._is_loading = None
@ -147,7 +147,7 @@ class ChromiumBase(BasePage):
def _get_document(self, timeout=10):
"""获取页面文档
:param timeout: 超时时间
:param timeout: 超时时间
:return: 是否获取成功
"""
if self._debug:
@ -282,7 +282,7 @@ class ChromiumBase(BasePage):
"""在内部查找元素
ele = page('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:param timeout: 超时时间
:return: ChromiumElement对象
"""
return self.ele(loc_or_str, timeout)
@ -468,7 +468,7 @@ class ChromiumBase(BasePage):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: 运行的结果
"""
return run_js(self, script, as_expr, self.timeouts.script if timeout is None else timeout, args)
@ -478,7 +478,7 @@ class ChromiumBase(BasePage):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: 运行的结果
"""
self.wait.load_complete()
@ -489,7 +489,7 @@ class ChromiumBase(BasePage):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: None
"""
from threading import Thread
@ -502,7 +502,7 @@ class ChromiumBase(BasePage):
:param show_errmsg: 是否显示和抛出异常
:param retry: 重试次数
:param interval: 重试间隔
:param timeout: 连接超时时间
:param timeout: 连接超时时间
:return: 目标url是否可用
"""
retry, interval = self._before_connect(url, retry, interval)
@ -531,7 +531,7 @@ class ChromiumBase(BasePage):
def ele(self, loc_or_ele, timeout=None):
"""获取第一个符合条件的元素对象
:param loc_or_ele: 定位符或元素对象
:param timeout: 查找超时时间
:param timeout: 查找超时时间
:return: ChromiumElement对象
"""
return self._ele(loc_or_ele, timeout=timeout, method='ele()')
@ -539,7 +539,7 @@ class ChromiumBase(BasePage):
def eles(self, loc_or_str, timeout=None):
"""获取所有符合条件的元素对象
:param loc_or_str: 定位符或元素对象
:param timeout: 查找超时时间
:param timeout: 查找超时时间
:return: ChromiumElement对象组成的列表
"""
return self._ele(loc_or_str, timeout=timeout, single=False)
@ -568,7 +568,7 @@ class ChromiumBase(BasePage):
def _find_elements(self, loc_or_ele, timeout=None, single=True, relative=False, raise_err=None):
"""执行元素查找
:param loc_or_ele: 定位符或元素对象
:param timeout: 查找超时时间
:param timeout: 查找超时时间
:param single: 是否只返回第一个
:param relative: WebPage用的表示是否相对定位的参数
:param raise_err: 找不到元素是是否抛出异常为None时根据全局设置
@ -581,56 +581,39 @@ class ChromiumBase(BasePage):
else:
raise ValueError('loc_or_str参数只能是tuple、str、ChromiumElement类型。')
ok = False
nodeIds = None
self.wait.load_complete()
timeout = timeout if timeout is not None else self.timeout
end_time = perf_counter() + timeout
search_ids = []
try:
search_result = self.run_cdp_loaded('DOM.performSearch', query=loc, _timeout=timeout,
includeUserAgentShadowDOM=True)
count = search_result['resultCount']
search_ids.append(search_result['searchId'])
except ContextLostError:
search_result = None
count = 0
timeout = .5 if timeout <= 0 else timeout
result = self.driver.run('DOM.performSearch', query=loc, _timeout=timeout, includeUserAgentShadowDOM=True)
if not result or __ERROR__ in result:
num = 0
else:
num = result['resultCount']
search_ids.append(result['searchId'])
while True:
if count > 0:
count = 1 if single else count
try:
nodeIds = self.run_cdp_loaded('DOM.getSearchResults', searchId=search_result['searchId'],
fromIndex=0, toIndex=count)
if nodeIds['nodeIds'][0] != 0:
ok = True
except Exception:
pass
if ok:
r = make_chromium_eles(self, node_ids=nodeIds['nodeIds'], single=single)
if r is not False:
break
else:
ok = False
try:
timeout = end_time - perf_counter()
if timeout <= 0:
timeout = .5
search_result = self.run_cdp_loaded('DOM.performSearch', query=loc, _timeout=timeout,
includeUserAgentShadowDOM=True)
count = search_result['resultCount']
search_ids.append(search_result['searchId'])
except ContextLostError:
pass
if num > 0:
num = 1 if single else num
nIds = self._driver.run('DOM.getSearchResults', searchId=result['searchId'], fromIndex=0, toIndex=num)
if __ERROR__ not in nIds:
if nIds['nodeIds'][0] != 0:
r = make_chromium_eles(self, node_ids=nIds['nodeIds'], single=single)
if r is not False:
break
if perf_counter() >= end_time:
return NoneElement(self) if single else []
sleep(.1)
timeout = end_time - perf_counter()
timeout = .5 if timeout <= 0 else timeout
result = self.driver.run('DOM.performSearch', query=loc, _timeout=timeout, includeUserAgentShadowDOM=True)
if not result or __ERROR__ not in result:
num = result['resultCount']
search_ids.append(result['searchId'])
for _id in search_ids:
self._driver.run('DOM.discardSearchResults', searchId=_id)
@ -712,7 +695,7 @@ class ChromiumBase(BasePage):
def get_frame(self, loc_ind_ele, timeout=None):
"""获取页面中一个frame对象可传入定位符、iframe序号、ChromiumFrame对象序号从1开始
:param loc_ind_ele: 定位符iframe序号ChromiumFrame对象
:param timeout: 查找元素超时时间
:param timeout: 查找元素超时时间
:return: ChromiumFrame对象
"""
if isinstance(loc_ind_ele, str):
@ -752,7 +735,7 @@ class ChromiumBase(BasePage):
def get_frames(self, loc=None, timeout=None):
"""获取所有符合条件的frame对象
:param loc: 定位符为None时返回所有
:param timeout: 查找超时时间
:param timeout: 查找超时时间
:return: ChromiumFrame对象组成的列表
"""
loc = loc or 'xpath://*[name()="iframe" or name()="frame"]'
@ -839,6 +822,11 @@ class ChromiumBase(BasePage):
if cookies:
self.run_cdp_loaded('Network.clearBrowserCookies')
def disconnect(self):
"""断开与页面的连接,不关闭页面"""
if self._driver:
self.driver.stop()
def handle_alert(self, accept=True, send=None, timeout=None, next_one=False):
r = self._handle_alert(accept=accept, send=send, timeout=timeout, next_one=next_one)
while self._has_alert:
@ -849,7 +837,7 @@ class ChromiumBase(BasePage):
"""处理提示框,可以自动等待提示框出现
:param accept: True表示确认False表示取消其它值不会按按钮但依然返回文本值
:param send: 处理prompt提示框时可输入文本
:param timeout: 等待提示框出现的超时时间为None则使用self.timeout属性的值
:param timeout: 等待提示框出现的超时时间为None则使用self.timeout属性的值
:param next_one: 是否处理下一个出现的提示框为True时timeout参数无效
:return: 提示框内容文本未等到提示框则返回False
"""
@ -901,12 +889,9 @@ class ChromiumBase(BasePage):
def _wait_loaded(self, timeout=None):
"""等待页面加载完成,超时触发停止加载
:param timeout: 超时时间
:param timeout: 超时时间
:return: 是否成功超时返回False
"""
if self._load_mode == 'none':
return True
timeout = timeout if timeout is not None else self.timeouts.page_load
end_time = perf_counter() + timeout
while perf_counter() < end_time:
@ -948,10 +933,11 @@ class ChromiumBase(BasePage):
:param times: 重试次数
:param interval: 重试间隔
:param show_errmsg: 是否抛出异常
:param timeout: 连接超时时间
:param timeout: 连接超时时间
:return: 是否成功返回None表示不确定
"""
err = None
self._is_loading = True
timeout = timeout if timeout is not None else self.timeouts.page_load
for t in range(times + 1):
err = None

View File

@ -224,6 +224,8 @@ class ChromiumBase(BasePage):
def clear_cache(self, session_storage: bool = True, local_storage: bool = True, cache: bool = True,
cookies: bool = True) -> None: ...
def disconnect(self) -> None: ...
def handle_alert(self, accept: bool = True, send: str = None, timeout: float = None,
next_one: bool = False) -> Union[str, False]: ...

View File

@ -19,10 +19,11 @@ from ..errors import ContextLostError, ElementLostError, GetDocumentError, PageC
class ChromiumFrame(ChromiumBase):
def __init__(self, page, ele):
def __init__(self, page, ele, info=None):
"""
:param page: frame所在的页面对象
:param ele: frame所在元素
:param info: frame所在元素信息
"""
page_type = str(type(page))
if 'ChromiumPage' in page_type or 'WebPage' in page_type:
@ -41,7 +42,7 @@ class ChromiumFrame(ChromiumBase):
self._states = None
self._reloading = False
node = page.run_cdp('DOM.describeNode', backendNodeId=ele._backend_id)['node']
node = info['node'] if not info else page.run_cdp('DOM.describeNode', backendNodeId=ele._backend_id)['node']
self._frame_id = node['frameId']
if self._is_inner_frame():
self._is_diff_domain = False
@ -65,7 +66,7 @@ class ChromiumFrame(ChromiumBase):
"""在内部查找元素
ele2 = ele1('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:param timeout: 超时时间
:return: ChromiumElement对象或属性文本
"""
return self.ele(loc_or_str, timeout)
@ -159,7 +160,7 @@ class ChromiumFrame(ChromiumBase):
def _get_document(self, timeout=10):
"""刷新cdp使用的document数据
:param timeout: 超时时间
:param timeout: 超时时间
:return: 是否获取成功
"""
if self._is_reading:
@ -392,7 +393,7 @@ class ChromiumFrame(ChromiumBase):
:param script: js文本
:param args: 参数按顺序在js文本中对应arguments[0]arguments[1]...
:param as_expr: 是否作为表达式运行为True时args无效
:param timeout: js超时时间为None则使用页面timeouts.script设置
:param timeout: js超时时间为None则使用页面timeouts.script设置
:return: 运行的结果
"""
if script.startswith('this.scrollIntoView'):
@ -412,7 +413,7 @@ class ChromiumFrame(ChromiumBase):
"""返回当前元素前面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 前面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 同级元素或节点
"""
@ -422,7 +423,7 @@ class ChromiumFrame(ChromiumBase):
"""返回当前元素后面一个符合条件的同级元素,可用查询语法筛选,可指定返回筛选结果的第几个
:param filter_loc: 用于筛选的查询语法
:param index: 后面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 同级元素或节点
"""
@ -433,7 +434,7 @@ class ChromiumFrame(ChromiumBase):
查找范围不限同级元素而是整个DOM文档
:param filter_loc: 用于筛选的查询语法
:param index: 前面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素前面的某个元素或节点
"""
@ -444,7 +445,7 @@ class ChromiumFrame(ChromiumBase):
查找范围不限同级元素而是整个DOM文档
:param filter_loc: 用于筛选的查询语法
:param index: 后面第几个查询结果1开始
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 本元素后面的某个元素或节点
"""
@ -453,7 +454,7 @@ class ChromiumFrame(ChromiumBase):
def prevs(self, filter_loc='', timeout=0, ele_only=True):
"""返回当前元素前面符合条件的同级元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 同级元素或节点文本组成的列表
"""
@ -462,7 +463,7 @@ class ChromiumFrame(ChromiumBase):
def nexts(self, filter_loc='', timeout=0, ele_only=True):
"""返回当前元素后面符合条件的同级元素或节点组成的列表,可用查询语法筛选
:param filter_loc: 用于筛选的查询语法
:param timeout: 查找节点的超时时间
:param timeout: 查找节点的超时时间
:param ele_only: 是否只获取元素为False时把文本注释节点也纳入
:return: 同级元素或节点文本组成的列表
"""

View File

@ -24,7 +24,8 @@ class ChromiumFrame(ChromiumBase):
def __init__(self,
page: Union[ChromiumPage, WebPage, ChromiumTab, ChromiumFrame],
ele: ChromiumElement):
ele: ChromiumElement,
info: dict = None):
self._page: ChromiumPage = ...
self._target_page: ChromiumBase = ...
self.tab: ChromiumTab = ...

View File

@ -25,7 +25,7 @@ class ChromiumPage(ChromiumBase):
"""
:param addr_or_opts: 浏览器地址:端口ChromiumOptions对象或端口数字int
:param tab_id: 要控制的标签页id不指定默认为激活的
:param timeout: 超时时间
:param timeout: 超时时间
"""
addr_or_opts = addr_or_opts or addr_driver_opts
self._page = self
@ -242,7 +242,7 @@ class ChromiumPage(ChromiumBase):
def quit(self, timeout=5, force=True):
"""关闭浏览器
:param timeout: 等待浏览器关闭超时时间
:param timeout: 等待浏览器关闭超时时间
:param force: 关闭超时是否强制终止进程
:return: None
"""

View File

@ -79,7 +79,7 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage):
"""在内部查找元素
ele = page('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:param timeout: 超时时间
:return: 子元素对象
"""
if self._mode == 'd':
@ -221,7 +221,7 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage):
def ele(self, loc_or_ele, timeout=None):
"""返回第一个符合条件的元素、属性或节点文本
:param loc_or_ele: 元素的定位信息可以是元素对象loc元组或查询字符串
:param timeout: 查找元素超时时间默认与页面等待时间一致
:param timeout: 查找元素超时时间默认与页面等待时间一致
:return: 元素对象或属性文本节点文本
"""
if self._mode == 's':
@ -232,7 +232,7 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage):
def eles(self, loc_or_str, timeout=None):
"""返回页面中所有符合条件的元素、属性或节点文本
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与页面等待时间一致
:param timeout: 查找元素超时时间默认与页面等待时间一致
:return: 元素对象或属性文本组成的列表
"""
if self._mode == 's':
@ -345,7 +345,7 @@ class WebPageTab(SessionPage, ChromiumTab, BasePage):
def _find_elements(self, loc_or_ele, timeout=None, single=True, relative=False, raise_err=None):
"""返回页面中符合条件的元素、属性或节点文本,默认返回第一个
:param loc_or_ele: 元素的定位信息可以是元素对象loc元组或查询字符串
:param timeout: 查找元素超时时间d模式专用
:param timeout: 查找元素超时时间d模式专用
:param single: True则返回第一个False则返回全部
:param relative: WebPage用的表示是否相对定位的参数
:param raise_err: 找不到元素是是否抛出异常为None时根据全局设置

View File

@ -25,7 +25,7 @@ class SessionPage(BasePage):
def __init__(self, session_or_options=None, timeout=None):
"""
:param session_or_options: Session对象或SessionOptions对象
:param timeout: 连接超时时间为None时从ini文件读取
:param timeout: 连接超时时间为None时从ini文件读取
"""
super(SessionPage, SessionPage).__init__(self)
self._headers = None

View File

@ -18,7 +18,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
def __init__(self, mode='d', timeout=None, chromium_options=None, session_or_options=None, driver_or_options=None):
"""初始化函数
:param mode: 'd' 's'即driver模式和session模式
:param timeout: 超时时间d模式时为寻找元素时间s模式时为连接时间默认10秒
:param timeout: 超时时间d模式时为寻找元素时间s模式时为连接时间默认10秒
:param chromium_options: Driver对象只使用s模式时应传入False
:param session_or_options: Session对象或SessionOptions对象只使用d模式时应传入False
"""
@ -40,7 +40,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
"""在内部查找元素
ele = page('@id=ele_id')
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 超时时间
:param timeout: 超时时间
:return: 子元素对象
"""
if self._mode == 'd':
@ -182,7 +182,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
def ele(self, loc_or_ele, timeout=None):
"""返回第一个符合条件的元素、属性或节点文本
:param loc_or_ele: 元素的定位信息可以是元素对象loc元组或查询字符串
:param timeout: 查找元素超时时间默认与页面等待时间一致
:param timeout: 查找元素超时时间默认与页面等待时间一致
:return: 元素对象或属性文本节点文本
"""
if self._mode == 's':
@ -193,7 +193,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
def eles(self, loc_or_str, timeout=None):
"""返回页面中所有符合条件的元素、属性或节点文本
:param loc_or_str: 元素的定位信息可以是loc元组或查询字符串
:param timeout: 查找元素超时时间默认与页面等待时间一致
:param timeout: 查找元素超时时间默认与页面等待时间一致
:return: 元素对象或属性文本组成的列表
"""
if self._mode == 's':

View File

@ -252,7 +252,6 @@ class Actions:
return self
data = self._get_key_data(key, 'keyDown')
data['_timeout'] = 1
data['_ignore'] = AlertExistsError
self.page.run_cdp('Input.dispatchKeyEvent', **data)
return self
@ -268,7 +267,6 @@ class Actions:
return self
data = self._get_key_data(key, 'keyUp')
data['_timeout'] = 1
data['_ignore'] = AlertExistsError
self.page.run_cdp('Input.dispatchKeyEvent', **data)
return self

View File

@ -21,7 +21,7 @@ class Clicker(object):
"""点击元素
如果遇到遮挡可选择是否用js点击
:param by_js: 是否用js点击为None时先用模拟点击遇到遮挡改用js为True时直接用js点击为False时只用模拟点击
:param timeout: 模拟点击的超时时间等待元素可见可用进入视口
:param timeout: 模拟点击的超时时间等待元素可见可用进入视口
:param wait_stop: 是否等待元素运动结束再执行点击
:return: 是否点击成功
"""
@ -30,7 +30,7 @@ class Clicker(object):
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 timeout: 模拟点击的超时时间等待元素可见可用进入视口
:param wait_stop: 是否等待元素运动结束再执行点击
:return: 是否点击成功
"""