优化关闭隐私声明逻辑;支持设置实验项

This commit is contained in:
g1879 2023-11-19 19:49:01 +08:00
parent b62cb110c4
commit 066eadc7e0
8 changed files with 97 additions and 12 deletions

View File

@ -13,4 +13,4 @@ from ._configs.chromium_options import ChromiumOptions
from ._configs.session_options import SessionOptions
__all__ = ['ChromiumPage', 'ChromiumOptions', 'SessionOptions', 'SessionPage', 'WebPage', '__version__']
__version__ = '4.0.0b8'
__version__ = '4.0.0b9'

View File

@ -37,6 +37,7 @@ def connect_browser(option):
# ----------创建浏览器进程----------
args = get_launch_args(option)
set_prefs(option)
set_flags(option)
try:
_run_browser(port, chrome_path, args)
@ -89,6 +90,7 @@ def get_launch_args(opt):
port = opt.debugger_address.split(':')[-1] if opt.debugger_address else '0'
path = Path(gettempdir()) / 'DrissionPage' / f'userData_{port}'
path.mkdir(parents=True, exist_ok=True)
opt.set_user_data_path(path)
result.add(f'--user-data-dir={path}')
if not remote_allow:
@ -119,15 +121,13 @@ def set_prefs(opt):
:param opt: ChromiumOptions
:return: None
"""
if not opt.user_data_path or (not opt.preferences and not opt._prefs_to_del):
return
prefs = opt.preferences
del_list = opt._prefs_to_del
if not opt.user_data_path:
return
args = opt.arguments
user = 'Default'
for arg in args:
for arg in opt.arguments:
if arg.startswith('--profile-directory'):
user = arg.split('=')[-1].strip()
break
@ -158,6 +158,42 @@ def set_prefs(opt):
dump(prefs_dict, f)
def set_flags(opt):
"""处理启动配置中的prefs项目前只能对已存在文件夹配置
:param opt: ChromiumOptions
:return: None
"""
if not opt.user_data_path or (not opt.clear_file_flags and not opt.flags):
return
state_file = Path(opt.user_data_path) / 'Local State'
if not state_file.exists():
state_file.parent.mkdir(parents=True, exist_ok=True)
with open(state_file, 'w') as f:
f.write('{}')
with open(state_file, "r", encoding='utf-8') as f:
try:
states_dict = load(f)
except JSONDecodeError:
states_dict = {}
flags_list = [] if opt.clear_file_flags else states_dict.setdefault(
'browser', {}).setdefault('enabled_labs_experiments', [])
flags_dict = {}
for i in flags_list:
f = str(i).split('@', 1)
flags_dict[f[0]] = None if len(f) == 1 else f[1]
for k, i in opt.flags.items():
flags_dict[k] = i
states_dict['browser']['enabled_labs_experiments'] = [f'{k}@{i}' if i else k for k, i in flags_dict.items()]
with open(state_file, 'w', encoding='utf-8') as f:
dump(states_dict, f)
def test_connect(ip, port, timeout=30):
"""测试浏览器是否可用
:param ip: 浏览器ip

View File

@ -17,4 +17,7 @@ def get_launch_args(opt: ChromiumOptions) -> list: ...
def set_prefs(opt: ChromiumOptions) -> None: ...
def set_flags(opt: ChromiumOptions) -> None: ...
def test_connect(ip: str, port: Union[int, str], timeout: float = 30) -> None: ...

View File

