From 1aeda01d94989c59cf4d99eedadd03400101adb6 Mon Sep 17 00:00:00 2001 From: g1879 Date: Wed, 29 Mar 2023 18:44:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0wait.stop=5Flistening()?= =?UTF-8?q?=EF=BC=9Bwait.data=5Fpackets()=E5=8F=AF=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E7=9B=AE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/chromium_base.py | 98 +++++++++++++++++++++++++-------- DrissionPage/chromium_base.pyi | 15 +++-- DrissionPage/chromium_driver.py | 6 +- setup.py | 2 +- 4 files changed, 87 insertions(+), 34 deletions(-) diff --git a/DrissionPage/chromium_base.py b/DrissionPage/chromium_base.py index d565679..eba28cc 100644 --- a/DrissionPage/chromium_base.py +++ b/DrissionPage/chromium_base.py @@ -1027,6 +1027,8 @@ class ChromiumBaseWaiter(object): :param page_or_ele: 页面对象或元素对象 """ self._driver = page_or_ele + self._response = None + self._request_id = None def ele_delete(self, loc_or_ele, timeout=None): """等待元素从DOM中删除 @@ -1092,51 +1094,99 @@ class ChromiumBaseWaiter(object): sleep(gap) return False - def set_target(self, target): + def set_targets(self, targets): """指定要等待的数据包 - :param target: + :param targets: 指定的数据包url片段,可传入多个 :return: None """ - self._target = target + if not isinstance(targets, (str, list, tuple, set)): + raise TypeError('targets只能是str、list、tuple、set。') + self._targets = targets if isinstance(targets, str) else set(targets) self._driver.run_cdp('Network.enable') - self._driver.driver.Network.responseReceived = self._response_received - self._driver.driver.Network.loadingFinished = self._loading_finished + if targets: + self._driver.driver.Network.responseReceived = self._response_received + self._driver.driver.Network.loadingFinished = self._loading_finished + else: + self.stop_listening() - def data_packet(self, target=None, timeout=None): + def stop_listening(self): + """停止监听数据包""" + self._driver.driver.Network.responseReceived = None + self._driver.driver.Network.loadingFinished = None + + def data_packets(self, targets=None, timeout=None, any_target=False): """等待指定数据包加载完成 - :param target: 指定的数据包url片段 + :param targets: 指定的数据包url片段,可传入多个 :param timeout: 超时时间,为None则使用页面对象timeout + :param any_target: 多个target时,是否全部监听到才结束,为True时监听到一个目标就结束 :return: ResponseData对象 """ - if target: - self._target = target + if targets and not isinstance(targets, (str, list, tuple, set)): + raise TypeError('targets只能是str、list、tuple、set。') + if targets: + self._targets = targets if isinstance(targets, str) else set(targets) self._request_id = None - self._response_data = None + self._response_result = None timeout = timeout if timeout is not None else self._driver.timeout end_time = perf_counter() + timeout - while not self._response_data and perf_counter() < end_time: - sleep(.1) + if isinstance(self._targets, str): + while not self._response_result and perf_counter() < end_time: + sleep(.1) + + else: + while perf_counter() < end_time: + if self._response_result and (any_target or set(self._response_result) == self._targets): + break + sleep(.1) self._request_id = None - - return self._response_data or False + return self._response_result or False def _response_received(self, **kwargs): """接收到返回信息时处理方法""" - if self._target in kwargs['response']['url']: - self._request_id = kwargs['requestId'] - self._response = kwargs['response'] + if isinstance(self._targets, str): + if self._targets in kwargs['response']['url']: + self._request_id = kwargs['requestId'] + self._response = kwargs['response'] + + else: + if not self._response: + self._response = {} + if not self._request_id: + self._request_id = {} + + for target in self._targets: + if target in kwargs['response']['url']: + self._response[target] = kwargs['response'] + self._request_id[kwargs['requestId']] = target def _loading_finished(self, **kwargs): """请求完成时处理方法""" - if kwargs['requestId'] == self._request_id: - try: - body = self._driver.run_cdp('Network.getResponseBody', requestId=self._request_id)['body'] - except: - body = '' - self._response_data = ResponseData(self._request_id, self._response, body, - self._driver.tab_id, self._target) + if isinstance(self._targets, str): + if kwargs['requestId'] == self._request_id: + try: + body = self._driver.run_cdp('Network.getResponseBody', requestId=self._request_id)['body'] + except: + body = '' + self._response_result = ResponseData(self._request_id, self._response, body, + self._driver.tab_id, self._targets) + + else: + if self._request_id and kwargs['requestId'] in self._request_id: + if not self._response_result: + self._response_result = {} + + try: + body = self._driver.run_cdp('Network.getResponseBody', requestId=self._request_id)['body'] + except: + body = '' + + target = self._request_id[kwargs['requestId']] + self._response_result[self._request_id[kwargs['requestId']]] = ResponseData(kwargs['requestId'], + self._response[target], + body, self._driver.tab_id, + target) class ChromiumPageScroll(ChromiumScroll): diff --git a/DrissionPage/chromium_base.pyi b/DrissionPage/chromium_base.pyi index f2e52b8..2b2e577 100644 --- a/DrissionPage/chromium_base.pyi +++ b/DrissionPage/chromium_base.pyi @@ -4,7 +4,7 @@ @Contact : g1879@qq.com """ from pathlib import Path -from typing import Union, Tuple, List, Any +from typing import Union, Tuple, List, Any, Dict from DataRecorder import Recorder from FlowViewer.listener import ResponseData @@ -217,10 +217,10 @@ class ChromiumBase(BasePage): class ChromiumBaseWaiter(object): def __init__(self, page: ChromiumBase): self._driver: ChromiumBase = ... - self._target: str = ... - self._request_id: str = ... + self._targets: Union[str, dict] = ... + self._request_id: Union[str, dict] = ... self._response: dict = ... - self._response_data: ResponseData = ... + self._response_result: Union[ResponseData, List[ResponseData], False] = ... def ele_delete(self, loc_or_ele: Union[str, tuple, ChromiumElement], timeout: float = None) -> bool: ... @@ -234,9 +234,12 @@ class ChromiumBaseWaiter(object): def load_complete(self, timeout: float = None) -> bool: ... - def set_target(self, target: str) -> None: ... + def set_targets(self, target: Union[str, list, tuple, set]) -> None: ... - def data_packet(self, target: str = None, timeout: float = None) -> Union[ResponseData, None]: ... + def stop_listening(self) -> None: ... + + def data_packets(self, target: Union[str, list, tuple, set] = None, timeout: float = None, + any_target: bool = False) -> Union[ResponseData, Dict[str, ResponseData], False]: ... def _response_received(self, **kwargs): ... diff --git a/DrissionPage/chromium_driver.py b/DrissionPage/chromium_driver.py index e2ae33f..a207bf6 100644 --- a/DrissionPage/chromium_driver.py +++ b/DrissionPage/chromium_driver.py @@ -149,9 +149,9 @@ class ChromiumDriver(object): if event['method'] in self.event_handlers: try: self.event_handlers[event['method']](**event['params']) - except Exception: - pass - # raise RuntimeError(f"\n回调函数 {self.event_handlers[event['method']].__name__} 错误:\n{e}") + except Exception as e: + # pass + raise RuntimeError(f"\n回调函数 {self.event_handlers[event['method']].__name__} 错误:\n{e}") self.event_queue.task_done() diff --git a/setup.py b/setup.py index 2518924..317e11a 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh: setup( name="DrissionPage", - version="3.2.19", + version="3.2.20", author="g1879", author_email="g1879@qq.com", description="Python based web automation tool. It can control the browser and send and receive data packets.",