ChromiumDirver删除GenericAttr

This commit is contained in:
g1879 2023-07-24 15:42:43 +08:00
parent 0845814dc5
commit cbc9367127
7 changed files with 23 additions and 51 deletions

View File

@ -103,14 +103,14 @@ class ChromiumBase(BasePage):
self._tab_obj = ChromiumDriver(tab_id=tab_id, tab_type='page', address=self.address) self._tab_obj = ChromiumDriver(tab_id=tab_id, tab_type='page', address=self.address)
self._tab_obj.start() self._tab_obj.start()
self._tab_obj.DOM.enable() self._tab_obj.call_method('DOM.enable')
self._tab_obj.Page.enable() self._tab_obj.call_method('Page.enable')
self._tab_obj.Page.frameStoppedLoading = self._onFrameStoppedLoading self._tab_obj.set_listener('Page.frameStoppedLoading', self._onFrameStoppedLoading)
self._tab_obj.Page.frameStartedLoading = self._onFrameStartedLoading self._tab_obj.set_listener('Page.frameStartedLoading', self._onFrameStartedLoading)
self._tab_obj.DOM.documentUpdated = self._onDocumentUpdated self._tab_obj.set_listener('DOM.documentUpdated', self._onDocumentUpdated)
self._tab_obj.Page.loadEventFired = self._onLoadEventFired self._tab_obj.set_listener('Page.loadEventFired', self._onLoadEventFired)
self._tab_obj.Page.frameNavigated = self._onFrameNavigated self._tab_obj.set_listener('Page.frameNavigated', self._onFrameNavigated)
def _get_document(self): def _get_document(self):
"""刷新cdp使用的document数据""" """刷新cdp使用的document数据"""
@ -238,7 +238,7 @@ class ChromiumBase(BasePage):
files = self._upload_list if kwargs['mode'] == 'selectMultiple' else self._upload_list[:1] files = self._upload_list if kwargs['mode'] == 'selectMultiple' else self._upload_list[:1]
self.run_cdp('DOM.setFileInputFiles', files=files, backendNodeId=kwargs['backendNodeId']) 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.run_cdp('Page.setInterceptFileChooserDialog', enabled=False)
self._upload_list = None self._upload_list = None
@ -972,7 +972,7 @@ class Screencast(object):
raise ValueError('save_path必须设置。') raise ValueError('save_path必须设置。')
clean_folder(self._path) clean_folder(self._path)
if self._mode.startswith('frugal'): 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) self._page.run_cdp('Page.startScreencast', everyNthFrame=1, quality=100)
elif not self._mode.startswith('js'): elif not self._mode.startswith('js'):
@ -1029,7 +1029,7 @@ class Screencast(object):
return path return path
if self._mode.startswith('frugal'): 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') self._page.run_cdp('Page.stopScreencast')
else: else:
self._enable = False self._enable = False

View File

@ -3,7 +3,6 @@
@Author : g1879 @Author : g1879
@Contact : g1879@qq.com @Contact : g1879@qq.com
""" """
from functools import partial
from json import dumps, loads from json import dumps, loads
from queue import Queue, Empty from queue import Queue, Empty
from threading import Thread, Event from threading import Thread, Event
@ -11,26 +10,6 @@ from threading import Thread, Event
from websocket import WebSocketTimeoutException, WebSocketException, WebSocketConnectionClosedException, \ from websocket import WebSocketTimeoutException, WebSocketException, WebSocketConnectionClosedException, \
create_connection 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): class ChromiumDriver(object):
_INITIAL_ = 'initial' _INITIAL_ = 'initial'
@ -167,12 +146,7 @@ class ChromiumDriver(object):
self.event_queue.task_done() self.event_queue.task_done()
def __getattr__(self, item): def call_method(self, _method, **kwargs):
attr = GenericAttr(item, self)
setattr(self, item, attr)
return attr
def call_method(self, _method, *args, **kwargs):
"""执行cdp方法 """执行cdp方法
:param _method: cdp方法名 :param _method: cdp方法名
:param args: cdp参数 :param args: cdp参数
@ -182,8 +156,6 @@ class ChromiumDriver(object):
if not self._started: if not self._started:
self.start() self.start()
# raise RuntimeError("不能在启动前调用方法。") # raise RuntimeError("不能在启动前调用方法。")
if args:
raise CDPError("参数必须是key=value形式。")
if self._stopped.is_set(): if self._stopped.is_set():
return {'error': 'tab closed', 'type': 'tab_closed'} return {'error': 'tab closed', 'type': 'tab_closed'}

View File

@ -47,7 +47,7 @@ class ChromiumDriver(object):
def __getattr__(self, item: str) -> Callable: ... 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: ... def start(self) -> bool: ...

View File

