diff --git a/DrissionPage/chromium_base.py b/DrissionPage/chromium_base.py index a77e9f1..839ddf9 100644 --- a/DrissionPage/chromium_base.py +++ b/DrissionPage/chromium_base.py @@ -103,14 +103,14 @@ class ChromiumBase(BasePage): self._tab_obj = ChromiumDriver(tab_id=tab_id, tab_type='page', address=self.address) self._tab_obj.start() - self._tab_obj.DOM.enable() - self._tab_obj.Page.enable() + self._tab_obj.call_method('DOM.enable') + self._tab_obj.call_method('Page.enable') - self._tab_obj.Page.frameStoppedLoading = self._onFrameStoppedLoading - self._tab_obj.Page.frameStartedLoading = self._onFrameStartedLoading - self._tab_obj.DOM.documentUpdated = self._onDocumentUpdated - self._tab_obj.Page.loadEventFired = self._onLoadEventFired - self._tab_obj.Page.frameNavigated = self._onFrameNavigated + self._tab_obj.set_listener('Page.frameStoppedLoading', self._onFrameStoppedLoading) + self._tab_obj.set_listener('Page.frameStartedLoading', self._onFrameStartedLoading) + self._tab_obj.set_listener('DOM.documentUpdated', self._onDocumentUpdated) + self._tab_obj.set_listener('Page.loadEventFired', self._onLoadEventFired) + self._tab_obj.set_listener('Page.frameNavigated', self._onFrameNavigated) def _get_document(self): """刷新cdp使用的document数据""" @@ -238,7 +238,7 @@ class ChromiumBase(BasePage): files = self._upload_list if kwargs['mode'] == 'selectMultiple' else self._upload_list[:1] self.run_cdp('DOM.setFileInputFiles', files=files, backendNodeId=kwargs['backendNodeId']) - self.driver.Page.fileChooserOpened = None + self.driver.set_listener('Page.fileChooserOpened', None) self.run_cdp('Page.setInterceptFileChooserDialog', enabled=False) self._upload_list = None @@ -972,7 +972,7 @@ class Screencast(object): raise ValueError('save_path必须设置。') clean_folder(self._path) if self._mode.startswith('frugal'): - self._page.driver.Page.screencastFrame = self._onScreencastFrame + self._page.driver.set_listener('Page.screencastFrame', self._onScreencastFrame) self._page.run_cdp('Page.startScreencast', everyNthFrame=1, quality=100) elif not self._mode.startswith('js'): @@ -1029,7 +1029,7 @@ class Screencast(object): return path if self._mode.startswith('frugal'): - self._page.driver.Page.screencastFrame = None + self._page.driver.set_listener('Page.screencastFrame', None) self._page.run_cdp('Page.stopScreencast') else: self._enable = False diff --git a/DrissionPage/chromium_driver.py b/DrissionPage/chromium_driver.py index 9d053f3..09e9cbf 100644 --- a/DrissionPage/chromium_driver.py +++ b/DrissionPage/chromium_driver.py @@ -3,7 +3,6 @@ @Author : g1879 @Contact : g1879@qq.com """ -from functools import partial from json import dumps, loads from queue import Queue, Empty from threading import Thread, Event @@ -11,26 +10,6 @@ from threading import Thread, Event from websocket import WebSocketTimeoutException, WebSocketException, WebSocketConnectionClosedException, \ create_connection -from .errors import CDPError - - -class GenericAttr(object): - def __init__(self, name, tab): - self.__dict__['name'] = name - self.__dict__['tab'] = tab - - def __getattr__(self, item): - method_name = f"{self.name}.{item}" - event_listener = self.tab.get_listener(method_name) - - if event_listener: - return event_listener - - return partial(self.tab.call_method, method_name) - - def __setattr__(self, key, value): - self.tab.set_listener(f"{self.name}.{key}", value) - class ChromiumDriver(object): _INITIAL_ = 'initial' @@ -167,12 +146,7 @@ class ChromiumDriver(object): self.event_queue.task_done() - def __getattr__(self, item): - attr = GenericAttr(item, self) - setattr(self, item, attr) - return attr - - def call_method(self, _method, *args, **kwargs): + def call_method(self, _method, **kwargs): """执行cdp方法 :param _method: cdp方法名 :param args: cdp参数 @@ -182,8 +156,6 @@ class ChromiumDriver(object): if not self._started: self.start() # raise RuntimeError("不能在启动前调用方法。") - if args: - raise CDPError("参数必须是key=value形式。") if self._stopped.is_set(): return {'error': 'tab closed', 'type': 'tab_closed'} diff --git a/DrissionPage/chromium_driver.pyi b/DrissionPage/chromium_driver.pyi index df1bf9e..0c63041 100644 --- a/DrissionPage/chromium_driver.pyi +++ b/DrissionPage/chromium_driver.pyi @@ -47,7 +47,7 @@ class ChromiumDriver(object): def __getattr__(self, item: str) -> Callable: ... - def call_method(self, _method: str, *args, **kwargs) -> dict: ... + def call_method(self, _method: str, **kwargs) -> dict: ... def start(self) -> bool: ... diff --git a/DrissionPage/chromium_page.py b/DrissionPage/chromium_page.py index 4903560..936243e 100644 --- a/DrissionPage/chromium_page.py +++ b/DrissionPage/chromium_page.py @@ -95,8 +95,8 @@ class ChromiumPage(ChromiumBase): self._browser_driver.start() self._alert = Alert() - self._tab_obj.Page.javascriptDialogOpening = self._on_alert_open - self._tab_obj.Page.javascriptDialogClosed = self._on_alert_close + self._tab_obj.set_listener('Page.javascriptDialogOpening', self._on_alert_open) + self._tab_obj.set_listener('Page.javascriptDialogClosed', self._on_alert_close) self._rect = None self._main_tab = self.tab_id @@ -106,7 +106,7 @@ class ChromiumPage(ChromiumBase): # pass self._process_id = None - r = self.browser_driver.SystemInfo.getProcessInfo() + r = self.browser_driver.call_method('SystemInfo.getProcessInfo') if 'processInfo' not in r: return None for i in r['processInfo']: @@ -329,14 +329,14 @@ class ChromiumPage(ChromiumBase): res_text = self._alert.text if self._alert.type == 'prompt': - self.driver.Page.handleJavaScriptDialog(accept=accept, promptText=send) + self.driver.call_method('Page.handleJavaScriptDialog', accept=accept, promptText=send) else: - self.driver.Page.handleJavaScriptDialog(accept=accept) + self.driver.call_method('Page.handleJavaScriptDialog', accept=accept) return res_text def quit(self): """关闭浏览器""" - self._tab_obj.Browser.close() + self._tab_obj.call_method('Browser.close') self._tab_obj.stop() ip, port = self.address.split(':') while port_is_using(ip, port): @@ -431,7 +431,7 @@ class ChromiumTabRect(object): def _get_browser_rect(self): """获取浏览器范围信息""" - return self._page.browser_driver.Browser.getWindowForTarget(targetId=self._page.tab_id)['bounds'] + return self._page.browser_driver.call_method('Browser.getWindowForTarget', targetId=self._page.tab_id)['bounds'] # class BaseDownloadSetter(DownloadSetter): diff --git a/DrissionPage/setter.py b/DrissionPage/setter.py index 754bd32..1faeaa2 100644 --- a/DrissionPage/setter.py +++ b/DrissionPage/setter.py @@ -101,7 +101,7 @@ class ChromiumBaseSetter(object): :return: None """ if not self._page._upload_list: - self._page.driver.Page.fileChooserOpened = self._page._onFileChooserOpened + self._page.driver.set_listener('Page.fileChooserOpened', self._page._onFileChooserOpened) self._page.run_cdp('Page.setInterceptFileChooserDialog', enabled=True) if isinstance(files, str): diff --git a/DrissionPage/web_page.py b/DrissionPage/web_page.py index e85bdca..b36b09c 100644 --- a/DrissionPage/web_page.py +++ b/DrissionPage/web_page.py @@ -382,7 +382,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): if self._has_driver: self.change_mode('s') try: - self.driver.Browser.close() + self.driver.call_method('Browser.close') except Exception: pass self._tab_obj.stop() @@ -421,7 +421,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): self._response = None self._has_session = None if self._has_driver: - self._tab_obj.Browser.close() + self._tab_obj.call_method('Browser.close') self._tab_obj.stop() self._tab_obj = None self._has_driver = None diff --git a/README.md b/README.md index b94e27e..0c1b297 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ python 版本:3.6 及以上 用 requests 做数据采集面对要登录的网站时,要分析数据包、JS 源码,构造复杂的请求,往往还要应付验证码、JS 混淆、签名参数等反爬手段,门槛较高,开发效率不高。 使用浏览器,可以很大程度上绕过这些坑,但浏览器运行效率不高。 -因此,这个库设计初衷,是将它们合而为一,同时实现“写得快”和“跑得快”。能够在不同须要时切换相应模式,并提供一种人性化的使用方法,提高开发和运行效率。 +因此,这个库设计初衷,是将它们合而为一,同时实现“写得快”和“跑得快”。能够在不同需要时切换相应模式,并提供一种人性化的使用方法,提高开发和运行效率。 除了合并两者,本库还以网页为单位封装了常用功能,提供非常简便的操作和语句,使用户可减少考虑细节,专注功能实现。 以简单的方式实现强大的功能,使代码更优雅。 以前的版本是对 selenium 进行重新封装实现的。从 3.0 开始,作者另起炉灶,对底层进行了重新开发,摆脱对 selenium 的依赖,增强了功能,提升了运行效率。