mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
优化waiter,待测试;修复某些情况下获取不到sr里的元素问题;优化css_path;Driver的_stopped改为is_running
This commit is contained in:
parent
2dd44d1982
commit
982dee6246
@ -14,4 +14,4 @@ from ._pages.chromium_page import ChromiumPage
|
|||||||
from ._pages.mix_page import MixPage
|
from ._pages.mix_page import MixPage
|
||||||
from ._pages.mix_page import MixPage as WebPage
|
from ._pages.mix_page import MixPage as WebPage
|
||||||
|
|
||||||
__version__ = '4.1.0.0b10'
|
__version__ = '4.1.0.0b11'
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"""
|
"""
|
||||||
from json import dumps, loads, JSONDecodeError
|
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
|
||||||
from time import perf_counter, sleep
|
from time import perf_counter, sleep
|
||||||
|
|
||||||
from requests import Session
|
from requests import Session
|
||||||
@ -44,7 +44,7 @@ class Driver(object):
|
|||||||
self._handle_event_th.daemon = True
|
self._handle_event_th.daemon = True
|
||||||
self._handle_immediate_event_th = None
|
self._handle_immediate_event_th = None
|
||||||
|
|
||||||
self._stopped = Event()
|
self.is_running = False
|
||||||
|
|
||||||
self.event_handlers = {}
|
self.event_handlers = {}
|
||||||
self.immediate_event_handlers = {}
|
self.immediate_event_handlers = {}
|
||||||
@ -87,7 +87,7 @@ class Driver(object):
|
|||||||
self.method_results.pop(ws_id, None)
|
self.method_results.pop(ws_id, None)
|
||||||
return {'error': {'message': 'connection disconnected'}, 'type': 'connection_error'}
|
return {'error': {'message': 'connection disconnected'}, 'type': 'connection_error'}
|
||||||
|
|
||||||
while not self._stopped.is_set():
|
while self.is_running:
|
||||||
try:
|
try:
|
||||||
result = self.method_results[ws_id].get(timeout=.2)
|
result = self.method_results[ws_id].get(timeout=.2)
|
||||||
self.method_results.pop(ws_id, None)
|
self.method_results.pop(ws_id, None)
|
||||||
@ -108,7 +108,7 @@ class Driver(object):
|
|||||||
|
|
||||||
def _recv_loop(self):
|
def _recv_loop(self):
|
||||||
"""接收浏览器信息的守护线程方法"""
|
"""接收浏览器信息的守护线程方法"""
|
||||||
while not self._stopped.is_set():
|
while self.is_running:
|
||||||
try:
|
try:
|
||||||
# self._ws.settimeout(1)
|
# self._ws.settimeout(1)
|
||||||
msg_json = self._ws.recv()
|
msg_json = self._ws.recv()
|
||||||
@ -146,7 +146,7 @@ class Driver(object):
|
|||||||
|
|
||||||
def _handle_event_loop(self):
|
def _handle_event_loop(self):
|
||||||
"""当接收到浏览器信息,执行已绑定的方法"""
|
"""当接收到浏览器信息,执行已绑定的方法"""
|
||||||
while not self._stopped.is_set():
|
while self.is_running:
|
||||||
try:
|
try:
|
||||||
event = self.event_queue.get(timeout=1)
|
event = self.event_queue.get(timeout=1)
|
||||||
except Empty:
|
except Empty:
|
||||||
@ -184,7 +184,7 @@ class Driver(object):
|
|||||||
:param kwargs: cdp参数
|
:param kwargs: cdp参数
|
||||||
:return: 执行结果
|
:return: 执行结果
|
||||||
"""
|
"""
|
||||||
if self._stopped.is_set():
|
if not self.is_running:
|
||||||
return {'error': 'connection disconnected', 'type': 'connection_error'}
|
return {'error': 'connection disconnected', 'type': 'connection_error'}
|
||||||
|
|
||||||
timeout = kwargs.pop('_timeout', Settings.cdp_timeout)
|
timeout = kwargs.pop('_timeout', Settings.cdp_timeout)
|
||||||
@ -198,7 +198,7 @@ class Driver(object):
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""启动连接"""
|
"""启动连接"""
|
||||||
self._stopped.clear()
|
self.is_running = True
|
||||||
try:
|
try:
|
||||||
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)
|
||||||
except WebSocketBadStatusException as e:
|
except WebSocketBadStatusException as e:
|
||||||
@ -221,10 +221,10 @@ class Driver(object):
|
|||||||
|
|
||||||
def _stop(self):
|
def _stop(self):
|
||||||
"""中断连接"""
|
"""中断连接"""
|
||||||
if self._stopped.is_set():
|
if not self.is_running:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self._stopped.set()
|
self.is_running = False
|
||||||
if self._ws:
|
if self._ws:
|
||||||
self._ws.close()
|
self._ws.close()
|
||||||
self._ws = None
|
self._ws = None
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
@License : BSD 3-Clause.
|
@License : BSD 3-Clause.
|
||||||
"""
|
"""
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from threading import Thread, Event
|
from threading import Thread
|
||||||
from typing import Union, Callable, Dict, Optional
|
from typing import Union, Callable, Dict, Optional
|
||||||
|
|
||||||
from requests import Response, Session
|
from requests import Response, Session
|
||||||
@ -35,7 +35,8 @@ class Driver(object):
|
|||||||
_recv_th: Thread
|
_recv_th: Thread
|
||||||
_handle_event_th: Thread
|
_handle_event_th: Thread
|
||||||
_handle_immediate_event_th: Optional[Thread]
|
_handle_immediate_event_th: Optional[Thread]
|
||||||
_stopped: Event
|
# _stopped: Event
|
||||||
|
is_running: bool
|
||||||
event_handlers: dict
|
event_handlers: dict
|
||||||
immediate_event_handlers: dict
|
immediate_event_handlers: dict
|
||||||
method_results: dict
|
method_results: dict
|
||||||
|
@ -903,7 +903,11 @@ class ChromiumElement(DrissionElement):
|
|||||||
txt5 = '''return path;'''
|
txt5 = '''return path;'''
|
||||||
|
|
||||||
elif mode == 'css':
|
elif mode == 'css':
|
||||||
txt1 = ''
|
txt1 = '''
|
||||||
|
let i = el.getAttribute("id");
|
||||||
|
if (i){path = '>' + el.tagName.toLowerCase() + "#" + i + path;
|
||||||
|
break;}
|
||||||
|
'''
|
||||||
txt3 = ''
|
txt3 = ''
|
||||||
txt4 = '''path = '>' + el.tagName.toLowerCase() + ":nth-child(" + nth + ")" + path;'''
|
txt4 = '''path = '>' + el.tagName.toLowerCase() + ":nth-child(" + nth + ")" + path;'''
|
||||||
txt5 = '''return path.substr(1);'''
|
txt5 = '''return path.substr(1);'''
|
||||||
@ -913,6 +917,7 @@ class ChromiumElement(DrissionElement):
|
|||||||
|
|
||||||
js = '''function(){
|
js = '''function(){
|
||||||
function e(el) {
|
function e(el) {
|
||||||
|
//return el;
|
||||||
if (!(el instanceof Element)) return;
|
if (!(el instanceof Element)) return;
|
||||||
let path = '';
|
let path = '';
|
||||||
while (el.nodeType === Node.ELEMENT_NODE) {
|
while (el.nodeType === Node.ELEMENT_NODE) {
|
||||||
@ -1243,7 +1248,12 @@ class ShadowRoot(BaseElement):
|
|||||||
if not eles:
|
if not eles:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
css = [i.css_path[61:] for i in eles]
|
css = []
|
||||||
|
for i in eles:
|
||||||
|
c = i.css_path
|
||||||
|
if c.startswith('html:nth-child(1)>body:nth-child(1)>shadow_root:nth-child(1)'):
|
||||||
|
c = c[61:]
|
||||||
|
css.append(c)
|
||||||
if index is not None:
|
if index is not None:
|
||||||
try:
|
try:
|
||||||
node_id = self.owner._run_cdp('DOM.querySelector', nodeId=self._node_id,
|
node_id = self.owner._run_cdp('DOM.querySelector', nodeId=self._node_id,
|
||||||
|
@ -276,6 +276,10 @@ class SessionElement(DrissionElement):
|
|||||||
|
|
||||||
while ele:
|
while ele:
|
||||||
if mode == 'css':
|
if mode == 'css':
|
||||||
|
id_ = ele.attr('id')
|
||||||
|
if id_:
|
||||||
|
path_str = f'>{ele.tag}#{id_}{path_str}'
|
||||||
|
break
|
||||||
brothers = len(ele.eles(f'xpath:./preceding-sibling::*'))
|
brothers = len(ele.eles(f'xpath:./preceding-sibling::*'))
|
||||||
path_str = f'>{ele.tag}:nth-child({brothers + 1}){path_str}'
|
path_str = f'>{ele.tag}:nth-child({brothers + 1}){path_str}'
|
||||||
else:
|
else:
|
||||||
|
@ -374,7 +374,7 @@ class ChromiumBase(BasePage):
|
|||||||
@property
|
@property
|
||||||
def _target_id(self):
|
def _target_id(self):
|
||||||
"""返回当前标签页id"""
|
"""返回当前标签页id"""
|
||||||
return self.driver.id if not self.driver._stopped.is_set() else ''
|
return self.driver.id if self.driver.is_running else ''
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_ele(self):
|
def active_ele(self):
|
||||||
|
@ -127,13 +127,13 @@ class Listener(object):
|
|||||||
if not self.listening:
|
if not self.listening:
|
||||||
raise RuntimeError('监听未启动或已暂停。')
|
raise RuntimeError('监听未启动或已暂停。')
|
||||||
if not timeout:
|
if not timeout:
|
||||||
while self._caught.qsize() < count:
|
while self._driver.is_running and self._caught.qsize() < count:
|
||||||
sleep(.03)
|
sleep(.03)
|
||||||
fail = False
|
fail = False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
end = perf_counter() + timeout
|
end = perf_counter() + timeout
|
||||||
while True:
|
while self._driver.is_running:
|
||||||
if perf_counter() > end:
|
if perf_counter() > end:
|
||||||
fail = True
|
fail = True
|
||||||
break
|
break
|
||||||
@ -167,8 +167,8 @@ class Listener(object):
|
|||||||
raise RuntimeError('监听未启动或已暂停。')
|
raise RuntimeError('监听未启动或已暂停。')
|
||||||
caught = 0
|
caught = 0
|
||||||
end = perf_counter() + timeout if timeout else None
|
end = perf_counter() + timeout if timeout else None
|
||||||
while True:
|
while self._driver.is_running:
|
||||||
if (timeout and perf_counter() > end) or self._driver._stopped.is_set():
|
if (timeout and perf_counter() > end) or not self._driver.is_running:
|
||||||
return
|
return
|
||||||
if self._caught.qsize() >= gap:
|
if self._caught.qsize() >= gap:
|
||||||
yield self._caught.get_nowait() if gap == 1 else [self._caught.get_nowait() for _ in range(gap)]
|
yield self._caught.get_nowait() if gap == 1 else [self._caught.get_nowait() for _ in range(gap)]
|
||||||
|
@ -285,18 +285,26 @@ class BaseWaiter(OriginWaiter):
|
|||||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||||
:return: 是否等待成功
|
:return: 是否等待成功
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def do():
|
||||||
|
if arg == 'url':
|
||||||
|
v = self._owner.url
|
||||||
|
elif arg == 'title':
|
||||||
|
v = self._owner.title
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
if (not exclude and text in v) or (exclude and text not in v):
|
||||||
|
return True
|
||||||
|
|
||||||
|
if do():
|
||||||
|
return True
|
||||||
|
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self._owner.timeout
|
timeout = self._owner.timeout
|
||||||
|
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
while perf_counter() < end_time:
|
while perf_counter() < end_time:
|
||||||
if arg == 'url':
|
if do():
|
||||||
val = self._owner.url
|
|
||||||
elif arg == 'title':
|
|
||||||
val = self._owner.title
|
|
||||||
else:
|
|
||||||
raise ValueError
|
|
||||||
if (not exclude and text in val) or (exclude and text not in val):
|
|
||||||
return True
|
return True
|
||||||
sleep(.05)
|
sleep(.05)
|
||||||
|
|
||||||
@ -313,9 +321,8 @@ class BaseWaiter(OriginWaiter):
|
|||||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||||
:return: 是否等待成功
|
:return: 是否等待成功
|
||||||
"""
|
"""
|
||||||
if timeout != 0:
|
timeout = timeout if timeout is not None else self._owner.timeout
|
||||||
if timeout is None or timeout is True:
|
timeout = .1 if timeout <= 0 else timeout
|
||||||
timeout = self._owner.timeout
|
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
while perf_counter() < end_time:
|
while perf_counter() < end_time:
|
||||||
if self._owner._is_loading == start:
|
if self._owner._is_loading == start:
|
||||||
@ -461,6 +468,9 @@ class ElementWaiter(OriginWaiter):
|
|||||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||||
:return: 成功返回元素对象,失败返回False
|
:return: 成功返回元素对象,失败返回False
|
||||||
"""
|
"""
|
||||||
|
if not self._ele.states.is_enabled or not self._ele.states.is_alive:
|
||||||
|
return self._ele
|
||||||
|
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self._timeout
|
timeout = self._timeout
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
@ -483,6 +493,9 @@ class ElementWaiter(OriginWaiter):
|
|||||||
"""
|
"""
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self._timeout
|
timeout = self._timeout
|
||||||
|
if timeout <= 0:
|
||||||
|
timeout = .1
|
||||||
|
|
||||||
end_time = perf_counter() + timeout
|
end_time = perf_counter() + timeout
|
||||||
while perf_counter() < end_time:
|
while perf_counter() < end_time:
|
||||||
try:
|
try:
|
||||||
@ -514,9 +527,10 @@ class ElementWaiter(OriginWaiter):
|
|||||||
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
:param raise_err: 等待失败时是否报错,为None时根据Settings设置
|
||||||
:return: 成功返回元素对象,失败返回False
|
:return: 成功返回元素对象,失败返回False
|
||||||
"""
|
"""
|
||||||
|
timeout = timeout if timeout is not None else self._timeout
|
||||||
t1 = perf_counter()
|
t1 = perf_counter()
|
||||||
r = self._wait_state('is_clickable', True, timeout, raise_err, err_text='等待元素可点击失败(等{}秒)。')
|
r = self._wait_state('is_clickable', True, timeout, raise_err, err_text='等待元素可点击失败(等{}秒)。')
|
||||||
r = self.stop_moving(timeout=perf_counter() - t1) if wait_moved and r else r
|
r = self.stop_moving(timeout=timeout - perf_counter() + t1) if wait_moved and r else r
|
||||||
if raise_err and not r:
|
if raise_err and not r:
|
||||||
raise WaitTimeoutError(f'等待元素可点击失败(等{timeout}秒)。')
|
raise WaitTimeoutError(f'等待元素可点击失败(等{timeout}秒)。')
|
||||||
return r
|
return r
|
||||||
|
Loading…
x
Reference in New Issue
Block a user