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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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