diff --git a/DrissionPage/_configs/chromium_options.py b/DrissionPage/_configs/chromium_options.py index 35e14c2..5306486 100644 --- a/DrissionPage/_configs/chromium_options.py +++ b/DrissionPage/_configs/chromium_options.py @@ -13,10 +13,6 @@ from .options_manage import OptionsManager class ChromiumOptions(object): def __init__(self, read_file=True, ini_path=None): - """ - :param read_file: 是否从默认ini文件中读取配置信息 - :param ini_path: ini文件路径,为None则读取默认ini文件 - """ self._user_data_path = None self._user = 'Default' self._prefs_to_del = [] @@ -82,105 +78,81 @@ class ChromiumOptions(object): @property def download_path(self): - """默认下载路径文件路径""" return self._download_path @property def browser_path(self): - """浏览器启动文件路径""" return self._browser_path @property def user_data_path(self): - """返回用户数据文件夹路径""" return self._user_data_path @property def tmp_path(self): - """返回临时文件夹路径""" return self._tmp_path @property def user(self): - """返回用户配置文件夹名称""" return self._user @property def load_mode(self): - """返回页面加载策略,'normal', 'eager', 'none'""" return self._load_mode @property def timeouts(self): - """返回timeouts设置""" return self._timeouts @property def proxy(self): - """返回代理设置""" return self._proxy @property def address(self): - """返回浏览器地址,ip:port""" return self._address @property def arguments(self): - """返回浏览器命令行设置列表""" return self._arguments @property def extensions(self): - """以list形式返回要加载的插件路径""" return self._extensions @property def preferences(self): - """返回用户首选项配置""" return self._prefs @property def flags(self): - """返回实验项配置""" return self._flags @property def system_user_path(self): - """返回是否使用系统安装的浏览器所使用的用户数据文件夹""" return self._system_user_path @property def is_existing_only(self): - """返回是否只接管现有浏览器方式""" return self._existing_only @property def is_auto_port(self): - """返回是否使用自动端口和用户文件,如指定范围则返回范围tuple""" return self._auto_port @property def retry_times(self): - """返回连接失败时的重试次数""" return self._retry_times @property def retry_interval(self): - """返回连接失败时的重试间隔(秒)""" return self._retry_interval @property def is_headless(self): - """返回是否无头模式""" return self._is_headless def set_retry(self, times=None, interval=None): - """设置连接失败时的重试操作 - :param times: 重试次数 - :param interval: 重试间隔 - :return: 当前对象 - """ if times is not None: self._retry_times = times if interval is not None: @@ -188,11 +160,6 @@ class ChromiumOptions(object): return self def set_argument(self, arg, value=None): - """设置浏览器配置的argument属性 - :param arg: 属性名 - :param value: 属性值,有值的属性传入值,没有的传入None,如传入False,删除该项 - :return: 当前对象 - """ self.remove_argument(arg) if value is not False: if arg == '--headless': @@ -211,10 +178,6 @@ class ChromiumOptions(object): return self def remove_argument(self, value): - """移除一个argument项 - :param value: 设置项名,有值的设置项传入设置名称即可 - :return: 当前对象 - """ elements_to_delete = [arg for arg in self._arguments if arg == value or arg.startswith(f'{value}=')] if not elements_to_delete: return self @@ -227,10 +190,6 @@ class ChromiumOptions(object): return self def add_extension(self, path): - """添加插件 - :param path: 插件路径,可指向文件夹 - :return: 当前对象 - """ path = Path(path) if not path.exists(): raise OSError('插件路径不存在。') @@ -238,43 +197,22 @@ class ChromiumOptions(object): return self def remove_extensions(self): - """移除所有插件 - :return: 当前对象 - """ self._extensions = [] return self def set_pref(self, arg, value): - """设置Preferences文件中的用户设置项 - :param arg: 设置项名称 - :param value: 设置项值 - :return: 当前对象 - """ self._prefs[arg] = value return self def remove_pref(self, arg): - """删除用户首选项设置,不能删除已设置到文件中的项 - :param arg: 设置项名称 - :return: 当前对象 - """ self._prefs.pop(arg, None) return self def remove_pref_from_file(self, arg): - """删除用户配置文件中已设置的项 - :param arg: 设置项名称 - :return: 当前对象 - """ 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: @@ -282,32 +220,22 @@ class ChromiumOptions(object): return self def clear_flags_in_file(self): - """删除浏览器配置文件中已设置的实验项""" self.clear_file_flags = True return self def clear_flags(self): - """清空本对象已设置的flag参数""" self._flags = {} return self def clear_arguments(self): - """清空本对象已设置的argument参数""" self._arguments = [] return self def clear_prefs(self): - """清空本对象已设置的pref参数""" self._prefs = {} return self def set_timeouts(self, base=None, page_load=None, script=None): - """设置超时时间,单位为秒 - :param base: 默认超时时间 - :param page_load: 页面加载超时时间 - :param script: 脚本运行超时时间 - :return: 当前对象 - """ if base is not None: self._timeouts['base'] = base if page_load is not None: @@ -318,82 +246,42 @@ class ChromiumOptions(object): return self def set_user(self, user='Default'): - """设置使用哪个用户配置文件夹 - :param user: 用户文件夹名称 - :return: 当前对象 - """ self.set_argument('--profile-directory', user) self._user = user return self def headless(self, on_off=True): - """设置是否隐藏浏览器界面 - :param on_off: 开或关 - :return: 当前对象 - """ on_off = 'new' if on_off else on_off return self.set_argument('--headless', on_off) def no_imgs(self, on_off=True): - """设置是否加载图片 - :param on_off: 开或关 - :return: 当前对象 - """ on_off = None if on_off else False return self.set_argument('--blink-settings=imagesEnabled=false', on_off) def no_js(self, on_off=True): - """设置是否禁用js - :param on_off: 开或关 - :return: 当前对象 - """ on_off = None if on_off else False return self.set_argument('--disable-javascript', on_off) def mute(self, on_off=True): - """设置是否静音 - :param on_off: 开或关 - :return: 当前对象 - """ on_off = None if on_off else False return self.set_argument('--mute-audio', on_off) def incognito(self, on_off=True): - """设置是否使用无痕模式启动 - :param on_off: 开或关 - :return: 当前对象 - """ on_off = None if on_off else False return self.set_argument('--incognito', on_off) def new_env(self, on_off=True): - """设置是否使用全新浏览器环境 - :param on_off: 开或关 - :return: 当前对象 - """ self._new_env = on_off return self def ignore_certificate_errors(self, on_off=True): - """设置是否忽略证书错误 - :param on_off: 开或关 - :return: 当前对象 - """ on_off = None if on_off else False return self.set_argument('--ignore-certificate-errors', on_off) def set_user_agent(self, user_agent): - """设置user agent - :param user_agent: user agent文本 - :return: 当前对象 - """ return self.set_argument('--user-agent', user_agent) def set_proxy(self, proxy): - """设置代理 - :param proxy: 代理url和端口 - :return: 当前对象 - """ if search(r'.*?:.*?@.*?\..*', proxy): print('你似乎在设置使用账号密码的代理,暂时不支持这种代理,可自行用插件实现需求。') if proxy.lower().startswith('socks'): @@ -402,13 +290,6 @@ class ChromiumOptions(object): return self.set_argument('--proxy-server', proxy) def set_load_mode(self, value): - """设置load_mode,可接收 'normal', 'eager', 'none' - normal:默认情况下使用, 等待所有资源下载完成 - eager:DOM访问已准备就绪, 但其他资源 (如图像) 可能仍在加载中 - none:完全不阻塞 - :param value: 可接收 'normal', 'eager', 'none' - :return: 当前对象 - """ if value not in ('normal', 'eager', 'none'): raise ValueError("只能选择 'normal', 'eager', 'none'。") self._load_mode = value.lower() @@ -446,52 +327,28 @@ class ChromiumOptions(object): return self def set_local_port(self, port): - """设置本地启动端口 - :param port: 端口号 - :return: 当前对象 - """ self._address = f'127.0.0.1:{port}' self._auto_port = False return self def set_address(self, address): - """设置浏览器地址,格式'ip:port' - :param address: 浏览器地址 - :return: 当前对象 - """ address = address.replace('localhost', '127.0.0.1').lstrip('http://').lstrip('https://') self._address = address return self def set_browser_path(self, path): - """设置浏览器可执行文件路径 - :param path: 浏览器路径 - :return: 当前对象 - """ self._browser_path = str(path) return self def set_download_path(self, path): - """设置下载文件保存路径 - :param path: 下载路径 - :return: 当前对象 - """ self._download_path = '.' if path is None else str(path) return self def set_tmp_path(self, path): - """设置临时文件文件保存路径 - :param path: 下载路径 - :return: 当前对象 - """ self._tmp_path = str(path) return self def set_user_data_path(self, path): - """设置用户文件夹路径 - :param path: 用户文件夹路径 - :return: 当前对象 - """ u = str(path) self.set_argument('--user-data-dir', u) self._user_data_path = u @@ -499,27 +356,14 @@ class ChromiumOptions(object): return self def set_cache_path(self, path): - """设置缓存路径 - :param path: 缓存路径 - :return: 当前对象 - """ self.set_argument('--disk-cache-dir', str(path)) return self def use_system_user_path(self, on_off=True): - """设置是否使用系统安装的浏览器默认用户文件夹 - :param on_off: 开或关 - :return: 当前对象 - """ self._system_user_path = on_off return self def auto_port(self, on_off=True, scope=None): - """自动获取可用端口 - :param on_off: 是否开启自动获取端口号 - :param scope: 指定端口范围,不含最后的数字,为None则使用[9600-59600) - :return: 当前对象 - """ if on_off: self._auto_port = scope if scope else (9600, 59600) else: @@ -527,18 +371,10 @@ class ChromiumOptions(object): return self def existing_only(self, on_off=True): - """设置只接管已有浏览器,不自动启动新的 - :param on_off: 是否开启自动获取端口号 - :return: 当前对象 - """ self._existing_only = on_off return self def save(self, path=None): - """保存设置到文件 - :param path: ini文件的路径, None 保存到当前读取的配置文件,传入 'default' 保存到默认ini文件 - :return: 保存文件的绝对路径 - """ if path == 'default': path = (Path(__file__).parent / 'configs.ini').absolute() @@ -585,7 +421,6 @@ class ChromiumOptions(object): return path def save_to_default(self): - """保存当前配置到默认ini文件""" return self.save('default') def __repr__(self): diff --git a/DrissionPage/_configs/chromium_options.pyi b/DrissionPage/_configs/chromium_options.pyi index 06875a1..d6de46b 100644 --- a/DrissionPage/_configs/chromium_options.pyi +++ b/DrissionPage/_configs/chromium_options.pyi @@ -36,144 +36,368 @@ class ChromiumOptions(object): _is_headless: bool = ... _ua_set: bool = ... - def __init__(self, read_file: [bool, None] = True, ini_path: Union[str, Path] = None): ... + def __init__(self, + read_file: [bool, None] = True, + ini_path: Union[str, Path] = None): + """ + :param read_file: 是否从默认ini文件中读取配置信息 + :param ini_path: ini文件路径,为None则读取默认ini文件 + """ + ... @property - def download_path(self) -> str: ... + def download_path(self) -> str: + """默认下载路径文件路径""" + ... @property - def browser_path(self) -> str: ... + def browser_path(self) -> str: + """浏览器启动文件路径""" + ... @property - def user_data_path(self) -> str: ... + def user_data_path(self) -> str: + """返回用户数据文件夹路径""" + ... @property - def tmp_path(self) -> Optional[str]: ... + def tmp_path(self) -> Optional[str]: + """返回临时文件夹路径""" + ... @property - def user(self) -> str: ... + def user(self) -> str: + """返回用户配置文件夹名称""" + ... @property - def load_mode(self) -> str: ... + def load_mode(self) -> str: + """返回页面加载策略,'normal', 'eager', 'none'""" + ... @property - def timeouts(self) -> dict: ... + def timeouts(self) -> dict: + """返回timeouts设置""" + ... @property - def proxy(self) -> str: ... + def proxy(self) -> str: + """返回代理设置""" + ... @property - def address(self) -> str: ... + def address(self) -> str: + """返回浏览器地址,ip:port""" + ... @property - def arguments(self) -> list: ... + def arguments(self) -> list: + """返回浏览器命令行设置列表""" + ... @property - def extensions(self) -> list: ... + def extensions(self) -> list: + """以list形式返回要加载的插件路径""" + ... @property - def preferences(self) -> dict: ... + def preferences(self) -> dict: + """返回用户首选项配置""" + ... @property - def flags(self) -> dict: ... + def flags(self) -> dict: + """返回实验项配置""" + ... @property - def system_user_path(self) -> bool: ... + def system_user_path(self) -> bool: + """返回是否使用系统安装的浏览器所使用的用户数据文件夹""" + ... @property - def is_existing_only(self) -> bool: ... + def is_existing_only(self) -> bool: + """返回是否只接管现有浏览器方式""" + ... @property - def is_auto_port(self) -> Union[bool, Tuple[int, int]]: ... + def is_auto_port(self) -> Union[bool, Tuple[int, int]]: + """返回是否使用自动端口和用户文件,如指定范围则返回范围tuple""" + ... @property - def retry_times(self) -> int: ... + def retry_times(self) -> int: + """返回连接失败时的重试次数""" + ... @property - def retry_interval(self) -> float: ... + def retry_interval(self) -> float: + """返回连接失败时的重试间隔(秒)""" + ... @property - def is_headless(self) -> bool: ... + def is_headless(self) -> bool: + """返回是否无头模式""" + ... - def set_retry(self, times: int = None, interval: float = None) -> ChromiumOptions: ... + def set_retry(self, times: int = None, interval: float = None) -> ChromiumOptions: + """设置连接失败时的重试操作 + :param times: 重试次数 + :param interval: 重试间隔 + :return: 当前对象 + """ + ... - def set_argument(self, arg: str, value: Union[str, None, bool] = None) -> ChromiumOptions: ... + def set_argument(self, arg: str, value: Union[str, None, bool] = None) -> ChromiumOptions: + """设置浏览器配置的argument属性 + :param arg: 属性名 + :param value: 属性值,有值的属性传入值,没有的传入None,如传入False,删除该项 + :return: 当前对象 + """ + ... - def remove_argument(self, value: str) -> ChromiumOptions: ... + def remove_argument(self, value: str) -> ChromiumOptions: + """移除一个argument项 + :param value: 设置项名,有值的设置项传入设置名称即可 + :return: 当前对象 + """ + ... - def add_extension(self, path: Union[str, Path]) -> ChromiumOptions: ... + def add_extension(self, path: Union[str, Path]) -> ChromiumOptions: + """添加插件 + :param path: 插件路径,可指向文件夹 + :return: 当前对象 + """ + ... - def remove_extensions(self) -> ChromiumOptions: ... + def remove_extensions(self) -> ChromiumOptions: + """移除所有插件 + :return: 当前对象 + """ + ... - def set_pref(self, arg: str, value: Any) -> ChromiumOptions: ... + def set_pref(self, arg: str, value: Any) -> ChromiumOptions: + """设置Preferences文件中的用户设置项 + :param arg: 设置项名称 + :param value: 设置项值 + :return: 当前对象 + """ + ... - def remove_pref(self, arg: str) -> ChromiumOptions: ... + def remove_pref(self, arg: str) -> ChromiumOptions: + """删除用户首选项设置,不能删除已设置到文件中的项 + :param arg: 设置项名称 + :return: 当前对象 + """ + ... - def remove_pref_from_file(self, arg: str) -> ChromiumOptions: ... + def remove_pref_from_file(self, arg: str) -> ChromiumOptions: + """删除用户配置文件中已设置的项 + :param arg: 设置项名称 + :return: 当前对象 + """ + ... - def set_flag(self, flag: str, value: Union[int, str, bool] = None) -> ChromiumOptions: ... + def set_flag(self, flag: str, value: Union[int, str, bool] = None) -> ChromiumOptions: + """设置实验项 + :param flag: 设置项名称 + :param value: 设置项的值,为False则删除该项 + :return: 当前对象 + """ + ... - def clear_flags_in_file(self) -> ChromiumOptions: ... + def clear_flags_in_file(self) -> ChromiumOptions: + """删除浏览器配置文件中已设置的实验项""" + ... - def clear_flags(self) -> ChromiumOptions: ... + def clear_flags(self) -> ChromiumOptions: + """清空本对象已设置的flag参数""" + ... - def clear_arguments(self) -> ChromiumOptions: ... + def clear_arguments(self) -> ChromiumOptions: + """清空本对象已设置的argument参数""" + ... - def clear_prefs(self) -> ChromiumOptions: ... + def clear_prefs(self) -> ChromiumOptions: + """清空本对象已设置的pref参数""" + ... def set_timeouts(self, base: float = None, page_load: float = None, - script: float = None) -> ChromiumOptions: ... + script: float = None) -> ChromiumOptions: + """设置超时时间,单位为秒 + :param base: 默认超时时间 + :param page_load: 页面加载超时时间 + :param script: 脚本运行超时时间 + :return: 当前对象 + """ + ... - def set_user(self, user: str = 'Default') -> ChromiumOptions: ... + def set_user(self, user: str = 'Default') -> ChromiumOptions: + """设置使用哪个用户配置文件夹 + :param user: 用户文件夹名称 + :return: 当前对象 + """ + ... - def headless(self, on_off: bool = True) -> ChromiumOptions: ... + def headless(self, on_off: bool = True) -> ChromiumOptions: + """设置是否隐藏浏览器界面 + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def no_imgs(self, on_off: bool = True) -> ChromiumOptions: ... + def no_imgs(self, on_off: bool = True) -> ChromiumOptions: + """设置是否加载图片 + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def no_js(self, on_off: bool = True) -> ChromiumOptions: ... + def no_js(self, on_off: bool = True) -> ChromiumOptions: + """设置是否禁用js + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def mute(self, on_off: bool = True) -> ChromiumOptions: ... + def mute(self, on_off: bool = True) -> ChromiumOptions: + """设置是否静音 + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def incognito(self, on_off: bool = True) -> ChromiumOptions: ... + def incognito(self, on_off: bool = True) -> ChromiumOptions: + """设置是否使用无痕模式启动 + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def new_env(self, on_off: bool = True) -> ChromiumOptions: ... + def new_env(self, on_off: bool = True) -> ChromiumOptions: + """设置是否使用全新浏览器环境 + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def set_user_agent(self, user_agent: str) -> ChromiumOptions: ... + def ignore_certificate_errors(self, on_off=True) -> ChromiumOptions: + """设置是否忽略证书错误 + :param on_off: 开或关 + :return: 当前对象 + """ + ... - def set_proxy(self, proxy: str) -> ChromiumOptions: ... + def set_user_agent(self, user_agent: str) -> ChromiumOptions: + """设置user agent + :param user_agent: user agent文本 + :return: 当前对象 + """ + ... - def ignore_certificate_errors(self, on_off=True) -> ChromiumOptions: ... + def set_proxy(self, proxy: str) -> ChromiumOptions: + """设置代理 + :param proxy: 代理url和端口 + :return: 当前对象 + """ + ... - def set_load_mode(self, value: Literal['normal', 'eager', 'none']) -> ChromiumOptions: ... + def set_load_mode(self, value: Literal['normal', 'eager', 'none']) -> ChromiumOptions: + """设置load_mode,可接收 'normal', 'eager', 'none' + normal:默认情况下使用, 等待所有资源下载完成 + eager:DOM访问已准备就绪, 但其他资源 (如图像) 可能仍在加载中 + none:完全不阻塞 + :param value: 可接收 'normal', 'eager', 'none' + :return: 当前对象 + """ + ... - def set_browser_path(self, path: Union[str, Path]) -> ChromiumOptions: ... + def set_local_port(self, port: Union[str, int]) -> ChromiumOptions: + """设置本地启动端口 + :param port: 端口号 + :return: 当前对象 + """ + ... - def set_local_port(self, port: Union[str, int]) -> ChromiumOptions: ... + def set_address(self, address: str) -> ChromiumOptions: + """设置浏览器地址,格式'ip:port' + :param address: 浏览器地址 + :return: 当前对象 + """ + ... - def set_address(self, address: str) -> ChromiumOptions: ... + def set_browser_path(self, path: Union[str, Path]) -> ChromiumOptions: + """设置浏览器可执行文件路径 + :param path: 浏览器路径 + :return: 当前对象 + """ + ... - def set_download_path(self, path: Union[str, Path]) -> ChromiumOptions: ... + def set_download_path(self, path: Union[str, Path]) -> ChromiumOptions: + """设置下载文件保存路径 + :param path: 下载路径 + :return: 当前对象 + """ + ... - def set_tmp_path(self, path: Union[str, Path]) -> ChromiumOptions: ... + def set_tmp_path(self, path: Union[str, Path]) -> ChromiumOptions: + """设置临时文件文件保存路径 + :param path: 下载路径 + :return: 当前对象 + """ + ... - def set_user_data_path(self, path: Union[str, Path]) -> ChromiumOptions: ... + def set_user_data_path(self, path: Union[str, Path]) -> ChromiumOptions: + """设置用户文件夹路径 + :param path: 用户文件夹路径 + :return: 当前对象 + """ + ... - def set_cache_path(self, path: Union[str, Path]) -> ChromiumOptions: ... + def set_cache_path(self, path: Union[str, Path]) -> ChromiumOptions: + """设置缓存路径 + :param path: 缓存路径 + :return: 当前对象 + """ + ... def set_paths(self, browser_path: Union[str, Path] = None, local_port: Union[int, str] = None, address: str = None, download_path: Union[str, Path] = None, user_data_path: Union[str, Path] = None, cache_path: Union[str, Path] = None) -> ChromiumOptions: ... - def use_system_user_path(self, on_off: bool = True) -> ChromiumOptions: ... + def use_system_user_path(self, on_off: bool = True) -> ChromiumOptions: + """设置是否使用系统安装的浏览器默认用户文件夹 + :param on_off: 开或关 + :return: 当前对象 + """ + ... def auto_port(self, on_off: bool = True, - scope: Tuple[int, int] = None) -> ChromiumOptions: ... + scope: Tuple[int, int] = None) -> ChromiumOptions: + """自动获取可用端口 + :param on_off: 是否开启自动获取端口号 + :param scope: 指定端口范围,不含最后的数字,为None则使用[9600-59600) + :return: 当前对象 + """ + ... - def existing_only(self, on_off: bool = True) -> ChromiumOptions: ... + def existing_only(self, on_off: bool = True) -> ChromiumOptions: + """设置只接管已有浏览器,不自动启动新的 + :param on_off: 是否开启自动获取端口号 + :return: 当前对象 + """ + ... - def save(self, path: Union[str, Path] = None) -> str: ... + def save(self, path: Union[str, Path] = None) -> str: + """保存设置到文件 + :param path: ini文件的路径, None 保存到当前读取的配置文件,传入 'default' 保存到默认ini文件 + :return: 保存文件的绝对路径 + """ + ... - def save_to_default(self) -> str: ... + def save_to_default(self) -> str: + """保存当前配置到默认ini文件""" + ... diff --git a/DrissionPage/_configs/options_manage.py b/DrissionPage/_configs/options_manage.py index 6638c50..a8d02a8 100644 --- a/DrissionPage/_configs/options_manage.py +++ b/DrissionPage/_configs/options_manage.py @@ -14,9 +14,6 @@ class OptionsManager(object): """管理配置文件内容的类""" def __init__(self, path=None): - """初始化,读取配置文件,如没有设置临时文件夹,则设置并新建 - :param path: ini文件的路径,为None则找项目文件夹下的,找不到则读取模块文件夹下的 - """ if path is False: self.ini_path = None else: @@ -79,18 +76,9 @@ class OptionsManager(object): self.set_item('others', 'retry_interval', '2') def __getattr__(self, item): - """以dict形似返回获取大项信息 - :param item: 项名 - :return: None - """ return self.get_option(item) def get_value(self, section, item): - """获取配置的值 - :param section: 段名 - :param item: 项名 - :return: 项值 - """ try: return eval(self._conf.get(section, item)) except (SyntaxError, NameError): @@ -99,10 +87,6 @@ class OptionsManager(object): return None def get_option(self, section): - """把section内容以字典方式返回 - :param section: 段名 - :return: 段内容生成的字典 - """ items = self._conf.items(section) option = dict() @@ -115,30 +99,15 @@ class OptionsManager(object): return option def set_item(self, section, item, value): - """设置配置值 - :param section: 段名 - :param item: 项名 - :param value: 项值 - :return: None - """ self._conf.set(section, item, str(value)) self.__setattr__(f'_{section}', None) return self def remove_item(self, section, item): - """删除配置值 - :param section: 段名 - :param item: 项名 - :return: None - """ self._conf.remove_option(section, item) return self def save(self, path=None): - """保存配置文件 - :param path: ini文件的路径,传入 'default' 保存到默认ini文件 - :return: 保存路径 - """ default_path = (Path(__file__).parent / 'configs.ini').absolute() if path == 'default': path = default_path @@ -163,11 +132,9 @@ class OptionsManager(object): return path def save_to_default(self): - """保存当前配置到默认ini文件""" return self.save('default') def show(self): - """打印所有设置信息""" for i in self._conf.sections(): print(f'[{i}]') pprint(self.get_option(i)) diff --git a/DrissionPage/_configs/options_manage.pyi b/DrissionPage/_configs/options_manage.pyi index f2b0483..7260644 100644 --- a/DrissionPage/_configs/options_manage.pyi +++ b/DrissionPage/_configs/options_manage.pyi @@ -15,20 +15,62 @@ class OptionsManager(object): file_exists: bool = ... _conf: RawConfigParser = ... - def __init__(self, path: Union[Path, str] = None): ... + def __init__(self, path: Union[Path, str] = None): + """初始化,读取配置文件,如没有设置临时文件夹,则设置并新建 + :param path: ini文件的路径,为None则找项目文件夹下的,找不到则读取模块文件夹下的 + """ + ... - def __getattr__(self, item) -> dict: ... + def __getattr__(self, item) -> dict: + """以dict形似返回获取大项信息 + :param item: 项名 + :return: None + """ + ... - def get_value(self, section: str, item: str) -> Any: ... + def get_value(self, section: str, item: str) -> Any: + """获取配置的值 + :param section: 段名 + :param item: 项名 + :return: 项值 + """ + ... - def get_option(self, section: str) -> dict: ... + def get_option(self, section: str) -> dict: + """把section内容以字典方式返回 + :param section: 段名 + :return: 段内容生成的字典 + """ + ... - def set_item(self, section: str, item: str, value: Any) -> None: ... + def set_item(self, section: str, item: str, value: Any) -> None: + """设置配置值 + :param section: 段名 + :param item: 项名 + :param value: 项值 + :return: None + """ + ... - def remove_item(self, section: str, item: str) -> None: ... + def remove_item(self, section: str, item: str) -> None: + """删除配置值 + :param section: 段名 + :param item: 项名 + :return: None + """ + ... - def save(self, path: str = None) -> str: ... + def save(self, path: str = None) -> str: + """保存配置文件 + :param path: ini文件的路径,传入 'default' 保存到默认ini文件 + :return: 保存路径 + """ + ... - def save_to_default(self) -> str: ... + def save_to_default(self) -> str: + """保存当前配置到默认ini文件""" + ... - def show(self) -> None: ... + def show(self) -> None: + """打印所有设置信息""" + ... diff --git a/DrissionPage/_configs/session_options.py b/DrissionPage/_configs/session_options.py index 9794395..ff6c7d4 100644 --- a/DrissionPage/_configs/session_options.py +++ b/DrissionPage/_configs/session_options.py @@ -17,13 +17,8 @@ from .._functions.web import format_headers class SessionOptions(object): - """requests的Session对象配置类""" def __init__(self, read_file=True, ini_path=None): - """ - :param read_file: 是否从文件读取配置 - :param ini_path: ini文件路径 - """ self.ini_path = None self._download_path = '.' self._timeout = 10 @@ -93,62 +88,39 @@ class SessionOptions(object): # ===========须独立处理的项开始============ @property def download_path(self): - """返回默认下载路径属性信息""" return self._download_path def set_download_path(self, path): - """设置默认下载路径 - :param path: 下载路径 - :return: 返回当前对象 - """ self._download_path = '.' if path is None else str(path) return self @property def timeout(self): - """返回timeout属性信息""" return self._timeout def set_timeout(self, second): - """设置超时信息 - :param second: 秒数 - :return: 返回当前对象 - """ self._timeout = second return self @property def proxies(self): - """返回proxies设置信息""" if self._proxies is None: self._proxies = {} return self._proxies def set_proxies(self, http=None, https=None): - """设置proxies参数 - :param http: http代理地址 - :param https: https代理地址 - :return: 返回当前对象 - """ self._sets('proxies', {'http': http, 'https': https}) return self @property def retry_times(self): - """返回连接失败时的重试次数""" return self._retry_times @property def retry_interval(self): - """返回连接失败时的重试间隔(秒)""" return self._retry_interval def set_retry(self, times=None, interval=None): - """设置连接失败时的重试操作 - :param times: 重试次数 - :param interval: 重试间隔 - :return: 当前对象 - """ if times is not None: self._retry_times = times if interval is not None: @@ -159,16 +131,11 @@ class SessionOptions(object): @property def headers(self): - """返回headers设置信息""" if self._headers is None: self._headers = {} return self._headers def set_headers(self, headers): - """设置headers参数 - :param headers: 参数值,传入None可在ini文件标记删除 - :return: 返回当前对象 - """ if headers is None: self._headers = None self._del_set.add('headers') @@ -178,11 +145,6 @@ class SessionOptions(object): return self def set_a_header(self, name, value): - """设置headers中一个项 - :param name: 设置名称 - :param value: 设置值 - :return: 返回当前对象 - """ if self._headers is None: self._headers = {} @@ -190,10 +152,6 @@ class SessionOptions(object): return self def remove_a_header(self, name): - """从headers中删除一个设置 - :param name: 要删除的设置 - :return: 返回当前对象 - """ if self._headers is None: return self @@ -202,156 +160,99 @@ class SessionOptions(object): return self def clear_headers(self): - """清空已设置的header参数""" self._headers = None self._del_set.add('headers') @property def cookies(self): - """以list形式返回cookies""" if self._cookies is None: self._cookies = [] return self._cookies def set_cookies(self, cookies): - """设置一个或多个cookies信息 - :param cookies: cookies,可为Cookie, CookieJar, list, tuple, str, dict,传入None可在ini文件标记删除 - :return: 返回当前对象 - """ cookies = cookies if cookies is None else list(cookies_to_tuple(cookies)) self._sets('cookies', cookies) return self @property def auth(self): - """返回认证设置信息""" return self._auth def set_auth(self, auth): - """设置认证元组或对象 - :param auth: 认证元组或对象 - :return: 返回当前对象 - """ self._sets('auth', auth) return self @property def hooks(self): - """返回回调方法""" if self._hooks is None: self._hooks = {} return self._hooks def set_hooks(self, hooks): - """设置回调方法 - :param hooks: 回调方法 - :return: 返回当前对象 - """ self._hooks = hooks return self @property def params(self): - """返回连接参数设置信息""" if self._params is None: self._params = {} return self._params def set_params(self, params): - """设置查询参数字典 - :param params: 查询参数字典 - :return: 返回当前对象 - """ self._sets('params', params) return self @property def verify(self): - """返回是否验证SSL证书设置""" return self._verify def set_verify(self, on_off): - """设置是否验证SSL证书 - :param on_off: 是否验证 SSL 证书 - :return: 返回当前对象 - """ self._sets('verify', on_off) return self @property def cert(self): - """返回SSL证书设置信息""" return self._cert def set_cert(self, cert): - """SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组 - :param cert: 证书路径或元组 - :return: 返回当前对象 - """ self._sets('cert', cert) return self @property def adapters(self): - """返回适配器设置信息""" if self._adapters is None: self._adapters = [] return self._adapters def add_adapter(self, url, adapter): - """添加适配器 - :param url: 适配器对应url - :param adapter: 适配器对象 - :return: 返回当前对象 - """ self._adapters.append((url, adapter)) return self @property def stream(self): - """返回是否使用流式响应内容设置信息""" return self._stream def set_stream(self, on_off): - """设置是否使用流式响应内容 - :param on_off: 是否使用流式响应内容 - :return: 返回当前对象 - """ self._sets('stream', on_off) return self @property def trust_env(self): - """返回是否信任环境设置信息""" return self._trust_env def set_trust_env(self, on_off): - """设置是否信任环境 - :param on_off: 是否信任环境 - :return: 返回当前对象 - """ self._sets('trust_env', on_off) return self @property def max_redirects(self): - """返回最大重定向次数""" return self._max_redirects def set_max_redirects(self, times): - """设置最大重定向次数 - :param times: 最大重定向次数 - :return: 返回当前对象 - """ self._sets('max_redirects', times) return self def _sets(self, arg, val): - """给属性赋值或标记删除 - :param arg: 属性名称 - :param val: 参数值 - :return: None - """ if val is None: self.__setattr__(f'_{arg}', None) self._del_set.add(arg) @@ -361,10 +262,6 @@ class SessionOptions(object): self._del_set.remove(arg) def save(self, path=None): - """保存设置到文件 - :param path: ini文件的路径,传入 'default' 保存到默认ini文件 - :return: 保存文件的绝对路径 - """ if path == 'default': path = (Path(__file__).parent / 'configs.ini').absolute() @@ -412,15 +309,12 @@ class SessionOptions(object): return path def save_to_default(self): - """保存当前配置到默认ini文件""" return self.save('default') def as_dict(self): - """以字典形式返回本对象""" return session_options_to_dict(self) def make_session(self): - """根据内在的配置生成Session对象,headers从对象中分离""" s = Session() h = CaseInsensitiveDict(self.headers) if self.headers else CaseInsensitiveDict() @@ -438,11 +332,6 @@ class SessionOptions(object): return s, h def from_session(self, session, headers=None): - """从Session对象中读取配置 - :param session: Session对象 - :param headers: headers - :return: 当前对象 - """ self._headers = CaseInsensitiveDict(copy(session.headers).update(headers)) if headers else session.headers self._cookies = session.cookies self._auth = session.auth @@ -463,10 +352,6 @@ class SessionOptions(object): def session_options_to_dict(options): - """把session配置对象转换为字典 - :param options: session配置对象或字典 - :return: 配置字典 - """ if options in (False, None): return SessionOptions(read_file=False).as_dict() diff --git a/DrissionPage/_configs/session_options.pyi b/DrissionPage/_configs/session_options.pyi index 54a88af..c55e37c 100644 --- a/DrissionPage/_configs/session_options.pyi +++ b/DrissionPage/_configs/session_options.pyi @@ -12,125 +12,287 @@ from typing import Any, Union, Tuple, Optional from requests import Session from requests.adapters import HTTPAdapter from requests.auth import HTTPBasicAuth +from requests.cookies import RequestsCookieJar from requests.structures import CaseInsensitiveDict class SessionOptions(object): - def __init__(self, read_file: [bool, None] = True, ini_path: Union[str, Path] = None): - self.ini_path: str = ... - self._download_path: str = ... - self._headers: dict = ... - self._cookies: list = ... - self._auth: tuple = ... - self._proxies: dict = ... - self._hooks: dict = ... - self._params: dict = ... - self._verify: bool = ... - self._cert: Union[str, tuple] = ... - self._adapters: list = ... - self._stream: bool = ... - self._trust_env: bool = ... - self._max_redirects: int = ... - self._timeout: float = ... - self._del_set: set = ... - self._retry_times: int = ... - self._retry_interval: float = ... + """requests的Session对象配置类""" + + ini_path: Optional[str] = ... + _download_path: str = ... + _headers: Union[dict, CaseInsensitiveDict, None] = ... + _cookies: Union[list, RequestsCookieJar, None] = ... + _auth: Optional[tuple] = ... + _proxies: Optional[dict] = ... + _hooks: Optional[dict] = ... + _params: Union[dict, None] = ... + _verify: Optional[bool] = ... + _cert: Union[str, tuple, None] = ... + _adapters: Optional[list] = ... + _stream: Optional[bool] = ... + _trust_env: Optional[bool] = ... + _max_redirects: Optional[int] = ... + _timeout: float = ... + _del_set: set = ... + _retry_times: int = ... + _retry_interval: float = ... + + def __init__(self, + read_file: [bool, None] = True, + ini_path: Union[str, Path] = None): + """ + :param read_file: 是否从文件读取配置 + :param ini_path: ini文件路径 + """ + ... @property - def download_path(self) -> str: ... + def download_path(self) -> str: + """返回默认下载路径属性信息""" + ... - def set_download_path(self, path: Union[str, Path]) -> SessionOptions: ... + def set_download_path(self, path: Union[str, Path]) -> SessionOptions: + """设置默认下载路径 + :param path: 下载路径 + :return: 返回当前对象 + """ + ... @property - def timeout(self) -> float: ... + def timeout(self) -> float: + """返回timeout属性信息""" + ... - def set_timeout(self, second: float) -> SessionOptions: ... + def set_timeout(self, second: float) -> SessionOptions: + """设置超时信息 + :param second: 秒数 + :return: 返回当前对象 + """ + ... @property - def headers(self) -> dict: ... + def proxies(self) -> dict: + """返回proxies设置信息""" + ... - def set_headers(self, headers: Union[dict, str, None]) -> SessionOptions: ... - - def set_a_header(self, name: str, value: str) -> SessionOptions: ... - - def remove_a_header(self, name: str) -> SessionOptions: ... - - def clear_headers(self) -> SessionOptions: ... + def set_proxies(self, http: Union[str, None], https: Union[str, None] = None) -> SessionOptions: + """设置proxies参数 + :param http: http代理地址 + :param https: https代理地址 + :return: 返回当前对象 + """ + ... @property - def cookies(self) -> list: ... - - def set_cookies(self, cookies: Union[Cookie, CookieJar, list, tuple, str, dict, None]) -> SessionOptions: ... + def retry_times(self) -> int: + """返回连接失败时的重试次数""" + ... @property - def auth(self) -> Union[Tuple[str, str], HTTPBasicAuth]: ... + def retry_interval(self) -> float: + """返回连接失败时的重试间隔(秒)""" + ... - def set_auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) -> SessionOptions: ... + def set_retry(self, times: int = None, interval: float = None) -> SessionOptions: + """设置连接失败时的重试操作 + :param times: 重试次数 + :param interval: 重试间隔 + :return: 当前对象 + """ + ... @property - def proxies(self) -> dict: ... + def headers(self) -> dict: + """返回headers设置信息""" + ... - def set_proxies(self, http: Union[str, None], https: Union[str, None] = None) -> SessionOptions: ... + def set_headers(self, headers: Union[dict, str, None]) -> SessionOptions: + """设置headers参数 + :param headers: 参数值,传入None可在ini文件标记删除 + :return: 返回当前对象 + """ + ... + + def set_a_header(self, name: str, value: str) -> SessionOptions: + """设置headers中一个项 + :param name: 设置名称 + :param value: 设置值 + :return: 返回当前对象 + """ + ... + + def remove_a_header(self, name: str) -> SessionOptions: + """从headers中删除一个设置 + :param name: 要删除的设置 + :return: 返回当前对象 + """ + ... + + def clear_headers(self) -> SessionOptions: + """清空已设置的header参数""" + ... @property - def retry_times(self) -> int: ... + def cookies(self) -> list: + """以list形式返回cookies""" + ... + + def set_cookies(self, cookies: Union[Cookie, CookieJar, list, tuple, str, dict, None]) -> SessionOptions: + """设置一个或多个cookies信息 + :param cookies: cookies,可为Cookie, CookieJar, list, tuple, str, dict,传入None可在ini文件标记删除 + :return: 返回当前对象 + """ + ... @property - def retry_interval(self) -> float: ... + def auth(self) -> Union[Tuple[str, str], HTTPBasicAuth]: + """返回认证设置信息""" + ... - def set_retry(self, times: int = None, interval: float = None) -> SessionOptions: ... + def set_auth(self, auth: Union[Tuple[str, str], HTTPBasicAuth, None]) -> SessionOptions: + """设置认证元组或对象 + :param auth: 认证元组或对象 + :return: 返回当前对象 + """ + ... @property - def hooks(self) -> dict: ... + def hooks(self) -> dict: + """返回回调方法""" + ... - def set_hooks(self, hooks: Union[dict, None]) -> SessionOptions: ... + def set_hooks(self, hooks: Union[dict, None]) -> SessionOptions: + """设置回调方法 + :param hooks: 回调方法 + :return: 返回当前对象 + """ + ... @property - def params(self) -> dict: ... + def params(self) -> dict: + """返回连接参数设置信息""" + ... - def set_params(self, params: Union[dict, None]) -> SessionOptions: ... + def set_params(self, params: Union[dict, None]) -> SessionOptions: + """设置查询参数字典 + :param params: 查询参数字典 + :return: 返回当前对象 + """ + ... @property - def verify(self) -> bool: ... + def verify(self) -> bool: + """返回是否验证SSL证书设置""" + ... - def set_verify(self, on_off: Union[bool, None]) -> SessionOptions: ... + def set_verify(self, on_off: Union[bool, None]) -> SessionOptions: + """设置是否验证SSL证书 + :param on_off: 是否验证 SSL 证书 + :return: 返回当前对象 + """ + ... @property - def cert(self) -> Union[str, tuple]: ... + def cert(self) -> Union[str, tuple]: + """返回SSL证书设置信息""" + ... - def set_cert(self, cert: Union[str, Tuple[str, str], None]) -> SessionOptions: ... + def set_cert(self, cert: Union[str, Tuple[str, str], None]) -> SessionOptions: + """SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组 + :param cert: 证书路径或元组 + :return: 返回当前对象 + """ + ... @property - def adapters(self): list: ... + def adapters(self) -> list: + """返回适配器设置信息""" + ... - def add_adapter(self, url: str, adapter: HTTPAdapter) -> SessionOptions: ... + def add_adapter(self, url: str, adapter: HTTPAdapter) -> SessionOptions: + """添加适配器 + :param url: 适配器对应url + :param adapter: 适配器对象 + :return: 返回当前对象 + """ + ... @property - def stream(self) -> bool: ... + def stream(self) -> bool: + """返回是否使用流式响应内容设置信息""" + ... - def set_stream(self, on_off: Union[bool, None]) -> SessionOptions: ... + def set_stream(self, on_off: Union[bool, None]) -> SessionOptions: + """设置是否使用流式响应内容 + :param on_off: 是否使用流式响应内容 + :return: 返回当前对象 + """ + ... @property - def trust_env(self) -> bool: ... + def trust_env(self) -> bool: + """返回是否信任环境设置信息""" + ... - def set_trust_env(self, on_off: Union[bool, None]) -> SessionOptions: ... + def set_trust_env(self, on_off: Union[bool, None]) -> SessionOptions: + """设置是否信任环境 + :param on_off: 是否信任环境 + :return: 返回当前对象 + """ + ... @property - def max_redirects(self) -> int: ... + def max_redirects(self) -> int: + """返回最大重定向次数""" + ... - def set_max_redirects(self, times: Union[int, None]) -> SessionOptions: ... + def set_max_redirects(self, times: Union[int, None]) -> SessionOptions: + """设置最大重定向次数 + :param times: 最大重定向次数 + :return: 返回当前对象 + """ + ... - def _sets(self, arg: str, val: Any) -> None: ... + def _sets(self, arg: str, val: Any) -> None: + """给属性赋值或标记删除 + :param arg: 属性名称 + :param val: 参数值 + :return: None + """ + ... - def save(self, path: str = None) -> str: ... + def save(self, path: str = None) -> str: + """保存设置到文件 + :param path: ini文件的路径,传入 'default' 保存到默认ini文件 + :return: 保存文件的绝对路径 + """ + ... - def save_to_default(self) -> str: ... + def save_to_default(self) -> str: + """保存当前配置到默认ini文件""" + ... - def as_dict(self) -> dict: ... + def as_dict(self) -> dict: + """以字典形式返回本对象""" + ... - def make_session(self) -> Tuple[Session, Optional[CaseInsensitiveDict]]: ... + def make_session(self) -> Tuple[Session, Optional[CaseInsensitiveDict]]: + """根据内在的配置生成Session对象,headers从对象中分离""" + ... - def from_session(self, session: Session, headers: CaseInsensitiveDict = None) -> SessionOptions: ... + def from_session(self, session: Session, headers: CaseInsensitiveDict = None) -> SessionOptions: + """从Session对象中读取配置 + :param session: Session对象 + :param headers: headers + :return: 当前对象 + """ + ... -def session_options_to_dict(options: Union[dict, SessionOptions, None]) -> Union[dict, None]: ... +def session_options_to_dict(options: Union[dict, SessionOptions, None]) -> Union[dict, None]: + """把session配置对象转换为字典 + :param options: session配置对象或字典 + :return: 配置字典 + """ + ... diff --git a/DrissionPage/_elements/chromium_element.py b/DrissionPage/_elements/chromium_element.py index ecaa47f..8754c2d 100644 --- a/DrissionPage/_elements/chromium_element.py +++ b/DrissionPage/_elements/chromium_element.py @@ -566,6 +566,8 @@ class ChromiumElement(DrissionElement): else: self.owner.actions.type(vals) + return self + def clear(self, by_js=False): if by_js: self._run_js("this.value='';") @@ -574,6 +576,7 @@ class ChromiumElement(DrissionElement): self._input_focus() self.input(('\ue009', 'a', '\ue017'), clear=False) + return self def _input_focus(self): try: @@ -586,15 +589,18 @@ class ChromiumElement(DrissionElement): self.owner._run_cdp('DOM.focus', backendNodeId=self._backend_id) except Exception: self._run_js('this.focus();') + return self def hover(self, offset_x=None, offset_y=None): self.owner.actions.move_to(self, offset_x=offset_x, offset_y=offset_y, duration=.1) + return self def drag(self, offset_x=0, offset_y=0, duration=.5): curr_x, curr_y = self.rect.midpoint offset_x += curr_x offset_y += curr_y self.drag_to((offset_x, offset_y), duration) + return self def drag_to(self, ele_or_loc, duration=.5): if isinstance(ele_or_loc, ChromiumElement): @@ -602,6 +608,7 @@ class ChromiumElement(DrissionElement): elif not isinstance(ele_or_loc, (list, tuple)): raise TypeError('需要ChromiumElement对象或坐标。') self.owner.actions.hold(self).move_to(ele_or_loc, duration=duration).release() + return self def _get_obj_id(self, node_id=None, backend_id=None): if node_id: @@ -675,6 +682,7 @@ class ChromiumElement(DrissionElement): files = files.split('\n') files = [str(Path(i).absolute()) for i in files] self.owner._run_cdp('DOM.setFileInputFiles', files=files, backendNodeId=self._backend_id) + return self class ShadowRoot(BaseElement): diff --git a/DrissionPage/_elements/chromium_element.pyi b/DrissionPage/_elements/chromium_element.pyi index 415d8ec..181ef05 100644 --- a/DrissionPage/_elements/chromium_element.pyi +++ b/DrissionPage/_elements/chromium_element.pyi @@ -526,7 +526,7 @@ class ChromiumElement(DrissionElement): """ ... - def input(self, vals: Any, clear: bool = False, by_js: bool = False) -> None: + def input(self, vals: Any, clear: bool = False, by_js: bool = False) -> ChromiumElement: """输入文本或组合键,也可用于输入文件路径到input元素(路径间用\n间隔) :param vals: 文本值或按键组合 :param clear: 输入前是否清空文本框 @@ -535,7 +535,7 @@ class ChromiumElement(DrissionElement): """ ... - def clear(self, by_js: bool = False) -> None: + def clear(self, by_js: bool = False) -> ChromiumElement: """清空元素文本 :param by_js: 是否用js方式清空,为False则用全选+del模拟输入删除 :return: None @@ -546,11 +546,11 @@ class ChromiumElement(DrissionElement): """输入前使元素获取焦点""" ... - def focus(self) -> None: + def focus(self) -> ChromiumElement: """使元素获取焦点""" ... - def hover(self, offset_x: int = None, offset_y: int = None) -> None: + def hover(self, offset_x: int = None, offset_y: int = None) -> ChromiumElement: """鼠标悬停,可接受偏移量,偏移量相对于元素左上角坐标。不传入offset_x和offset_y值时悬停在元素中点 :param offset_x: 相对元素左上角坐标的x轴偏移量 :param offset_y: 相对元素左上角坐标的y轴偏移量 @@ -558,7 +558,7 @@ class ChromiumElement(DrissionElement): """ ... - def drag(self, offset_x: int = 0, offset_y: int = 0, duration: float = 0.5) -> None: + def drag(self, offset_x: int = 0, offset_y: int = 0, duration: float = 0.5) -> ChromiumElement: """拖拽当前元素到相对位置 :param offset_x: x变化值 :param offset_y: y变化值 @@ -567,7 +567,9 @@ class ChromiumElement(DrissionElement): """ ... - def drag_to(self, ele_or_loc: Union[Tuple[int, int], str, ChromiumElement], duration: float = 0.5) -> None: + def drag_to(self, + ele_or_loc: Union[Tuple[int, int], str, ChromiumElement], + duration: float = 0.5) -> ChromiumElement: """拖拽当前元素,目标为另一个元素或坐标元组(x, y) :param ele_or_loc: 另一个元素或坐标元组,坐标为元素中点的坐标 :param duration: 拖动用时,传入0即瞬间到达 diff --git a/DrissionPage/_elements/none_element.py b/DrissionPage/_elements/none_element.py index 31e04e6..c583562 100644 --- a/DrissionPage/_elements/none_element.py +++ b/DrissionPage/_elements/none_element.py @@ -11,11 +11,6 @@ from ..errors import ElementNotFoundError class NoneElement(object): def __init__(self, page=None, method=None, args=None): - """ - :param page: 元素所在页面 - :param method: 查找元素的方法 - :param args: 查找元素的参数 - """ if method and Settings.raise_when_ele_not_found: # 无传入method时不自动抛出,由调用者处理 raise ElementNotFoundError(None, method=method, arguments=args) @@ -49,11 +44,10 @@ class NoneElement(object): raise ElementNotFoundError(None, self.method, self.args) def __eq__(self, other): - if other is None: - return True + return other is None def __bool__(self): return False def __repr__(self): - return 'None' + return f'' diff --git a/DrissionPage/_elements/none_element.pyi b/DrissionPage/_elements/none_element.pyi new file mode 100644 index 0000000..deeae48 --- /dev/null +++ b/DrissionPage/_elements/none_element.pyi @@ -0,0 +1,32 @@ +# -*- coding:utf-8 -*- +""" +@Author : g1879 +@Contact : g1879@qq.com +@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. +@License : BSD 3-Clause. +""" +from typing import Any + +from .._base.base import BasePage + + +class NoneElement(object): + def __init__(self, page: BasePage = None, + method: str = None, + args: dict = None): + """ + :param page: 元素所在页面 + :param method: 查找元素的方法 + :param args: 查找元素的参数 + """ + ... + + def __call__(self, *args, **kwargs) -> NoneElement: ... + + def __getattr__(self, item: str) -> str: ... + + def __eq__(self, other: Any) -> bool: ... + + def __bool__(self) -> bool: ... + + def __repr__(self) -> str: ... diff --git a/DrissionPage/_functions/browser.py b/DrissionPage/_functions/browser.py index 895bd94..250db6a 100644 --- a/DrissionPage/_functions/browser.py +++ b/DrissionPage/_functions/browser.py @@ -21,10 +21,6 @@ from ..errors import BrowserConnectError def connect_browser(option): - """连接或启动浏览器 - :param option: ChromiumOptions对象 - :return: 返回是否接管的浏览器 - """ address = option.address.replace('localhost', '127.0.0.1').lstrip('http://').lstrip('https://') browser_path = option.browser_path @@ -67,10 +63,6 @@ def connect_browser(option): def get_launch_args(opt): - """从ChromiumOptions获取命令行启动参数 - :param opt: ChromiumOptions - :return: 启动参数列表 - """ # ----------处理arguments----------- result = set() user_path = False @@ -107,10 +99,6 @@ def get_launch_args(opt): def set_prefs(opt): - """处理启动配置中的prefs项,目前只能对已存在文件夹配置 - :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 @@ -149,10 +137,6 @@ def set_prefs(opt): def set_flags(opt): - """处理启动配置中的flags项 - :param opt: ChromiumOptions - :return: None - """ if not opt.user_data_path or (not opt.clear_file_flags and not opt.flags): return @@ -185,12 +169,6 @@ def set_flags(opt): def test_connect(ip, port, timeout=30): - """测试浏览器是否可用 - :param ip: 浏览器ip - :param port: 浏览器端口 - :param timeout: 超时时间(秒) - :return: None - """ end_time = perf_counter() + timeout s = Session() s.trust_env = False @@ -276,7 +254,6 @@ def _remove_arg_from_dict(target_dict: dict, arg: str) -> None: def get_chrome_path(ini_path): - """从ini文件或系统变量中获取chrome可执行文件的路径""" # -----------从ini文件中获取-------------- if ini_path and Path(ini_path).exists(): path = OptionsManager(ini_path).chromium_options.get('browser_path', None) diff --git a/DrissionPage/_functions/browser.pyi b/DrissionPage/_functions/browser.pyi index ff7bdc6..d43f561 100644 --- a/DrissionPage/_functions/browser.pyi +++ b/DrissionPage/_functions/browser.pyi @@ -10,19 +10,51 @@ from typing import Union from .._configs.chromium_options import ChromiumOptions -def connect_browser(option: ChromiumOptions) -> bool: ... +def connect_browser(option: ChromiumOptions) -> bool: + """连接或启动浏览器 + :param option: ChromiumOptions对象 + :return: 返回是否接管的浏览器 + """ + ... -def get_launch_args(opt: ChromiumOptions) -> list: ... +def get_launch_args(opt: ChromiumOptions) -> list: + """从ChromiumOptions获取命令行启动参数 + :param opt: ChromiumOptions + :return: 启动参数列表 + """ + ... -def set_prefs(opt: ChromiumOptions) -> None: ... +def set_prefs(opt: ChromiumOptions) -> None: + """处理启动配置中的prefs项,目前只能对已存在文件夹配置 + :param opt: ChromiumOptions + :return: None + """ + ... -def set_flags(opt: ChromiumOptions) -> None: ... +def set_flags(opt: ChromiumOptions) -> None: + """处理启动配置中的flags项 + :param opt: ChromiumOptions + :return: None + """ + ... -def test_connect(ip: str, port: Union[int, str], timeout: float = 30) -> bool: ... +def test_connect(ip: str, port: Union[int, str], timeout: float = 30) -> bool: + """测试浏览器是否可用 + :param ip: 浏览器ip + :param port: 浏览器端口 + :param timeout: 超时时间(秒) + :return: None + """ + ... -def get_chrome_path(ini_path: str) -> Union[str, None]: ... +def get_chrome_path(ini_path: str) -> Union[str, None]: + """从ini文件或系统变量中获取chrome可执行文件的路径 + :param ini_path: ini文件路径 + :return: 文件路径 + """ + ... diff --git a/DrissionPage/_functions/cookies.py b/DrissionPage/_functions/cookies.py index ee5bdcc..8c6a608 100644 --- a/DrissionPage/_functions/cookies.py +++ b/DrissionPage/_functions/cookies.py @@ -12,10 +12,6 @@ from tldextract import extract def cookie_to_dict(cookie): - """把Cookie对象转为dict格式 - :param cookie: Cookie对象、字符串或字典 - :return: cookie字典 - """ if isinstance(cookie, Cookie): cookie_dict = cookie.__dict__.copy() cookie_dict.pop('rfc2109', None) @@ -44,10 +40,6 @@ def cookie_to_dict(cookie): def cookies_to_tuple(cookies): - """把cookies转为tuple格式 - :param cookies: cookies信息,可为CookieJar, list, tuple, str, dict - :return: 返回tuple形式的cookies - """ if isinstance(cookies, (list, tuple, CookieJar)): cookies = tuple(cookie_to_dict(cookie) for cookie in cookies) @@ -74,11 +66,6 @@ def cookies_to_tuple(cookies): def set_session_cookies(session, cookies): - """设置Session对象的cookies - :param session: Session对象 - :param cookies: cookies信息 - :return: None - """ for cookie in cookies_to_tuple(cookies): if cookie['value'] is None: cookie['value'] = '' @@ -94,11 +81,6 @@ def set_session_cookies(session, cookies): def set_browser_cookies(browser, cookies): - """设置cookies值 - :param browser: 页面对象 - :param cookies: cookies信息 - :return: None - """ c = [] for cookie in cookies_to_tuple(cookies): if 'domain' not in cookie and 'url' not in cookie: @@ -108,11 +90,6 @@ def set_browser_cookies(browser, cookies): def set_tab_cookies(page, cookies): - """设置cookies值 - :param page: 页面对象 - :param cookies: cookies信息 - :return: None - """ for cookie in cookies_to_tuple(cookies): cookie = format_cookie(cookie) @@ -154,11 +131,6 @@ def set_tab_cookies(page, cookies): def is_cookie_in_driver(page, cookie): - """查询cookie是否在浏览器内 - :param page: BasePage对象 - :param cookie: dict格式cookie - :return: bool - """ if 'domain' in cookie: for c in page.cookies(all_domains=True): if cookie['name'] == c['name'] and cookie['value'] == c['value'] and cookie['domain'] == c.get('domain', @@ -172,10 +144,6 @@ def is_cookie_in_driver(page, cookie): def format_cookie(cookie): - """设置cookie为可用格式 - :param cookie: dict格式cookie - :return: 格式化后的cookie字典 - """ if 'expiry' in cookie: cookie['expires'] = int(cookie['expiry']) cookie.pop('expiry') @@ -235,15 +203,12 @@ def format_cookie(cookie): class CookiesList(list): def as_dict(self): - """以dict格式返回,只包含name和value字段""" return {c['name']: c['value'] for c in self} def as_str(self): - """以str格式返回,只包含name和value字段""" return '; '.join([f'{c["name"]}={c["value"]}' for c in self]) def as_json(self): - """以json格式返回""" from json import dumps return dumps(self) diff --git a/DrissionPage/_functions/cookies.pyi b/DrissionPage/_functions/cookies.pyi index d7b5d08..714620d 100644 --- a/DrissionPage/_functions/cookies.pyi +++ b/DrissionPage/_functions/cookies.pyi @@ -15,32 +15,80 @@ from .._base.browser import Chromium from .._pages.chromium_base import ChromiumBase -def cookie_to_dict(cookie: Union[Cookie, str, dict]) -> dict: ... +def cookie_to_dict(cookie: Union[Cookie, str, dict]) -> dict: + """把Cookie对象转为dict格式 + :param cookie: Cookie对象、字符串或字典 + :return: cookie字典 + """ + ... -def cookies_to_tuple(cookies: Union[RequestsCookieJar, list, tuple, str, dict, Cookie]) -> tuple: ... +def cookies_to_tuple(cookies: Union[RequestsCookieJar, list, tuple, str, dict, Cookie]) -> tuple: + """把cookies转为tuple格式 + :param cookies: cookies信息,可为CookieJar, list, tuple, str, dict + :return: 返回tuple形式的cookies + """ + ... -def set_session_cookies(session: Session, cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: ... +def set_session_cookies(session: Session, + cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: + """设置Session对象的cookies + :param session: Session对象 + :param cookies: cookies信息 + :return: None + """ + ... -def set_browser_cookies(browser: Chromium, cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: ... +def set_browser_cookies(browser: Chromium, + cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: + """设置cookies值 + :param browser: 页面对象 + :param cookies: cookies信息 + :return: None + """ + ... -def set_tab_cookies(page: ChromiumBase, cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: ... +def set_tab_cookies(page: ChromiumBase, + cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: + """设置cookies值 + :param page: 页面对象 + :param cookies: cookies信息 + :return: None + """ + ... -def is_cookie_in_driver(page: ChromiumBase, cookie: dict) -> bool: ... +def is_cookie_in_driver(page: ChromiumBase, cookie: dict) -> bool: + """查询cookie是否在浏览器内 + :param page: BasePage对象 + :param cookie: dict格式cookie + :return: bool + """ + ... -def format_cookie(cookie: dict) -> dict: ... +def format_cookie(cookie: dict) -> dict: + """设置cookie为可用格式 + :param cookie: dict格式cookie + :return: 格式化后的cookie字典 + """ + ... class CookiesList(list): - def as_dict(self) -> dict: ... + def as_dict(self) -> dict: + """以dict格式返回,只包含name和value字段""" + ... - def as_str(self) -> str: ... + def as_str(self) -> str: + """以str格式返回,只包含name和value字段""" + ... - def as_json(self) -> str: ... + def as_json(self) -> str: + """以json格式返回""" + ... def __next__(self) -> dict: ... diff --git a/DrissionPage/_functions/elements.py b/DrissionPage/_functions/elements.py index 2a459b4..ebafcb3 100644 --- a/DrissionPage/_functions/elements.py +++ b/DrissionPage/_functions/elements.py @@ -12,9 +12,9 @@ from .._elements.none_element import NoneElement class SessionElementsList(list): - def __init__(self, page=None, *args): + def __init__(self, owner=None, *args): super().__init__(*args) - self._page = page + self._owner = owner @property def get(self): @@ -56,17 +56,6 @@ class ChromiumElementsList(SessionElementsList): def search_one(self, index=1, displayed=None, checked=None, selected=None, enabled=None, clickable=None, have_rect=None, have_text=None): - """或关系筛选元素,获取一个结果 - :param index: 元素序号,从1开始 - :param displayed: 是否显示,bool,None为忽略该项 - :param checked: 是否被选中,bool,None为忽略该项 - :param selected: 是否被选择,bool,None为忽略该项 - :param enabled: 是否可用,bool,None为忽略该项 - :param clickable: 是否可点击,bool,None为忽略该项 - :param have_rect: 是否拥有大小和位置,bool,None为忽略该项 - :param have_text: 是否含有文本,bool,None为忽略该项 - :return: 筛选结果 - """ return _search_one(self, index=index, displayed=displayed, checked=checked, selected=selected, enabled=enabled, clickable=clickable, have_rect=have_rect, have_text=have_text) @@ -77,29 +66,13 @@ class SessionFilterOne(object): self._index = 1 def __call__(self, index=1): - """返回结果中第几个元素 - :param index: 元素序号,从1开始 - :return: 对象自身 - """ self._index = index return self def attr(self, name, value, equal=True): - """以是否拥有某个attribute值为条件筛选元素 - :param name: 属性名称 - :param value: 属性值 - :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 - :return: 筛选结果 - """ return self._get_attr(name, value, 'attr', equal=equal) def text(self, text, fuzzy=True, contain=True): - """以是否含有指定文本为条件筛选元素 - :param text: 用于匹配的文本 - :param fuzzy: 是否模糊匹配 - :param contain: 是否包含该字符串,False表示不包含 - :return: 筛选结果 - """ num = 0 if contain: for i in self._list: @@ -115,16 +88,10 @@ class SessionFilterOne(object): num += 1 if self._index == num: return i - return NoneElement(self._list._page, 'text()', + return NoneElement(self._list._owner, 'text()', args={'text': text, 'fuzzy': fuzzy, 'contain': contain, 'index': self._index}) def _get_attr(self, name, value, method, equal=True): - """返回通过某个方法可获得某个值的元素 - :param name: 属性名称 - :param value: 属性值 - :param method: 方法名称 - :return: 筛选结果 - """ num = 0 if equal: for i in self._list: @@ -138,7 +105,7 @@ class SessionFilterOne(object): num += 1 if self._index == num: return i - return NoneElement(self._list._page, f'{method}()', + return NoneElement(self._list._owner, f'{method}()', args={'name': name, 'value': value, 'equal': equal, 'index': self._index}) @@ -158,28 +125,15 @@ class SessionFilter(SessionFilterOne): @property def get(self): - """返回用于获取元素属性的对象""" return self._list.get def text(self, text, fuzzy=True, contain=True): - """以是否含有指定文本为条件筛选元素 - :param text: 用于匹配的文本 - :param fuzzy: 是否模糊匹配 - :param contain: 是否包含该字符串,False表示不包含 - :return: 筛选结果 - """ - self._list = _text_all(self._list, SessionElementsList(page=self._list._page), + self._list = _text_all(self._list, SessionElementsList(owner=self._list._owner), text=text, fuzzy=fuzzy, contain=contain) return self def _get_attr(self, name, value, method, equal=True): - """返回通过某个方法可获得某个值的元素 - :param name: 属性名称 - :param value: 属性值 - :param method: 方法名称 - :return: 筛选结果 - """ - self._list = _get_attr_all(self._list, SessionElementsList(page=self._list._page), + self._list = _get_attr_all(self._list, SessionElementsList(owner=self._list._owner), name=name, value=value, method=method, equal=equal) return self @@ -187,71 +141,30 @@ class SessionFilter(SessionFilterOne): class ChromiumFilterOne(SessionFilterOne): def displayed(self, equal=True): - """以是否显示为条件筛选元素 - :param equal: 是否匹配显示的元素,False匹配不显示的 - :return: 筛选结果 - """ return self._any_state('is_displayed', equal=equal) def checked(self, equal=True): - """以是否被选中为条件筛选元素 - :param equal: 是否匹配被选中的元素,False匹配不被选中的 - :return: 筛选结果 - """ return self._any_state('is_checked', equal=equal) def selected(self, equal=True): - """以是否被选择为条件筛选元素,用于元素项目 + :param equal: 是否匹配被选择的元素,False匹配不被选择的 + :return: 筛选结果 + """ + ... - def enabled(self, equal: bool = True) -> ChromiumElement: ... + def enabled(self, equal: bool = True) -> ChromiumElement: + """以是否可用为条件筛选元素 + :param equal: 是否匹配可用的元素,False表示匹配disabled状态的 + :return: 筛选结果 + """ + ... - def clickable(self, equal: bool = True) -> ChromiumElement: ... + def clickable(self, equal: bool = True) -> ChromiumElement: + """以是否可点击为条件筛选元素 + :param equal: 是否匹配可点击的元素,False表示匹配不是可点击的 + :return: 筛选结果 + """ + ... - def have_rect(self, equal: bool = True) -> ChromiumElement: ... + def have_rect(self, equal: bool = True) -> ChromiumElement: + """以是否有大小为条件筛选元素 + :param equal: 是否匹配有大小的元素,False表示匹配没有大小的 + :return: 筛选结果 + """ + ... - def style(self, name: str, value: str, equal: bool = True) -> ChromiumElement: ... + def style(self, name: str, value: str, equal: bool = True) -> ChromiumElement: + """以是否拥有某个style值为条件筛选元素 + :param name: 属性名称 + :param value: 属性值 + :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 + :return: 筛选结果 + """ + ... def property(self, name: str, - value: str, equal: bool = True) -> ChromiumElement: ... + value: str, equal: bool = True) -> ChromiumElement: + """以是否拥有某个property值为条件筛选元素 + :param name: 属性名称 + :param value: 属性值 + :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 + :return: 筛选结果 + """ + ... - def attr(self, name: str, value: str, equal: bool = True) -> ChromiumElement: ... + def attr(self, name: str, value: str, equal: bool = True) -> ChromiumElement: + """以是否拥有某个attribute值为条件筛选元素 + :param name: 属性名称 + :param value: 属性值 + :param equal: True表示匹配name值为value值的元素,False表示匹配name值不为value值的 + :return: 筛选结果 + """ + ... - def text(self, text: str, fuzzy: bool = True, contain: bool = True) -> ChromiumElement: ... + def text(self, + text: str, + fuzzy: bool = True, + contain: bool = True) -> ChromiumElement: + """以是否含有指定文本为条件筛选元素 + :param text: 用于匹配的文本 + :param fuzzy: 是否模糊匹配 + :param contain: 是否包含该字符串,False表示不包含 + :return: 筛选结果 + """ + ... def _get_attr(self, name: str, value: str, - method: str, equal: bool = True) -> ChromiumElement: ... + method: str, equal: bool = True) -> ChromiumElement: + """返回通过某个方法可获得某个值的元素 + :param name: 属性名称 + :param value: 属性值 + :param method: 方法名称 + :return: 筛选结果 + """ + ... - def _any_state(self, name: str, equal: bool = True) -> ChromiumElement: ... + def _any_state(self, name: str, equal: bool = True) -> ChromiumElement: + """ + :param name: 状态名称 + :param equal: 是否是指定状态,False表示否定状态 + :return: 选中的列表 + """ + ... class ChromiumFilter(ChromiumFilterOne): @@ -163,38 +329,80 @@ class ChromiumFilter(ChromiumFilterOne): def __getitem__(self, item: int) -> ChromiumElement: ... @property - def get(self) -> Getter: ... + def get(self) -> Getter: + """返回用于获取元素属性的对象""" + ... - def displayed(self, equal: bool = True) -> ChromiumFilter: ... + def displayed(self, equal: bool = True) -> ChromiumFilter: + """以是否显示为条件筛选元素 + :param equal: 是否匹配显示的元素,False匹配不显示的 + :return: 筛选结果 + """ + ... - def checked(self, equal: bool = True) -> ChromiumFilter: ... + def checked(self, equal: bool = True) -> ChromiumFilter: + """以是否被选中为条件筛选元素 + :param equal: 是否匹配被选中的元素,False匹配不被选中的 + :return: 筛选结果 + """ + ... - def selected(self, equal: bool = True) -> ChromiumFilter: ... + def selected(self, equal: bool = True) -> ChromiumFilter: + """以是否被选择为条件筛选元素,用于