@ -21,6 +21,7 @@ class ChromiumOptions(object):
self._user_data_path = None
self._user = 'Default'
self._prefs_to_del = []
self.clear_file_flags = False
self._headless = None
if read_file is not False:
@ -34,6 +35,7 @@ class ChromiumOptions(object):
self._browser_path = options.get('browser_path', '')
self._extensions = options.get('extensions', [])
self._prefs = options.get('prefs', {})
self._flags = options.get('flags', {})
self._debugger_address = options.get('debugger_address', None)
self._load_mode = options.get('load_mode', 'normal')
self._proxy = om.proxies.get('http', None)
@ -69,6 +71,7 @@ class ChromiumOptions(object):
self._download_path = ''
self._extensions = []
self._prefs = {}
self._flags = {}
self._timeouts = {'implicit': 10, 'pageLoad': 30, 'script': 30}
self._debugger_address = '127.0.0.1:9222'
self._load_mode = 'normal'
@ -137,6 +140,11 @@ class ChromiumOptions(object):
"""返回用户首选项配置"""
return self._prefs
@property
def flags(self):
"""返回实验项配置"""
return self._flags
@property
def system_user_path(self):
"""返回是否使用系统安装的浏览器所使用的用户数据文件夹"""
@ -221,6 +229,23 @@ class ChromiumOptions(object):
self._prefs_to_del.append(arg)
return self
def set_flag(self, flag, value=None):
"""设置实验项
:param flag: 设置项名称
:param value: 设置项的值为False则删除该项
:return: 当前对象
"""
if value is False:
self._flags.pop(flag, None)
else:
self._flags[flag] = value
return self
def clear_flags_in_file(self):
"""删除浏览器设置文件中已设置的实验项"""
self.clear_file_flags = True
return self
def set_timeouts(self, implicit=None, pageLoad=None, script=None):
"""设置超时时间,单位为秒
:param implicit: 默认超时时间
@ -454,7 +479,7 @@ class ChromiumOptions(object):
# 设置chrome_options
attrs = ('debugger_address', 'browser_path', 'arguments', 'extensions', 'user', 'load_mode',
'auto_port', 'system_user_path', 'existing_only')
'auto_port', 'system_user_path', 'existing_only', 'flags')
for i in attrs:
om.set_item('chrome_options', i, self.__getattribute__(f'_{i}'))
# 设置代理

View File

@ -22,7 +22,9 @@ class ChromiumOptions(object):
self._debugger_address: str = ...
self._extensions: list = ...
self._prefs: dict = ...
self._flags: dict = ...
self._prefs_to_del: list = ...
self.clear_file_flags: bool = ...
self._auto_port: bool = ...
self._system_user_path: bool = ...
self._existing_only: bool = ...
@ -61,6 +63,9 @@ class ChromiumOptions(object):
@property
def preferences(self) -> dict: ...
@property
def flags(self) -> dict: ...
@property
def system_user_path(self) -> bool: ...
@ -81,6 +86,10 @@ class ChromiumOptions(object):
def remove_pref_from_file(self, arg: str) -> ChromiumOptions: ...
def set_flag(self, flag: str, value: Union[int, str, bool] = None) -> ChromiumOptions: ...
def clear_flags_in_file(self) -> ChromiumOptions: ...
def set_timeouts(self, implicit: float = None, pageLoad: float = None,
script: float = None) -> ChromiumOptions: ...

View File

@ -7,6 +7,7 @@ browser_path = chrome
arguments = ['--remote-allow-origins=*', '--no-first-run', '--disable-infobars', '--disable-popup-blocking']
extensions = []
prefs = {'profile.default_content_settings.popups': 0, 'profile.default_content_setting_values': {'notifications': 2}}
flags = {}
load_mode = normal
user = Default
auto_port = False

View File

@ -10,7 +10,6 @@ from re import findall
from threading import Thread
from time import perf_counter, sleep
from .._units.rect import TabRect
from .._base.base import BasePage
from .._commons.constants import ERROR, NoneElement
from .._commons.locator import get_loc
@ -20,6 +19,7 @@ from .._elements.chromium_element import ChromiumElement, run_js, make_chromium_
from .._elements.session_element import make_session_ele
from .._units.action_chains import ActionChains
from .._units.network_listener import NetworkListener
from .._units.rect import TabRect
from .._units.screencast import Screencast
from .._units.scroller import PageScroller
from .._units.setter import ChromiumBaseSetter
@ -88,9 +88,20 @@ class ChromiumBase(BasePage):
if not tab_id:
tabs = self.browser.driver.get(f'http://{self.address}/json').json()
tabs = [(i['id'], i['url']) for i in tabs if i['type'] == 'page' and not i['url'].startswith('devtools://')]
if tabs[0][1] == 'chrome://privacy-sandbox-dialog/notice' and len(tabs) > 1:
tab_id = tabs[1][0]
close_privacy_dialog(self, tabs[0][0])
dialog = None
if len(tabs) > 1:
for k, t in enumerate(tabs):
if t[1] == 'chrome://privacy-sandbox-dialog/notice':
dialog = k
elif not tab_id:
tab_id = t[0]
if tab_id and dialog is not None:
break
if dialog is not None:
close_privacy_dialog(self, tabs[dialog][0])
else:
tab_id = tabs[0][0]

View File

@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh:
setup(
name="DrissionPage",
version="4.0.0b8",
version="4.0.0b9",
author="g1879",
author_email="g1879@qq.com",
description="Python based web automation tool. It can control the browser and send and receive data packets.",