@ -95,8 +95,8 @@ class ChromiumPage(ChromiumBase):
self._browser_driver.start() self._browser_driver.start()
self._alert = Alert() self._alert = Alert()
self._tab_obj.Page.javascriptDialogOpening = self._on_alert_open self._tab_obj.set_listener('Page.javascriptDialogOpening', self._on_alert_open)
self._tab_obj.Page.javascriptDialogClosed = self._on_alert_close self._tab_obj.set_listener('Page.javascriptDialogClosed', self._on_alert_close)
self._rect = None self._rect = None
self._main_tab = self.tab_id self._main_tab = self.tab_id
@ -106,7 +106,7 @@ class ChromiumPage(ChromiumBase):
# pass # pass
self._process_id = None self._process_id = None
r = self.browser_driver.SystemInfo.getProcessInfo() r = self.browser_driver.call_method('SystemInfo.getProcessInfo')
if 'processInfo' not in r: if 'processInfo' not in r:
return None return None
for i in r['processInfo']: for i in r['processInfo']:
@ -329,14 +329,14 @@ class ChromiumPage(ChromiumBase):
res_text = self._alert.text res_text = self._alert.text
if self._alert.type == 'prompt': if self._alert.type == 'prompt':
self.driver.Page.handleJavaScriptDialog(accept=accept, promptText=send) self.driver.call_method('Page.handleJavaScriptDialog', accept=accept, promptText=send)
else: else:
self.driver.Page.handleJavaScriptDialog(accept=accept) self.driver.call_method('Page.handleJavaScriptDialog', accept=accept)
return res_text return res_text
def quit(self): def quit(self):
"""关闭浏览器""" """关闭浏览器"""
self._tab_obj.Browser.close() self._tab_obj.call_method('Browser.close')
self._tab_obj.stop() self._tab_obj.stop()
ip, port = self.address.split(':') ip, port = self.address.split(':')
while port_is_using(ip, port): while port_is_using(ip, port):
@ -431,7 +431,7 @@ class ChromiumTabRect(object):
def _get_browser_rect(self): 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): # class BaseDownloadSetter(DownloadSetter):

View File

@ -101,7 +101,7 @@ class ChromiumBaseSetter(object):
:return: None :return: None
""" """
if not self._page._upload_list: 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) self._page.run_cdp('Page.setInterceptFileChooserDialog', enabled=True)
if isinstance(files, str): if isinstance(files, str):

View File

@ -382,7 +382,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
if self._has_driver: if self._has_driver:
self.change_mode('s') self.change_mode('s')
try: try:
self.driver.Browser.close() self.driver.call_method('Browser.close')
except Exception: except Exception:
pass pass
self._tab_obj.stop() self._tab_obj.stop()
@ -421,7 +421,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage):
self._response = None self._response = None
self._has_session = None self._has_session = None
if self._has_driver: if self._has_driver:
self._tab_obj.Browser.close() self._tab_obj.call_method('Browser.close')
self._tab_obj.stop() self._tab_obj.stop()
self._tab_obj = None self._tab_obj = None
self._has_driver = None self._has_driver = None

View File

@ -45,7 +45,7 @@ python 版本3.6 及以上
用 requests 做数据采集面对要登录的网站时要分析数据包、JS 源码构造复杂的请求往往还要应付验证码、JS 混淆、签名参数等反爬手段,门槛较高,开发效率不高。 用 requests 做数据采集面对要登录的网站时要分析数据包、JS 源码构造复杂的请求往往还要应付验证码、JS 混淆、签名参数等反爬手段,门槛较高,开发效率不高。
使用浏览器,可以很大程度上绕过这些坑,但浏览器运行效率不高。 使用浏览器,可以很大程度上绕过这些坑,但浏览器运行效率不高。
因此,这个库设计初衷,是将它们合而为一,同时实现“写得快”和“跑得快”。能够在不同要时切换相应模式,并提供一种人性化的使用方法,提高开发和运行效率。 因此,这个库设计初衷,是将它们合而为一,同时实现“写得快”和“跑得快”。能够在不同要时切换相应模式,并提供一种人性化的使用方法,提高开发和运行效率。
除了合并两者,本库还以网页为单位封装了常用功能,提供非常简便的操作和语句,使用户可减少考虑细节,专注功能实现。 以简单的方式实现强大的功能,使代码更优雅。 除了合并两者,本库还以网页为单位封装了常用功能,提供非常简便的操作和语句,使用户可减少考虑细节,专注功能实现。 以简单的方式实现强大的功能,使代码更优雅。
以前的版本是对 selenium 进行重新封装实现的。从 3.0 开始,作者另起炉灶,对底层进行了重新开发,摆脱对 selenium 的依赖,增强了功能,提升了运行效率。 以前的版本是对 selenium 进行重新封装实现的。从 3.0 开始,作者另起炉灶,对底层进行了重新开发,摆脱对 selenium 的依赖,增强了功能,提升了运行效率。