diff --git a/DrissionPage/_pages/session_page.py b/DrissionPage/_pages/session_page.py index 4e39598..6843460 100644 --- a/DrissionPage/_pages/session_page.py +++ b/DrissionPage/_pages/session_page.py @@ -27,9 +27,6 @@ class SessionPage(BasePage): """SessionPage封装了页面操作的常用功能,使用requests来获取、解析网页""" def __init__(self, session_or_options=None): - """ - :param session_or_options: Session对象或SessionOptions对象 - """ super(SessionPage, SessionPage).__init__(self) self._headers = None self._response = None @@ -44,10 +41,6 @@ class SessionPage(BasePage): self._create_session() def _s_set_start_options(self, session_or_options): - """启动配置 - :param session_or_options: Session、SessionOptions对象 - :return: None - """ if not session_or_options: self._session_options = SessionOptions(session_or_options) @@ -61,57 +54,42 @@ class SessionPage(BasePage): self._session.headers = None def _s_set_runtime_settings(self): - """设置运行时用到的属性""" self._timeout = self._session_options.timeout self._download_path = str(Path(self._session_options.download_path or '.').absolute()) self.retry_times = self._session_options.retry_times self.retry_interval = self._session_options.retry_interval def _create_session(self): - """创建内建Session对象""" if not self._session: self._session, self._headers = self._session_options.make_session() def __call__(self, locator, index=1, timeout=None): - """在内部查找元素 - 例:ele2 = ele1('@id=ele_id') - :param locator: 元素的定位信息,可以是loc元组,或查询字符串 - :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 - :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 - :return: SessionElement对象或属性文本 - """ return self.ele(locator, index=index) # -----------------共有属性和方法------------------- @property def title(self): - """返回网页title""" ele = self._ele('xpath://title', raise_err=False) return ele.text if ele else None @property def url(self): - """返回当前访问url""" return self._url @property def _session_url(self): - """返回当前访问url""" return self._url @property def raw_data(self): - """返回页面原始数据""" return self.response.content if self.response else b'' @property def html(self): - """返回页面的html文本""" return self.response.text if self.response else '' @property def json(self): - """当返回内容是json格式时,返回对应的字典,非json格式时返回None""" try: return self.response.json() except Exception: @@ -119,34 +97,28 @@ class SessionPage(BasePage): @property def user_agent(self): - """返回user agent""" return self._headers.get('user-agent', '') @property def session(self): - """返回Session对象""" return self._session @property def response(self): - """返回访问url得到的Response对象""" return self._response @property def encoding(self): - """返回设置的编码""" return self._encoding @property def set(self): - """返回用于设置的对象""" if self._set is None: self._set = SessionPageSetter(self) return self._set @property def timeout(self): - """返回超时设置""" return self._timeout def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs): @@ -182,53 +154,21 @@ class SessionPage(BasePage): return self._s_connect(url, 'post', show_errmsg, retry, interval, **kwargs) def ele(self, locator, index=1, timeout=None): - """返回页面中符合条件的一个元素、属性或节点文本 - :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 - :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 - :return: SessionElement对象或属性、文本 - """ return self._ele(locator, index=index, method='ele()') def eles(self, locator, timeout=None): - """返回页面中所有符合条件的元素、属性或节点文本 - :param locator: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 - :return: SessionElement对象或属性、文本组成的列表 - """ return self._ele(locator, index=None) def s_ele(self, locator=None, index=1): - """返回页面中符合条件的一个元素、属性或节点文本 - :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 - :return: SessionElement对象或属性、文本 - """ return make_session_ele(self) if locator is None else self._ele(locator, index=index, method='s_ele()') def s_eles(self, locator): - """返回页面中符合条件的所有元素、属性或节点文本 - :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :return: SessionElement对象或属性、文本 - """ return self._ele(locator, index=None) def _find_elements(self, locator, timeout=None, index=1, relative=True, raise_err=None): - """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 - :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param timeout: 不起实际作用,用于和父类对应 - :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 - :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 - :return: SessionElement对象 - """ return locator if isinstance(locator, SessionElement) else make_session_ele(self, locator, index=index) def cookies(self, all_domains=False, all_info=False): - """返回cookies - :param all_domains: 是否返回所有域的cookies - :param all_info: 是否返回所有信息,False则只返回name、value、domain - :return: cookies信息 - """ if all_domains: cookies = self.session.cookies else: @@ -251,21 +191,11 @@ class SessionPage(BasePage): return r def close(self): - """关闭Session对象""" self._session.close() if self._response is not None: self._response.close() def _s_connect(self, url, mode, show_errmsg=False, retry=None, interval=None, **kwargs): - """执行get或post连接 - :param url: 目标url - :param mode: 'get' 或 'post' - :param show_errmsg: 是否显示和抛出异常 - :param retry: 重试次数 - :param interval: 重试间隔(秒) - :param kwargs: 连接参数 - :return: url是否可用 - """ retry, interval, is_file = self._before_connect(url, retry, interval) self._response, info = self._make_response(self._url, mode, retry, interval, show_errmsg, **kwargs) @@ -284,13 +214,6 @@ class SessionPage(BasePage): return self._url_available def _make_response(self, url, mode='get', retry=None, interval=None, show_errmsg=False, **kwargs): - """生成Response对象 - :param url: 目标url - :param mode: 'get' 或 'post' - :param show_errmsg: 是否显示和抛出异常 - :param kwargs: 其它参数 - :return: tuple,第一位为Response或None,第二位为出错信息或 'Success' - """ kwargs = CaseInsensitiveDict(kwargs) if 'headers' not in kwargs: kwargs['headers'] = CaseInsensitiveDict() @@ -359,12 +282,10 @@ class SessionPage(BasePage): def check_headers(kwargs, headers, arg): - """检查kwargs或headers中是否有arg所示属性""" return arg in kwargs or arg in headers def set_charset(response): - """设置Response对象的编码""" # 在headers中获取编码 content_type = response.headers.get('content-type', '').lower() if not content_type.endswith(';'): diff --git a/DrissionPage/_pages/session_page.pyi b/DrissionPage/_pages/session_page.pyi index cec9098..497a9e5 100644 --- a/DrissionPage/_pages/session_page.pyi +++ b/DrissionPage/_pages/session_page.pyi @@ -20,56 +20,113 @@ from .._units.setter import SessionPageSetter class SessionPage(BasePage): + _headers: Optional[CaseInsensitiveDict] = ... + _session: Optional[Session] = ... + _session_options: SessionOptions = ... + _url: str = ... + _response: Optional[Response] = ... + _url_available: bool = ... + _timeout: float = ... + retry_times: int = ... + retry_interval: float = ... + _set: Optional[SessionPageSetter] = ... + _encoding: Optional[str] = ... + _page: SessionPage = ... + def __init__(self, session_or_options: Union[Session, SessionOptions] = None): - self._headers: Optional[CaseInsensitiveDict] = ... - self._session: Session = ... - self._session_options: SessionOptions = ... - self._url: str = ... - self._response: Response = ... - self._url_available: bool = ... - self._timeout: float = ... - self.retry_times: int = ... - self.retry_interval: float = ... - self._set: SessionPageSetter = ... - self._encoding: str = ... - self._page: SessionPage = ... + """ + :param session_or_options: Session对象或SessionOptions对象 + """ + ... - def _s_set_start_options(self, session_or_options: Union[Session, SessionOptions]) -> None: ... + def _s_set_start_options(self, session_or_options: Union[Session, SessionOptions]) -> None: + """启动配置 + :param session_or_options: Session、SessionOptions对象 + :return: None + """ + ... - def _s_set_runtime_settings(self) -> None: ... + def _s_set_runtime_settings(self) -> None: + """设置运行时用到的属性""" + ... - def _create_session(self) -> None: ... + def _create_session(self) -> None: + """创建内建Session对象""" + ... def __call__(self, locator: Union[Tuple[str, str], str, SessionElement], index: int = 1, - timeout: float = None) -> SessionElement: ... - - # -----------------共有属性和方法------------------- - @property - def title(self) -> str: ... + timeout: float = None) -> SessionElement: + """在内部查找元素 + 例:ele2 = ele1('@id=ele_id') + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 + :return: SessionElement对象或属性文本 + """ + ... @property - def url(self) -> str: ... + def title(self) -> str: + """返回网页title""" + ... @property - def _session_url(self) -> str: ... + def url(self) -> str: + """返回当前访问url""" + ... @property - def raw_data(self) -> Union[str, bytes]: ... + def _session_url(self) -> str: + """返回当前访问url""" + ... @property - def html(self) -> str: ... + def raw_data(self) -> Union[str, bytes]: + """返回页面原始数据""" + ... @property - def json(self) -> Union[dict, None]: ... + def html(self) -> str: + """返回页面的html文本""" + ... @property - def user_agent(self) -> str: ... + def json(self) -> Union[dict, None]: + """当返回内容是json格式时,返回对应的字典,非json格式时返回None""" + ... @property - def download_path(self) -> str: ... + def user_agent(self) -> str: + """返回user agent""" + ... + + @property + def session(self) -> Session: + """返回Session对象""" + ... + + @property + def response(self) -> Response: + """返回访问url得到的Response对象""" + ... + + @property + def encoding(self) -> str: + """返回设置的编码""" + ... + + @property + def set(self) -> SessionPageSetter: + """返回用于设置的对象""" + ... + + @property + def timeout(self) -> float: + """返回超时设置""" + ... def get(self, url: Union[Path, str], @@ -89,58 +146,38 @@ class SessionPage(BasePage): hooks: Any | None = ..., stream: Any | None = ..., verify: Any | None = ..., - cert: Any | None = ...) -> bool: ... - - def ele(self, - locator: Union[Tuple[str, str], str, SessionElement], - index: int = 1, - timeout: float = None) -> SessionElement: ... - - def eles(self, - locator: Union[Tuple[str, str], str], - timeout: float = None) -> SessionElementsList: ... - - def s_ele(self, - locator: Union[Tuple[str, str], str, SessionElement] = None, - index: int = 1) -> SessionElement: ... - - def s_eles(self, loc: Union[Tuple[str, str], str]) -> SessionElementsList: ... - - def _find_elements(self, - locator: Union[Tuple[str, str], str, SessionElement], - timeout: float = None, - index: Optional[int] = 1, - relative: bool = True, - raise_err: bool = None) -> Union[SessionElement, SessionElementsList]: ... - - def cookies(self, - all_domains: bool = False, - all_info: bool = False) -> CookiesList: ... - - # ----------------session独有属性和方法----------------------- - @property - def session(self) -> Session: ... - - @property - def response(self) -> Response: ... - - @property - def encoding(self) -> str: ... - - @property - def set(self) -> SessionPageSetter: ... - - @property - def timeout(self) -> float: ... + cert: Any | None = ...) -> bool: + """用get方式跳转到url + :param url: 目标url + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数,为None时使用页面对象retry_times属性值 + :param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值 + :param timeout: 连接超时时间 + :param params: url中的参数 + :param data: 携带的数据 + :param json: 要发送的 JSON 数据,会自动设置 Content-Type 为 application/json + :param headers: 请求头 + :param cookies: cookies信息 + :param files: 要上传的文件,可以是一个字典,其中键是文件名,值是文件对象或文件路径 + :param auth: 身份认证信息 + :param allow_redirects: 是否允许重定向 + :param proxies: 代理信息 + :param hooks: 回调方法 + :param stream: 是否使用流式传输 + :param verify: 是否验证 SSL 证书 + :param cert: SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组 + :return: s模式时返回url是否可用,d模式时返回获取到的Response对象 + """ + ... def post(self, url: str, show_errmsg: bool = False, retry: int | None = None, interval: float | None = None, - data: Union[dict, str, None] = ..., timeout: float | None = ..., params: dict | None = ..., + data: Union[dict, str, None] = ..., json: Union[dict, str, None] = ..., headers: Union[dict, str, None] = ..., cookies: Any | None = ..., @@ -151,9 +188,97 @@ class SessionPage(BasePage): hooks: Any | None = ..., stream: Any | None = ..., verify: Any | None = ..., - cert: Any | None = ...) -> bool: ... + cert: Any | None = ...) -> bool: + """用post方式跳转到url + :param url: 目标url + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数,为None时使用页面对象retry_times属性值 + :param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值 + :param timeout: 连接超时时间 + :param params: url中的参数 + :param data: 携带的数据 + :param json: 要发送的 JSON 数据,会自动设置 Content-Type 为 application/json + :param headers: 请求头 + :param cookies: cookies信息 + :param files: 要上传的文件,可以是一个字典,其中键是文件名,值是文件对象或文件路径 + :param auth: 身份认证信息 + :param allow_redirects: 是否允许重定向 + :param proxies: 代理信息 + :param hooks: 回调方法 + :param stream: 是否使用流式传输 + :param verify: 是否验证 SSL 证书 + :param cert: SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组 + :return: s模式时返回url是否可用,d模式时返回获取到的Response对象 + """ + ... - def close(self) -> None: ... + def ele(self, + locator: Union[Tuple[str, str], str, SessionElement], + index: int = 1, + timeout: float = None) -> SessionElement: + """返回页面中符合条件的一个元素、属性或节点文本 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 + :return: SessionElement对象或属性、文本 + """ + ... + + def eles(self, + locator: Union[Tuple[str, str], str], + timeout: float = None) -> SessionElementsList: + """返回页面中所有符合条件的元素、属性或节点文本 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 不起实际作用,用于和ChromiumElement对应,便于无差别调用 + :return: SessionElement对象或属性、文本组成的列表 + """ + ... + + def s_ele(self, + locator: Union[Tuple[str, str], str, SessionElement] = None, + index: int = 1) -> SessionElement: + """返回页面中符合条件的一个元素、属性或节点文本 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :return: SessionElement对象或属性、文本 + """ + ... + + def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionElementsList: + """返回页面中符合条件的所有元素、属性或节点文本 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + ... + + def _find_elements(self, + locator: Union[Tuple[str, str], str, SessionElement], + timeout: float = None, + index: Optional[int] = 1, + relative: bool = True, + raise_err: bool = None) -> Union[SessionElement, SessionElementsList]: + """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 不起实际作用,用于和父类对应 + :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 + :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 + :return: SessionElement对象 + """ + ... + + def cookies(self, + all_domains: bool = False, + all_info: bool = False) -> CookiesList: + """返回cookies + :param all_domains: 是否返回所有域的cookies + :param all_info: 是否返回所有信息,False则只返回name、value、domain + :return: cookies信息 + """ + ... + + def close(self) -> None: + """关闭Session对象""" + ... def _s_connect(self, url: str, @@ -161,7 +286,17 @@ class SessionPage(BasePage): show_errmsg: bool = False, retry: int = None, interval: float = None, - **kwargs) -> bool: ... + **kwargs) -> bool: + """执行get或post连接 + :param url: 目标url + :param mode: 'get' 或 'post' + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数 + :param interval: 重试间隔(秒) + :param kwargs: 连接参数 + :return: url是否可用 + """ + ... def _make_response(self, url: str, @@ -169,12 +304,32 @@ class SessionPage(BasePage): retry: int = None, interval: float = None, show_errmsg: bool = False, - **kwargs) -> tuple: ... + **kwargs) -> tuple: + """生成Response对象 + :param url: 目标url + :param mode: 'get' 或 'post' + :param show_errmsg: 是否显示和抛出异常 + :param kwargs: 其它参数 + :return: tuple,第一位为Response或None,第二位为出错信息或 'Success' + """ + ... def check_headers(kwargs: Union[dict, CaseInsensitiveDict], headers: Union[dict, CaseInsensitiveDict], - arg: str) -> bool: ... + arg: str) -> bool: + """检查kwargs或headers中是否有arg所示属性 + :param kwargs: 要检查的参数dict + :param headers: 要检查的headers + :param arg: 属性名称 + :return: 检查结果 + """ + ... -def set_charset(response: Response) -> Response: ... +def set_charset(response: Response) -> Response: + """设置Response对象的编码 + :param response: Response对象 + :return: Response对象 + """ + ... diff --git a/DrissionPage/_pages/tabs.py b/DrissionPage/_pages/tabs.py index 7c6930f..3ab4044 100644 --- a/DrissionPage/_pages/tabs.py +++ b/DrissionPage/_pages/tabs.py @@ -24,10 +24,6 @@ class ChromiumTab(ChromiumBase): _TABS = {} def __new__(cls, browser, tab_id): - """ - :param browser: Browser对象 - :param tab_id: 标签页id - """ if Settings.singleton_tab_obj and tab_id in cls._TABS: r = cls._TABS[tab_id] while not hasattr(r, '_frame_id'): @@ -38,10 +34,6 @@ class ChromiumTab(ChromiumBase): return r def __init__(self, browser, tab_id): - """ - :param browser: Browser对象 - :param tab_id: 标签页id - """ if Settings.singleton_tab_obj and hasattr(self, '_created'): return self._created = True @@ -51,7 +43,6 @@ class ChromiumTab(ChromiumBase): self._type = 'ChromiumTab' def _d_set_runtime_settings(self): - """重写设置浏览器运行参数方法""" self._timeouts = copy(self.browser.timeouts) self.retry_times = self.browser.retry_times self.retry_interval = self.browser.retry_interval @@ -59,34 +50,21 @@ class ChromiumTab(ChromiumBase): self._download_path = self.browser.download_path def close(self, others=False): - """关闭当前标签页 - :param others: 是否关闭其它,保留自己 - :return: None - """ self.browser.close_tabs(self.tab_id, others=others) @property def set(self): - """返回用于设置的对象""" if self._set is None: self._set = TabSetter(self) return self._set @property def wait(self): - """返回用于等待的对象""" if self._wait is None: self._wait = TabWaiter(self) return self._wait def save(self, path=None, name=None, as_pdf=False, **kwargs): - """把当前页面保存为文件,如果path和name参数都为None,只返回文本 - :param path: 保存路径,为None且name不为None时保存在当前路径 - :param name: 文件名,为None且path不为None时用title属性值 - :param as_pdf: 为Ture保存为pdf,否则为mhtml且忽略kwargs参数 - :param kwargs: pdf生成参数 - :return: as_pdf为True时返回bytes,否则返回文件文本 - """ return save_page(self, path, name, as_pdf, kwargs) def __repr__(self): @@ -98,10 +76,6 @@ class ChromiumTab(ChromiumBase): class MixTab(SessionPage, ChromiumTab, BasePage): def __init__(self, browser, tab_id): - """ - :param browser: Chromium对象 - :param tab_id: 标签页id - """ if Settings.singleton_tab_obj and hasattr(self, '_created'): return @@ -113,13 +87,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage): self._type = 'MixTab' def __call__(self, locator, index=1, timeout=None): - """在内部查找元素 - 例:ele = page('@id=ele_id') - :param locator: 元素的定位信息,可以是loc元组,或查询字符串 - :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 - :param timeout: 超时时间(秒) - :return: 子元素对象 - """ if self._mode == 'd': return super(SessionPage, self).__call__(locator, index=index, timeout=timeout) elif self._mode == 's': @@ -127,14 +94,12 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def set(self): - """返回用于设置的对象""" if self._set is None: self._set = MixTabSetter(self) return self._set @property def url(self): - """返回当前url""" if self._mode == 'd': return self._browser_url elif self._mode == 's': @@ -142,12 +107,10 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def _browser_url(self): - """返回浏览器当前url""" return super(SessionPage, self).url if self._driver else None @property def title(self): - """返回当前页面title""" if self._mode == 's': return super().title elif self._mode == 'd': @@ -155,7 +118,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def raw_data(self): - """返回页码原始数据数据""" if self._mode == 's': return super().raw_data elif self._mode == 'd': @@ -163,7 +125,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def html(self): - """返回页面html文本""" if self._mode == 's': return super().html elif self._mode == 'd': @@ -171,7 +132,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def json(self): - """当返回内容是json格式时,返回对应的字典""" if self._mode == 's': return super().json elif self._mode == 'd': @@ -179,17 +139,14 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def response(self): - """返回 s 模式获取到的 Response 对象,切换到 s 模式""" return self._response @property def mode(self): - """返回当前模式,'s'或'd' """ return self._mode @property def user_agent(self): - """返回user agent""" if self._mode == 's': return super().user_agent elif self._mode == 'd': @@ -197,32 +154,22 @@ class MixTab(SessionPage, ChromiumTab, BasePage): @property def session(self): - """返回Session对象,如未初始化则按配置信息创建""" if self._session is None: self._create_session() return self._session @property def _session_url(self): - """返回 session 保存的url""" return self._response.url if self._response else None @property def timeout(self): - """返回通用timeout设置""" return self._timeout if self._mode == 's' else self.timeouts.base def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs): - """跳转到一个url - :param url: 目标url - :param show_errmsg: 是否显示和抛出异常 - :param retry: 重试次数,为None时使用页面对象retry_times属性值 - :param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值 - :param timeout: 连接超时时间(秒),为None时使用页面对象timeouts.page_load属性值 - :param kwargs: 连接参数,s模式专用 - :return: url是否可用,d模式返回None时表示不确定 - """ if self._mode == 'd': + if kwargs: + raise ValueError(f'以下参数在s模式下才会生效:{" ".join(kwargs.keys())}') return super(SessionPage, self).get(url, show_errmsg, retry, interval, timeout) elif self._mode == 's': if timeout is None: @@ -230,14 +177,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage): return super().get(url, show_errmsg, retry, interval, timeout, **kwargs) def post(self, url, show_errmsg=False, retry=None, interval=None, **kwargs): - """用post方式跳转到url,会切换到s模式 - :param url: 目标url - :param show_errmsg: 是否显示和抛出异常 - :param retry: 重试次数,为None时使用页面对象retry_times属性值 - :param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值 - :param kwargs: 连接参数 - :return: s模式时返回url是否可用,d模式时返回获取到的Response对象 - """ if self.mode == 'd': self.cookies_to_session() super().post(url, show_errmsg, retry, interval, **kwargs) @@ -245,58 +184,30 @@ class MixTab(SessionPage, ChromiumTab, BasePage): return super().post(url, show_errmsg, retry, interval, **kwargs) def ele(self, locator, index=1, timeout=None): - """返回第一个符合条件的元素、属性或节点文本 - :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 - :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 - :return: 元素对象或属性、文本节点文本 - """ if self._mode == 's': return super().ele(locator, index=index) elif self._mode == 'd': return super(SessionPage, self).ele(locator, index=index, timeout=timeout) def eles(self, locator, timeout=None): - """返回页面中所有符合条件的元素、属性或节点文本 - :param locator: 元素的定位信息,可以是loc元组,或查询字符串 - :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 - :return: 元素对象或属性、文本组成的列表 - """ if self._mode == 's': return super().eles(locator) elif self._mode == 'd': return super(SessionPage, self).eles(locator, timeout=timeout) def s_ele(self, locator=None, index=1): - """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 - :param locator: 元素的定位信息,可以是loc元组,或查询字符串 - :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 - :return: SessionElement对象或属性、文本 - """ if self._mode == 's': return super().s_ele(locator, index=index) elif self._mode == 'd': return super(SessionPage, self).s_ele(locator, index=index) def s_eles(self, locator): - """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 - :param locator: 元素的定位信息,可以是loc元组,或查询字符串 - :return: SessionElement对象或属性、文本组成的列表 - """ if self._mode == 's': return super().s_eles(locator) elif self._mode == 'd': return super(SessionPage, self).s_eles(locator) def change_mode(self, mode=None, go=True, copy_cookies=True): - """切换模式,接收's'或'd',除此以外的字符串会切换为 d 模式 - 如copy_cookies为True,切换时会把当前模式的cookies复制到目标模式 - 切换后,如果go是True,调用相应的get函数使访问的页面同步 - :param mode: 模式字符串 - :param go: 是否跳转到原模式的url - :param copy_cookies: 是否复制cookies到目标模式 - :return: None - """ if mode is not None and mode.lower() == self._mode: return @@ -334,10 +245,6 @@ class MixTab(SessionPage, ChromiumTab, BasePage): self.get(url) def cookies_to_session(self, copy_user_agent=True): - """把浏览器的cookies复制到session对象 - :param copy_user_agent: 是否复制ua信息 - :return: None - """ if not self._has_session: return @@ -348,41 +255,23 @@ class MixTab(SessionPage, ChromiumTab, BasePage): set_session_cookies(self.session, super(SessionPage, self).cookies()) def cookies_to_browser(self): - """把session对象的cookies复制到浏览器""" if not self._has_driver: return set_tab_cookies(self, super().cookies()) def cookies(self, all_domains=False, all_info=False): - """返回cookies - :param all_domains: 是否返回所有域的cookies - :param all_info: 是否返回所有信息,False则只返回name、value、domain - :return: cookies信息 - """ if self._mode == 's': return super().cookies(all_domains, all_info) elif self._mode == 'd': return super(SessionPage, self).cookies(all_domains, all_info) def close(self, others=False): - """关闭当前标签页 - :param others: 是否关闭其它,保留自己 - :return: None - """ self.browser.close_tabs(self.tab_id, others=others) self._session.close() if self._response is not None: self._response.close() def _find_elements(self, locator, timeout=None, index=1, relative=False, raise_err=None): - """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 - :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 - :param timeout: 查找元素超时时间(秒),d模式专用 - :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 - :param relative: MixTab用的表示是否相对定位的参数 - :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 - :return: 元素对象或属性、文本节点文本 - """ if self._mode == 's': return super()._find_elements(locator, index=index) elif self._mode == 'd': diff --git a/DrissionPage/_pages/tabs.pyi b/DrissionPage/_pages/tabs.pyi index 3bba12b..886a14c 100644 --- a/DrissionPage/_pages/tabs.pyi +++ b/DrissionPage/_pages/tabs.pyi @@ -6,7 +6,7 @@ @License : BSD 3-Clause. """ from pathlib import Path -from typing import Union, Tuple, Any, Optional +from typing import Union, Tuple, Any, Optional, Literal from requests import Session, Response @@ -25,43 +25,94 @@ from .._units.waiter import TabWaiter class ChromiumTab(ChromiumBase): _TABS: dict = ... + _tab: ChromiumTab = ... + _rect: Optional[TabRect] = ... - def __new__(cls, browser: Chromium, tab_id: str): ... + def __new__(cls, browser: Chromium, tab_id: str): + """ + :param browser: Browser对象 + :param tab_id: 标签页id + """ + ... def __init__(self, browser: Chromium, tab_id: str): - self._tab: ChromiumTab = ... - self._rect: Optional[TabRect] = ... + """ + :param browser: Browser对象 + :param tab_id: 标签页id + """ + ... - def _d_set_runtime_settings(self) -> None: ... + def _d_set_runtime_settings(self) -> None: + """重写设置浏览器运行参数方法""" + ... - def close(self) -> None: ... + def close(self, others: bool = False) -> None: + """关闭标签页 + :param others: 是否关闭其它,保留自己 + :return: None + """ + ... @property - def set(self) -> TabSetter: ... + def set(self) -> TabSetter: + """返回用于设置的对象""" + ... @property - def wait(self) -> TabWaiter: ... + def wait(self) -> TabWaiter: + """返回用于等待的对象""" + ... def save(self, path: Union[str, Path] = None, name: str = None, as_pdf: bool = False, - landscape: bool = ..., - displayHeaderFooter: bool = ..., - printBackground: bool = ..., - scale: float = ..., - paperWidth: float = ..., - paperHeight: float = ..., - marginTop: float = ..., - marginBottom: float = ..., - marginLeft: float = ..., - marginRight: float = ..., - pageRanges: str = ..., - headerTemplate: str = ..., - footerTemplate: str = ..., - preferCSSPageSize: bool = ..., + landscape: bool = False, + displayHeaderFooter: bool = False, + printBackground: bool = False, + scale: float = 1, + paperWidth: float = 8.5, + paperHeight: float = 11, + marginTop: float = 11, + marginBottom: float = 1, + marginLeft: float = 1, + marginRight: float = 1, + pageRanges: str = '', + headerTemplate: str = '', + footerTemplate: str = '', + preferCSSPageSize: bool = False, generateTaggedPDF: bool = ..., - generateDocumentOutline: bool = ...) -> Union[bytes, str]: ... + generateDocumentOutline: bool = ...) -> Union[bytes, str]: + """把当前页面保存为文件,如果path和name参数都为None,只返回文本 + :param path: 保存路径,为None且name不为None时保存在当前路径 + :param name: 文件名,为None且path不为None时用title属性值 + :param as_pdf: 为Ture保存为pdf,否则为mhtml且忽略kwargs参数 + :param landscape: 纸张方向,as_pdf为True时才生效 + :param displayHeaderFooter: 是否显示页头页脚,as_pdf为True时才生效 + :param printBackground: 是否打印背景图片,as_pdf为True时才生效 + :param scale: 缩放比例,as_pdf为True时才生效 + :param paperWidth: 页面宽度(英寸),as_pdf为True时才生效 + :param paperHeight: 页面高度(英寸),as_pdf为True时才生效 + :param marginTop: 上边距(英寸),as_pdf为True时才生效 + :param marginBottom: 下边距(英寸),as_pdf为True时才生效 + :param marginLeft: 左边距(英寸),as_pdf为True时才生效 + :param marginRight: 右边距(英寸),as_pdf为True时才生效 + :param pageRanges: 页面范围,格式'1-5, 8, 11-13',as_pdf为True时才生效 + :param headerTemplate: 页头HTML模板,as_pdf为True时才生效 + 模板可包含以下class: + - date:日期 + - title:文档标题 + - url:文档url + - pageNumber:当前页码 + - totalPages:总页数 + 示例: + :param footerTemplate: 页脚HTML模板,格式与页头的一样,as_pdf为True时才生效 + :param preferCSSPageSize: 是否使用css定义的页面大小,as_pdf为True时才生效 + :param generateTaggedPDF: 是否生成带标签的(可访问的)PDF。默认为嵌入器选择,as_pdf为True时才生效 + :param generateDocumentOutline: 是否将文档大纲嵌入到PDF中。,as_pdf为True时才生效 + :return: as_pdf为True时返回bytes,否则返回文件文本 + """ + ... class MixTab(SessionPage, ChromiumTab): @@ -70,48 +121,90 @@ class MixTab(SessionPage, ChromiumTab): _has_driver: bool = ... _has_session: bool = ... - def __init__(self, browser: Chromium, tab_id: str): ... + def __init__(self, browser: Chromium, tab_id: str): + """ + :param browser: Chromium对象 + :param tab_id: 标签页id + """ + ... def __call__(self, locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], index: int = 1, - timeout: float = None) -> Union[ChromiumElement, SessionElement]: ... + timeout: float = None) -> Union[ChromiumElement, SessionElement]: + """在内部查找元素 + 例:ele = page('@id=ele_id') + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :param timeout: 超时时间(秒) + :return: 子元素对象 + """ + ... @property - def url(self) -> Union[str, None]: ... + def set(self) -> MixTabSetter: + """返回用于设置的对象""" + ... @property - def _browser_url(self) -> Union[str, None]: ... + def url(self) -> Union[str, None]: + """返回浏览器当前url""" + ... @property - def title(self) -> str: ... + def _browser_url(self) -> Union[str, None]: + """返回浏览器当前url""" + ... @property - def raw_data(self) -> Union[str, bytes]: ... + def title(self) -> str: + """返回当前页面title""" + ... @property - def html(self) -> str: ... + def raw_data(self) -> Union[str, bytes]: + """返回页码原始数据数据""" + ... @property - def json(self) -> dict: ... + def html(self) -> str: + """返回页面html文本""" + ... @property - def response(self) -> Response: ... + def json(self) -> dict: + """当返回内容是json格式时,返回对应的字典""" + ... @property - def mode(self) -> str: ... + def response(self) -> Response: + """返回 s 模式获取到的 Response 对象,切换到 s 模式""" + ... @property - def user_agent(self) -> str: ... + def mode(self) -> Literal['s', 'd']: + """返回当前模式,'s'或'd' """ + ... @property - def session(self) -> Session: ... + def user_agent(self) -> str: + """返回user agent""" + ... @property - def _session_url(self) -> str: ... + def session(self) -> Session: + """返回Session对象,如未初始化则按配置信息创建""" + ... @property - def timeout(self) -> float: ... + def _session_url(self) -> str: + """返回 session 保存的url""" + ... + + @property + def timeout(self) -> float: + """返回通用timeout设置""" + ... def get(self, url: str, @@ -131,42 +224,38 @@ class MixTab(SessionPage, ChromiumTab): hooks: Any | None = ..., stream: Any | None = ..., verify: Any | None = ..., - cert: Any | None = ...) -> Union[bool, None]: ... + cert: Any | None = ...) -> Union[bool, None]: + """跳转到一个url + :param url: 目标url + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数,为None时使用页面对象retry_times属性值 + :param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值 + :param timeout: 连接超时时间 + :param params: url中的参数 + :param data: 携带的数据 + :param json: 要发送的 JSON 数据,会自动设置 Content-Type 为 application/json + :param headers: 请求头 + :param cookies: cookies信息 + :param files: 要上传的文件,可以是一个字典,其中键是文件名,值是文件对象或文件路径 + :param auth: 身份认证信息 + :param allow_redirects: 是否允许重定向 + :param proxies: 代理信息 + :param hooks: 回调方法 + :param stream: 是否使用流式传输 + :param verify: 是否验证 SSL 证书 + :param cert: SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组 + :return: s模式时返回url是否可用,d模式时返回获取到的Response对象 + """ + ... - def ele(self, - locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], - index: int = 1, - timeout: float = None) -> Union[ChromiumElement, SessionElement]: ... - - def eles(self, - locator: Union[Tuple[str, str], str], - timeout: float = None) -> Union[SessionElementsList, ChromiumElementsList]: ... - - def s_ele(self, - locator: Union[Tuple[str, str], str] = None, - index: int = 1) -> SessionElement: ... - - def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionElementsList: ... - - def change_mode(self, mode: str = None, go: bool = True, copy_cookies: bool = True) -> None: ... - - def cookies_to_session(self, copy_user_agent: bool = True) -> None: ... - - def cookies_to_browser(self) -> None: ... - - def cookies(self, all_domains: bool = False, all_info: bool = False) -> CookiesList: ... - - def close(self) -> None: ... - - # ----------------重写SessionPage的函数----------------------- def post(self, url: str, - data: Union[dict, str, None] = None, show_errmsg: bool = False, retry: int | None = None, interval: float | None = None, timeout: float | None = ..., params: dict | None = ..., + data: Union[dict, str, None] = None, json: Union[dict, str, None] = ..., headers: dict | None = ..., cookies: Any | None = ..., @@ -177,10 +266,105 @@ class MixTab(SessionPage, ChromiumTab): hooks: Any | None = ..., stream: Any | None = ..., verify: Any | None = ..., - cert: Any | None = ...) -> Union[bool, Response]: ... + cert: Any | None = ...) -> Union[bool, Response]: + """用post方式跳转到url + :param url: 目标url + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数,为None时使用页面对象retry_times属性值 + :param interval: 重试间隔(秒),为None时使用页面对象retry_interval属性值 + :param timeout: 连接超时时间 + :param params: url中的参数 + :param data: 携带的数据 + :param json: 要发送的 JSON 数据,会自动设置 Content-Type 为 application/json + :param headers: 请求头 + :param cookies: cookies信息 + :param files: 要上传的文件,可以是一个字典,其中键是文件名,值是文件对象或文件路径 + :param auth: 身份认证信息 + :param allow_redirects: 是否允许重定向 + :param proxies: 代理信息 + :param hooks: 回调方法 + :param stream: 是否使用流式传输 + :param verify: 是否验证 SSL 证书 + :param cert: SSL客户端证书文件的路径(.pem格式),或(‘cert’, ‘key’)元组 + :return: s模式时返回url是否可用,d模式时返回获取到的Response对象 + """ + ... - @property - def set(self) -> MixTabSetter: ... + def ele(self, + locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + index: int = 1, + timeout: float = None) -> Union[ChromiumElement, SessionElement]: + """返回第一个符合条件的元素、属性或节点文本 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 + :return: 元素对象或属性、文本节点文本 + """ + ... + + def eles(self, + locator: Union[Tuple[str, str], str], + timeout: float = None) -> Union[SessionElementsList, ChromiumElementsList]: + """返回页面中所有符合条件的元素、属性或节点文本 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间(秒),默认与页面等待时间一致 + :return: 元素对象或属性、文本组成的列表 + """ + ... + + def s_ele(self, + locator: Union[Tuple[str, str], str] = None, + index: int = 1) -> SessionElement: + """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :param index: 获取第几个,从1开始,可传入负数获取倒数第几个 + :return: SessionElement对象或属性、文本 + """ + ... + + def s_eles(self, locator: Union[Tuple[str, str], str]) -> SessionElementsList: + """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 + :param locator: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本组成的列表 + """ + ... + + def change_mode(self, mode: str = None, go: bool = True, copy_cookies: bool = True) -> None: + """切换模式,接收's'或'd',除此以外的字符串会切换为 d 模式 + 如copy_cookies为True,切换时会把当前模式的cookies复制到目标模式 + 切换后,如果go是True,调用相应的get函数使访问的页面同步 + :param mode: 模式字符串 + :param go: 是否跳转到原模式的url + :param copy_cookies: 是否复制cookies到目标模式 + :return: None + """ + ... + + def cookies_to_session(self, copy_user_agent: bool = True) -> None: + """把浏览器的cookies复制到session对象 + :param copy_user_agent: 是否复制ua信息 + :return: None + """ + ... + + def cookies_to_browser(self) -> None: + """把session对象的cookies复制到浏览器""" + ... + + def cookies(self, all_domains: bool = False, all_info: bool = False) -> CookiesList: + """返回cookies + :param all_domains: 是否返回所有域的cookies + :param all_info: 是否返回所有信息,False则只返回name、value、domain + :return: cookies信息 + """ + ... + + def close(self, others: bool = False) -> None: + """关闭标签页 + :param others: 是否关闭其它,保留自己 + :return: None + """ + ... def _find_elements(self, locator: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], @@ -188,4 +372,13 @@ class MixTab(SessionPage, ChromiumTab): index: Optional[int] = 1, relative: bool = False, raise_err: bool = None) \ - -> Union[ChromiumElement, SessionElement, ChromiumFrame, SessionElementsList, ChromiumElementsList]: ... + -> Union[ChromiumElement, SessionElement, ChromiumFrame, SessionElementsList, ChromiumElementsList]: + """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 + :param locator: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 查找元素超时时间(秒),d模式专用 + :param index: 第几个结果,从1开始,可传入负数获取倒数第几个,为None返回所有 + :param relative: MixTab用的表示是否相对定位的参数 + :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 + :return: 元素对象或属性、文本节点文本 + """ + ...