自动关闭浏览器启动时的隐私声明

This commit is contained in:
g1879 2023-11-12 22:56:52 +08:00
parent 89e1b3a29f
commit 27bea5f579
11 changed files with 97 additions and 69 deletions

View File

@ -51,8 +51,8 @@ class Browser(object):
break break
self.run_cdp('Target.setDiscoverTargets', discover=True) self.run_cdp('Target.setDiscoverTargets', discover=True)
self._driver.set_listener('Target.targetDestroyed', self._onTargetDestroyed) self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed)
self._driver.set_listener('Target.targetCreated', self._onTargetCreated) self._driver.set_callback('Target.targetCreated', self._onTargetCreated)
def _get_driver(self, tab_id): def _get_driver(self, tab_id):
"""获取对应tab id的ChromiumDriver """获取对应tab id的ChromiumDriver
@ -70,6 +70,7 @@ class Browser(object):
def _onTargetDestroyed(self, **kwargs): def _onTargetDestroyed(self, **kwargs):
"""标签页关闭时执行""" """标签页关闭时执行"""
tab_id = kwargs['targetId'] tab_id = kwargs['targetId']
if hasattr(self, '_dl_mgr'):
self._dl_mgr.clear_tab_info(tab_id) self._dl_mgr.clear_tab_info(tab_id)
for key in [k for k, i in self._frames.items() if i == tab_id]: for key in [k for k, i in self._frames.items() if i == tab_id]:
self._frames.pop(key, None) self._frames.pop(key, None)
@ -87,7 +88,7 @@ class Browser(object):
:param cmd_args: 参数 :param cmd_args: 参数
:return: 执行的结果 :return: 执行的结果
""" """
return self._driver.call_method(cmd, **cmd_args) return self._driver.run(cmd, **cmd_args)
@property @property
def driver(self): def driver(self):

View File

@ -139,15 +139,15 @@ class ChromiumDriver(object):
function = self.event_handlers.get(event['method']) function = self.event_handlers.get(event['method'])
if function: if function:
if self._debug: # if self._debug:
print(f'开始执行 {function.__name__}') # print(f'开始执行 {function.__name__}')
function(**event['params']) function(**event['params'])
if self._debug: # if self._debug:
print(f'执行 {function.__name__}完毕') # print(f'执行 {function.__name__}完毕')
self.event_queue.task_done() self.event_queue.task_done()
def call_method(self, _method, **kwargs): def run(self, _method, **kwargs):
"""执行cdp方法 """执行cdp方法
:param _method: cdp方法名 :param _method: cdp方法名
:param args: cdp参数 :param args: cdp参数
@ -205,7 +205,7 @@ class ChromiumDriver(object):
self.event_queue.queue.clear() self.event_queue.queue.clear()
return True return True
def set_listener(self, event, callback): def set_callback(self, event, callback):
"""绑定cdp event和回调方法 """绑定cdp event和回调方法
:param event: cdp event :param event: cdp event
:param callback: 绑定到cdp event的回调方法 :param callback: 绑定到cdp event的回调方法

View File

@ -47,13 +47,13 @@ class ChromiumDriver(object):
def __getattr__(self, item: str) -> Callable: ... def __getattr__(self, item: str) -> Callable: ...
def call_method(self, _method: str, **kwargs) -> dict: ... def run(self, _method: str, **kwargs) -> dict: ...
def start(self) -> bool: ... def start(self) -> bool: ...
def stop(self) -> bool: ... def stop(self) -> bool: ...
def set_listener(self, event: str, callback: Union[Callable, None]) -> None: ... def set_callback(self, event: str, callback: Union[Callable, None]) -> None: ...
def __str__(self) -> str: ... def __str__(self) -> str: ...

View File

