diff --git a/DrissionPage/__init__.py b/DrissionPage/__init__.py index b4bb936..a4ee172 100644 --- a/DrissionPage/__init__.py +++ b/DrissionPage/__init__.py @@ -14,4 +14,4 @@ from ._pages.chromium_page import ChromiumPage from ._pages.mix_page import MixPage from ._pages.mix_page import MixPage as WebPage -__version__ = '4.1.0.0b15' +__version__ = '4.1.0.0b16' diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index d04785b..f99dafb 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -25,6 +25,7 @@ from .._functions.settings import Settings from .._functions.tools import raise_error from .._functions.web import location_in_viewport from .._units.actions import Actions +from .._units.console import Console from .._units.listener import Listener from .._units.rect import TabRect from .._units.screencast import Screencast @@ -58,6 +59,7 @@ class ChromiumBase(BasePage): self._rect = None self._wait = None self._scroll = None + self._console = None self._upload_list = None self._doc_got = False # 用于在LoadEventFired和FrameStoppedLoading间标记是否已获取doc self._download_path = None @@ -314,6 +316,13 @@ class ChromiumBase(BasePage): self._rect = TabRect(self) return self._rect + @property + def console(self): + """返回获取控制台信息的对象""" + if self._console is None: + self._console = Console(self) + return self._console + @property def timeout(self): """返回timeout设置""" diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index 2ab5fb2..aa2cf48 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -19,6 +19,7 @@ from .._functions.elements import SessionElementsList, ChromiumElementsList from .._pages.chromium_frame import ChromiumFrame from .._pages.chromium_page import ChromiumPage from .._units.actions import Actions +from .._units.console import Console from .._units.listener import Listener from .._units.rect import TabRect from .._units.screencast import Screencast @@ -61,6 +62,7 @@ class ChromiumBase(BasePage): self._init_jss: list = ... self._ready_state: Optional[str] = ... self._rect: TabRect = ... + self._console: Console = ... self._type: str = ... def _connect_browser(self, target_id: str = None) -> None: ... @@ -143,6 +145,9 @@ class ChromiumBase(BasePage): @property def rect(self) -> TabRect: ... + @property + def console(self) -> Console: ... + @property def timeout(self) -> float: ... diff --git a/DrissionPage/_pages/chromium_frame.py b/DrissionPage/_pages/chromium_frame.py index 95117d4..2a50d7f 100644 --- a/DrissionPage/_pages/chromium_frame.py +++ b/DrissionPage/_pages/chromium_frame.py @@ -37,6 +37,7 @@ class ChromiumFrame(ChromiumBase): sleep(.1) return r r = object.__new__(cls) + r._frame_id = node['frameId'] cls._Frames[node['frameId']] = r return r @@ -53,7 +54,6 @@ class ChromiumFrame(ChromiumBase): self._reloading = False node = info['node'] if info else owner._run_cdp('DOM.describeNode', backendNodeId=ele._backend_id)['node'] - self._frame_id = node['frameId'] if self._is_inner_frame(): self._is_diff_domain = False self.doc_ele = ChromiumElement(self._target_page, backend_id=node['contentDocument']['backendNodeId']) @@ -195,6 +195,8 @@ class ChromiumFrame(ChromiumBase): """同域变异域""" self.browser._frames.pop(kwargs['frameId'], None) ChromiumFrame._Frames.pop(kwargs['frameId'], None) + while not hasattr(self, '_frame_id'): + sleep(.1) if kwargs['frameId'] == self._frame_id: self._reload() diff --git a/DrissionPage/_pages/mix_page.py b/DrissionPage/_pages/mix_page.py index e4e834c..24f9295 100644 --- a/DrissionPage/_pages/mix_page.py +++ b/DrissionPage/_pages/mix_page.py @@ -375,10 +375,11 @@ class MixPage(SessionPage, ChromiumPage, BasePage): elif self._mode == 'd': return super(SessionPage, self)._find_elements(locator, timeout=timeout, index=index, relative=relative) - def quit(self, timeout=5, force=True): + def quit(self, timeout=5, force=True, del_data=False): """关闭浏览器和Session :param timeout: 等待浏览器关闭超时时间(秒) :param force: 关闭超时是否强制终止进程 + :param del_data: 是否删除用户文件夹 :return: None """ if self._has_session: @@ -387,7 +388,7 @@ class MixPage(SessionPage, ChromiumPage, BasePage): self._response = None self._has_session = None if self._has_driver: - super(SessionPage, self).quit(timeout, force) + super(SessionPage, self).quit(timeout, force, del_data=del_data) self._driver = None self._has_driver = None diff --git a/DrissionPage/_pages/mix_page.pyi b/DrissionPage/_pages/mix_page.pyi index 7d335da..727a155 100644 --- a/DrissionPage/_pages/mix_page.pyi +++ b/DrissionPage/_pages/mix_page.pyi @@ -188,4 +188,4 @@ class MixPage(SessionPage, ChromiumPage, BasePage): dr_opt: Union[Driver, bool, None], se_opt: Union[Session, SessionOptions, bool, None]) -> None: ... - def quit(self, timeout: float = 5, force: bool = True) -> None: ... + def quit(self, timeout: float = 5, force: bool = True, del_data: bool = False) -> None: ... diff --git a/DrissionPage/_units/console.py b/DrissionPage/_units/console.py new file mode 100644 index 0000000..5dba0a5 --- /dev/null +++ b/DrissionPage/_units/console.py @@ -0,0 +1,61 @@ +# -*- coding:utf-8 -*- +from queue import Queue +from time import perf_counter, sleep + + +class Console(object): + def __init__(self, owner): + self.owner = owner + self.listening = False + self._caught = None + + @property + def messages(self): + if self._caught is None: + return [] + lst = [] + while not self._caught.empty(): + lst.append(self._caught.get_nowait()) + return lst + + def start(self): + self._caught = Queue(maxsize=0) + self.owner._driver.set_callback("Console.messageAdded", self._console) + self.owner._run_cdp("Console.enable") + self.listening = True + + def stop(self): + if self.listening: + self.owner._run_cdp("Console.disable") + self.owner._driver.set_callback('Console.messageAdded', None) + self.listening = False + + def clear(self): + self._caught = Queue(maxsize=0) + + def steps(self, timeout=None): + end = perf_counter() + timeout if timeout else None + while self.owner._driver.is_running: + if timeout and perf_counter() > end: + return + if self._caught.qsize(): + yield self._caught.get_nowait() + sleep(0.05) + + def _console(self, **kwargs): + self._caught.put(ConsoleData(kwargs['message'])) + + +class ConsoleData(object): + __slots__ = ('_data', 'source', 'level', 'text', 'url', 'line', 'column') + + def __init__(self, data): + self._data = data + + def __getattr__(self, item): + """获取属性""" + return self._data.get(item, None) + + def __repr__(self): + return (f'') diff --git a/DrissionPage/_units/console.pyi b/DrissionPage/_units/console.pyi new file mode 100644 index 0000000..56a82bb --- /dev/null +++ b/DrissionPage/_units/console.pyi @@ -0,0 +1,45 @@ +# -*- coding:utf-8 -*- +from queue import Queue +from typing import Optional, Iterable, List + +from .._pages.chromium_base import ChromiumBase + + +class Console(object): + listening: bool = ... + owner: ChromiumBase = ... + _caught: Optional[Queue] = ... + + def __init__(self, owner: ChromiumBase) -> None: ... + + @property + def messages(self) -> List[ConsoleData]: ... + + def start(self) -> None: + """开启console监听""" + ... + + def stop(self) -> None: + """停止监听,清空已监听到的列表""" + ... + + def clear(self) -> None: + """清空已获取但未返回的信息""" + ... + + def steps(self, timeout: Optional[float] = None) -> Iterable[ConsoleData]: + """每监听到一个信息就返回,用于for循环 + :param timeout: 等待一个信息的超时时间,为None无限等待 + :return: None + """ + ... + + def _console(self, **kwargs) -> None: ... + + +class ConsoleData(object): + __slots__ = ('_data', 'source', 'level', 'text', 'url', 'line', 'column') + + def __init__(self, data: dict) -> None: ... + + def __getattr__(self, item: str) -> str: ... diff --git a/DrissionPage/_units/listener.py b/DrissionPage/_units/listener.py index 0166e15..a12f144 100644 --- a/DrissionPage/_units/listener.py +++ b/DrissionPage/_units/listener.py @@ -168,7 +168,7 @@ class Listener(object): caught = 0 end = perf_counter() + timeout if timeout else None while self._driver.is_running: - if (timeout and perf_counter() > end) or not self._driver.is_running: + if timeout and perf_counter() > end: return if self._caught.qsize() >= gap: yield self._caught.get_nowait() if gap == 1 else [self._caught.get_nowait() for _ in range(gap)] diff --git a/README.md b/README.md index 95698a4..b44f3cb 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ DrissionPage 是一个基于 python 的网页自动化工具。 --- -官方网站:[https://drissionpage.cn](https://drissionpage.cn) +官方网站:[https://DrissionPage.cn](https://drissionpage.cn) star fork @@ -32,7 +32,7 @@ python 版本:3.6 及以上 # 🛠 如何使用 -**📖 使用文档:** [点击查看](https://g1879.gitee.io/drissionpagedocs) +**📖 使用文档:** [点击查看](https://DrissionPage.cn) **交流 QQ 群:** 636361957 @@ -55,27 +55,27 @@ python 版本:3.6 及以上 - 不基于 webdriver - 无需为不同版本的浏览器下载不同的驱动 - 运行速度更快 -- 可以跨`