@ -100,13 +100,17 @@ class ChromiumBase(BasePage):
""" """
self._is_loading = True self._is_loading = True
self._driver = self.browser._get_driver(tab_id) self._driver = self.browser._get_driver(tab_id)
self._alert = Alert() if self._driver.run('Target.getTargetInfo',
self._driver.set_listener('Page.javascriptDialogOpening', self._on_alert_open) targetId=self._target_id)['targetInfo']['url'] == 'chrome://privacy-sandbox-dialog/notice':
self._driver.set_listener('Page.javascriptDialogClosed', self._on_alert_close) self._driver = close_privacy_dialog(self)
self._driver.call_method('DOM.enable') self._alert = Alert()
self._driver.call_method('Page.enable') self._driver.set_callback('Page.javascriptDialogOpening', self._on_alert_open)
self._driver.call_method('Emulation.setFocusEmulationEnabled', enabled=True) self._driver.set_callback('Page.javascriptDialogClosed', self._on_alert_close)
self._driver.run('DOM.enable')
self._driver.run('Page.enable')
self._driver.run('Emulation.setFocusEmulationEnabled', enabled=True)
r = self.run_cdp('Page.getFrameTree') r = self.run_cdp('Page.getFrameTree')
for i in findall(r"'id': '(.*?)'", str(r)): for i in findall(r"'id': '(.*?)'", str(r)):
@ -114,13 +118,13 @@ class ChromiumBase(BasePage):
if not hasattr(self, '_frame_id'): if not hasattr(self, '_frame_id'):
self._frame_id = r['frameTree']['frame']['id'] self._frame_id = r['frameTree']['frame']['id']
self._driver.set_listener('Page.frameStartedLoading', self._onFrameStartedLoading) self._driver.set_callback('Page.frameStartedLoading', self._onFrameStartedLoading)
self._driver.set_listener('Page.frameNavigated', self._onFrameNavigated) self._driver.set_callback('Page.frameNavigated', self._onFrameNavigated)
self._driver.set_listener('Page.domContentEventFired', self._onDomContentEventFired) self._driver.set_callback('Page.domContentEventFired', self._onDomContentEventFired)
self._driver.set_listener('Page.loadEventFired', self._onLoadEventFired) self._driver.set_callback('Page.loadEventFired', self._onLoadEventFired)
self._driver.set_listener('Page.frameStoppedLoading', self._onFrameStoppedLoading) self._driver.set_callback('Page.frameStoppedLoading', self._onFrameStoppedLoading)
self._driver.set_listener('Page.frameAttached', self._onFrameAttached) self._driver.set_callback('Page.frameAttached', self._onFrameAttached)
self._driver.set_listener('Page.frameDetached', self._onFrameDetached) self._driver.set_callback('Page.frameDetached', self._onFrameDetached)
def _get_document(self): def _get_document(self):
if self._is_reading: if self._is_reading:
@ -231,7 +235,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.set_listener('Page.fileChooserOpened', None) self.driver.set_callback('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
@ -416,7 +420,7 @@ class ChromiumBase(BasePage):
:param cmd_args: 参数 :param cmd_args: 参数
:return: 执行的结果 :return: 执行的结果
""" """
r = self.driver.call_method(cmd, **cmd_args) r = self.driver.run(cmd, **cmd_args)
if ERROR not in r: if ERROR not in r:
return r return r
@ -822,9 +826,9 @@ class ChromiumBase(BasePage):
res_text = self._alert.text res_text = self._alert.text
if self._alert.type == 'prompt': if self._alert.type == 'prompt':
self.driver.call_method('Page.handleJavaScriptDialog', accept=accept, promptText=send) self.driver.run('Page.handleJavaScriptDialog', accept=accept, promptText=send)
else: else:
self.driver.call_method('Page.handleJavaScriptDialog', accept=accept) self.driver.run('Page.handleJavaScriptDialog', accept=accept)
return res_text return res_text
def _on_alert_close(self, **kwargs): def _on_alert_close(self, **kwargs):
@ -1032,3 +1036,35 @@ class Alert(object):
self.defaultPrompt = None self.defaultPrompt = None
self.response_accept = None self.response_accept = None
self.response_text = None self.response_text = None
def close_privacy_dialog(page):
"""关闭隐私声明弹窗
:param page: ChromiumBase对象
:return: ChromiumDriver对象
"""
tid = page.tab_id
page._driver.run('Runtime.enable')
page._driver.run('DOM.enable')
page._driver.run('DOM.getDocument')
sid = page._driver.run('DOM.performSearch', query='//*[name()="privacy-sandbox-notice-dialog-app"]',
includeUserAgentShadowDOM=True)['searchId']
r = page._driver.run('DOM.getSearchResults', searchId=sid, fromIndex=0, toIndex=1)['nodeIds'][0]
while True:
try:
r = page._driver.run('DOM.describeNode', nodeId=r)['node']['shadowRoots'][0]['backendNodeId']
break
except KeyError:
pass
page._driver.run('DOM.discardSearchResults', searchId=sid)
r = page._driver.run('DOM.resolveNode', backendNodeId=r)['object']['objectId']
r = page._driver.run('Runtime.callFunctionOn', objectId=r,
functionDeclaration='function()'
'{return this.getElementById("ackButton");}')['result']['objectId']
page._driver.run('Runtime.callFunctionOn', objectId=r, functionDeclaration='function(){return this.click();}')
while True:
new_tid = page.browser.tabs[0]
if new_tid != tid:
break
sleep(.1)
return page.browser._get_driver(new_tid)

View File

@ -90,7 +90,7 @@ class ChromiumFrame(ChromiumBase):
except: except:
self.browser.driver.get(f'http://{self.address}/json') self.browser.driver.get(f'http://{self.address}/json')
super()._driver_init(tab_id) super()._driver_init(tab_id)
self._driver.set_listener('Inspector.detached', self._onInspectorDetached) self._driver.set_callback('Inspector.detached', self._onInspectorDetached)
def _reload(self): def _reload(self):
"""重新获取document""" """重新获取document"""

View File

@ -314,7 +314,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.call_method('Browser.close') self.driver.run('Browser.close')
except Exception: except Exception:
pass pass
self._driver.stop() self._driver.stop()

View File

@ -59,7 +59,7 @@ class ActionChains:
cx = x + offset_x cx = x + offset_x
cy = y + offset_y cy = y + offset_y
self._dr.call_method('Input.dispatchMouseEvent', type='mouseMoved', x=cx, y=cy, modifiers=self.modifier) self._dr.run('Input.dispatchMouseEvent', type='mouseMoved', x=cx, y=cy, modifiers=self.modifier)
self.curr_x = cx self.curr_x = cx
self.curr_y = cy self.curr_y = cy
return self return self
@ -72,7 +72,7 @@ class ActionChains:
""" """
self.curr_x += offset_x self.curr_x += offset_x
self.curr_y += offset_y self.curr_y += offset_y
self._dr.call_method('Input.dispatchMouseEvent', type='mouseMoved', x=self.curr_x, y=self.curr_y, self._dr.run('Input.dispatchMouseEvent', type='mouseMoved', x=self.curr_x, y=self.curr_y,
modifiers=self.modifier) modifiers=self.modifier)
return self return self
@ -171,7 +171,7 @@ class ActionChains:
""" """
if on_ele: if on_ele:
self.move_to(on_ele) self.move_to(on_ele)
self._dr.call_method('Input.dispatchMouseEvent', type='mousePressed', button=button, clickCount=count, self._dr.run('Input.dispatchMouseEvent', type='mousePressed', button=button, clickCount=count,
x=self.curr_x, y=self.curr_y, modifiers=self.modifier) x=self.curr_x, y=self.curr_y, modifiers=self.modifier)
return self return self
@ -180,7 +180,7 @@ class ActionChains:
:param button: 要释放的按键 :param button: 要释放的按键
:return: self :return: self
""" """
self._dr.call_method('Input.dispatchMouseEvent', type='mouseReleased', button=button, clickCount=1, self._dr.run('Input.dispatchMouseEvent', type='mouseReleased', button=button, clickCount=1,
x=self.curr_x, y=self.curr_y, modifiers=self.modifier) x=self.curr_x, y=self.curr_y, modifiers=self.modifier)
return self return self
@ -193,7 +193,7 @@ class ActionChains:
""" """
if on_ele: if on_ele:
self.move_to(on_ele) self.move_to(on_ele)
self._dr.call_method('Input.dispatchMouseEvent', type='mouseWheel', x=self.curr_x, y=self.curr_y, self._dr.run('Input.dispatchMouseEvent', type='mouseWheel', x=self.curr_x, y=self.curr_y,
deltaX=delta_x, deltaY=delta_y, modifiers=self.modifier) deltaX=delta_x, deltaY=delta_y, modifiers=self.modifier)
return self return self

View File

@ -27,8 +27,8 @@ class DownloadManager(object):
self._tab_missions = {} # {tab_id: DownloadMission} self._tab_missions = {} # {tab_id: DownloadMission}
self._flags = {} # {tab_id: [bool, DownloadMission]} self._flags = {} # {tab_id: [bool, DownloadMission]}
self._browser.driver.set_listener('Browser.downloadProgress', self._onDownloadProgress) self._browser.driver.set_callback('Browser.downloadProgress', self._onDownloadProgress)
self._browser.driver.set_listener('Browser.downloadWillBegin', self._onDownloadWillBegin) self._browser.driver.set_callback('Browser.downloadWillBegin', self._onDownloadWillBegin)
self._browser.run_cdp('Browser.setDownloadBehavior', downloadPath=self._page.download_path, self._browser.run_cdp('Browser.setDownloadBehavior', downloadPath=self._page.download_path,
behavior='allowAndName', eventsEnabled=True) behavior='allowAndName', eventsEnabled=True)

View File

@ -78,7 +78,7 @@ class NetworkListener(object):
return return
self._driver = ChromiumDriver(self._page.tab_id, 'page', self._page.address) self._driver = ChromiumDriver(self._page.tab_id, 'page', self._page.address)
self._driver.call_method('Network.enable') self._driver.run('Network.enable')
self.listening = True self.listening = True
self._request_ids = {} self._request_ids = {}
@ -158,10 +158,10 @@ class NetworkListener(object):
:return: None :return: None
""" """
if self.listening: if self.listening:
self._driver.set_listener('Network.requestWillBeSent', None) self._driver.set_callback('Network.requestWillBeSent', None)
self._driver.set_listener('Network.responseReceived', None) self._driver.set_callback('Network.responseReceived', None)
self._driver.set_listener('Network.loadingFinished', None) self._driver.set_callback('Network.loadingFinished', None)
self._driver.set_listener('Network.loadingFailed', None) self._driver.set_callback('Network.loadingFailed', None)
self.listening = False self.listening = False
if clear: if clear:
self.clear() self.clear()
@ -181,12 +181,12 @@ class NetworkListener(object):
def _set_callback(self): def _set_callback(self):
"""设置监听请求的回调函数""" """设置监听请求的回调函数"""
self._driver.set_listener('Network.requestWillBeSent', self._requestWillBeSent) self._driver.set_callback('Network.requestWillBeSent', self._requestWillBeSent)
self._driver.set_listener('Network.requestWillBeSentExtraInfo', self._requestWillBeSentExtraInfo) self._driver.set_callback('Network.requestWillBeSentExtraInfo', self._requestWillBeSentExtraInfo)
self._driver.set_listener('Network.responseReceived', self._response_received) self._driver.set_callback('Network.responseReceived', self._response_received)
self._driver.set_listener('Network.responseReceivedExtraInfo', self._responseReceivedExtraInfo) self._driver.set_callback('Network.responseReceivedExtraInfo', self._responseReceivedExtraInfo)
self._driver.set_listener('Network.loadingFinished', self._loading_finished) self._driver.set_callback('Network.loadingFinished', self._loading_finished)
self._driver.set_listener('Network.loadingFailed', self._loading_failed) self._driver.set_callback('Network.loadingFailed', self._loading_failed)
def _requestWillBeSent(self, **kwargs): def _requestWillBeSent(self, **kwargs):
"""接收到请求时的回调函数""" """接收到请求时的回调函数"""
@ -197,7 +197,7 @@ class NetworkListener(object):
p = self._request_ids.setdefault(rid, DataPacket(self._page.tab_id, None)) p = self._request_ids.setdefault(rid, DataPacket(self._page.tab_id, None))
p._raw_request = kwargs p._raw_request = kwargs
if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None): if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None):
p._raw_post_data = self._driver.call_method('Network.getRequestPostData', requestId=rid)['postData'] p._raw_post_data = self._driver.run('Network.getRequestPostData', requestId=rid)['postData']
else: else:
rid = kwargs['requestId'] rid = kwargs['requestId']
@ -208,7 +208,7 @@ class NetworkListener(object):
p = self._request_ids.setdefault(rid, DataPacket(self._page.tab_id, target)) p = self._request_ids.setdefault(rid, DataPacket(self._page.tab_id, target))
p._raw_request = kwargs p._raw_request = kwargs
if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None): if kwargs['request'].get('hasPostData', None) and not kwargs['request'].get('postData', None):
p._raw_post_data = self._driver.call_method('Network.getRequestPostData', p._raw_post_data = self._driver.run('Network.getRequestPostData',
requestId=rid)['postData'] requestId=rid)['postData']
break break
@ -244,7 +244,7 @@ class NetworkListener(object):
r_id = kwargs['requestId'] r_id = kwargs['requestId']
dp = self._request_ids.get(r_id) dp = self._request_ids.get(r_id)
if dp: if dp:
r = self._driver.call_method('Network.getResponseBody', requestId=r_id) r = self._driver.run('Network.getResponseBody', requestId=r_id)
if 'body' in r: if 'body' in r:
dp._raw_body = r['body'] dp._raw_body = r['body']
dp._base64_body = r['base64Encoded'] dp._base64_body = r['base64Encoded']
@ -364,9 +364,6 @@ class DataPacket(object):
:param timeout: 超时时间None为无限等待 :param timeout: 超时时间None为无限等待
:return: 是否等待成功 :return: 是否等待成功
""" """
if self._raw_request['redirectHasExtraInfo'] is False:
return True
if timeout is None: if timeout is None:
while self._responseExtraInfo is None: while self._responseExtraInfo is None:
sleep(.1) sleep(.1)

View File

@ -35,7 +35,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.set_listener('Page.screencastFrame', self._onScreencastFrame) self._page.driver.set_callback('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'):
@ -92,7 +92,7 @@ class Screencast(object):
return path return path
if self._mode.startswith('frugal'): if self._mode.startswith('frugal'):
self._page.driver.set_listener('Page.screencastFrame', None) self._page.driver.set_callback('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

@ -102,7 +102,7 @@ class ChromiumBaseSetter(object):
:return: None :return: None
""" """
if not self._page._upload_list: if not self._page._upload_list:
self._page.driver.set_listener('Page.fileChooserOpened', self._page._onFileChooserOpened) self._page.driver.set_callback('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):
@ -164,12 +164,6 @@ class TabSetter(ChromiumBaseSetter):
class ChromiumPageSetter(TabSetter): class ChromiumPageSetter(TabSetter):
def main_tab(self, tab_id=None):
"""设置主tab
:param tab_id: 标签页id不传入则设置当前tab
:return: None
"""
self._page._main_tab = tab_id or self._page.tab_id
def tab_to_front(self, tab_or_id=None): def tab_to_front(self, tab_or_id=None):
"""激活标签页使其处于最前面 """激活标签页使其处于最前面