diff --git a/DrissionPage/chromium_page.py b/DrissionPage/chromium_page.py index 181cf50..084fe1e 100644 --- a/DrissionPage/chromium_page.py +++ b/DrissionPage/chromium_page.py @@ -196,10 +196,6 @@ class ChromiumPage(ChromiumBase): tab_id = tab_id or self.tab_id return ChromiumTab(self, tab_id) - def to_front(self): - """激活当前标签页使其处于最前面""" - self._control_session.get(f'http://{self.address}/json/activate/{self.tab_id}') - def new_tab(self, url=None, switch_to=True): """新建一个标签页,该标签页在最后面 :param url: 新标签页跳转到的网址 @@ -231,26 +227,31 @@ class ChromiumPage(ChromiumBase): """跳转到主标签页""" self.to_tab(self._main_tab) - def to_tab(self, tab_id=None, activate=True): + def to_tab(self, tab_or_id=None, activate=True): """跳转到标签页 - :param tab_id: 标签页id字符串,默认跳转到main_tab + :param tab_or_id: 标签页对象或id,默认跳转到main_tab :param activate: 切换后是否变为活动状态 :return: None """ - self._to_tab(tab_id, activate) + self._to_tab(tab_or_id, activate) - def _to_tab(self, tab_id=None, activate=True, read_doc=True): + def _to_tab(self, tab_or_id=None, activate=True, read_doc=True): """跳转到标签页 - :param tab_id: 标签页id字符串,默认跳转到main_tab + :param tab_or_id: 标签页对象或id,默认跳转到main_tab :param activate: 切换后是否变为活动状态 :param read_doc: 切换后是否读取文档 :return: None """ tabs = self.tabs - if not tab_id: + if not tab_or_id: tab_id = self._main_tab + elif isinstance(tab_or_id, ChromiumTab): + tab_id = tab_or_id.tab_id + else: + tab_id = tab_or_id + if tab_id not in tabs: - tab_id = tabs[0] + tab_id = self.latest_tab if activate: self._control_session.get(f'http://{self.address}/json/activate/{tab_id}') @@ -263,19 +264,23 @@ class ChromiumPage(ChromiumBase): if read_doc and self.ready_state == 'complete': self._get_document() - def close_tabs(self, tab_ids=None, others=False): + def close_tabs(self, tabs_or_ids=None, others=False): """关闭传入的标签页,默认关闭当前页。可传入多个 - :param tab_ids: 要关闭的标签页id,可传入id组成的列表或元组,为None时关闭当前页 + :param tabs_or_ids: 要关闭的标签页对象或id,可传入列表或元组,为None时关闭当前页 :param others: 是否关闭指定标签页之外的 :return: None """ all_tabs = set(self.tabs) - if isinstance(tab_ids, str): - tabs = {tab_ids} - elif tab_ids is None: + if isinstance(tabs_or_ids, str): + tabs = {tabs_or_ids} + elif isinstance(tabs_or_ids, ChromiumTab): + tabs = {tabs_or_ids.tab_id} + elif tabs_or_ids is None: tabs = {self.tab_id} + elif isinstance(tabs_or_ids, (list, tuple)): + tabs = set(i.tab_id if isinstance(i, ChromiumTab) else i for i in tabs_or_ids) else: - tabs = set(tab_ids) + raise TypeError('tabs_or_ids参数只能传入标签页对象或id。') if others: tabs = all_tabs - tabs @@ -298,12 +303,12 @@ class ChromiumPage(ChromiumBase): self.to_tab() - def close_other_tabs(self, tab_ids=None): + def close_other_tabs(self, tabs_or_ids=None): """关闭传入的标签页以外标签页,默认保留当前页。可传入多个 - :param tab_ids: 要保留的标签页id,可传入id组成的列表或元组,为None时保存当前页 + :param tabs_or_ids: 要保留的标签页对象或id,可传入列表或元组,为None时保存当前页 :return: None """ - self.close_tabs(tab_ids, True) + self.close_tabs(tabs_or_ids, True) def handle_alert(self, accept=True, send=None, timeout=None): """处理提示框,可以自动等待提示框出现 @@ -385,6 +390,11 @@ class ChromiumPage(ChromiumBase): warn("show_browser()方法即将弃用,请用set.show()方法代替。", DeprecationWarning) show_or_hide_browser(self, hide=False) + def to_front(self): + """激活当前标签页使其处于最前面""" + warn("to_front()方法即将弃用,请用set.tab_to_front()方法代替。", DeprecationWarning) + self.set.tab_to_front() + class ChromiumPageWaiter(ChromiumBaseWaiter): def download_begin(self, timeout=None): @@ -693,6 +703,17 @@ class ChromiumPageSetter(ChromiumBaseSetter): """返回用于设置浏览器窗口的对象""" return WindowSetter(self._page) + def tab_to_front(self, tab_or_id=None): + """激活标签页使其处于最前面 + :param tab_or_id: 标签页对象或id,为None表示当前标签页 + :return: None + """ + if not tab_or_id: + tab_or_id = self._page.tab_id + elif isinstance(tab_or_id, ChromiumTab): + tab_or_id = tab_or_id.tab_id + self._page._control_session.get(f'http://{self._page.address}/json/activate/{tab_or_id}') + def show_or_hide_browser(page, hide=True): """执行显示或隐藏浏览器窗口 diff --git a/DrissionPage/chromium_page.pyi b/DrissionPage/chromium_page.pyi index 024bcd3..e19b988 100644 --- a/DrissionPage/chromium_page.pyi +++ b/DrissionPage/chromium_page.pyi @@ -81,19 +81,21 @@ class ChromiumPage(ChromiumBase): def get_tab(self, tab_id: str = None) -> ChromiumTab: ... - def to_front(self) -> None: ... - def new_tab(self, url: str = None, switch_to: bool = True) -> None: ... def to_main_tab(self) -> None: ... - def to_tab(self, tab_id: str = None, activate: bool = True) -> None: ... + def to_tab(self, tab_or_id: Union[str, ChromiumTab] = None, activate: bool = True) -> None: ... - def _to_tab(self, tab_id: str = None, activate: bool = True, read_doc: bool = True) -> None: ... + def _to_tab(self, tab_or_id: Union[str, ChromiumTab] = None, activate: bool = True, + read_doc: bool = True) -> None: ... - def close_tabs(self, tab_ids: Union[str, List[str], Tuple[str]] = None, others: bool = False) -> None: ... + def close_tabs(self, tabs_or_ids: Union[ + str, ChromiumTab, List[Union[str, ChromiumTab]], Tuple[Union[str, ChromiumTab]]] = None, + others: bool = False) -> None: ... - def close_other_tabs(self, tab_ids: Union[str, List[str], Tuple[str]] = None) -> None: ... + def close_other_tabs(self, tabs_or_ids: Union[ + str, ChromiumTab, List[Union[str, ChromiumTab]], Tuple[Union[str, ChromiumTab]]] = None) -> None: ... def handle_alert(self, accept: bool = True, send: str = None, timeout: float = None) -> Union[str, None]: ... @@ -226,3 +228,5 @@ class ChromiumPageSetter(ChromiumBaseSetter): @property def window(self) -> WindowSetter: ... + + def tab_to_front(self, tab_or_id: Union[str, ChromiumTab] = None) -> None: ... diff --git a/DrissionPage/chromium_tab.py b/DrissionPage/chromium_tab.py index deada18..6aaefda 100644 --- a/DrissionPage/chromium_tab.py +++ b/DrissionPage/chromium_tab.py @@ -3,7 +3,13 @@ @Author : g1879 @Contact : g1879@qq.com """ -from .chromium_base import ChromiumBase +from copy import copy + +from tldextract import extract + +from .chromium_base import ChromiumBase, ChromiumBaseSetter +from .commons.web import set_session_cookies +from .session_page import SessionPage, SessionPageSetter, DownloadSetter class ChromiumTab(ChromiumBase): @@ -20,7 +26,364 @@ class ChromiumTab(ChromiumBase): def _set_runtime_settings(self): """重写设置浏览器运行参数方法""" self._timeouts = self.page.timeouts + self.retry_times = self.page.retry_times + self.retry_interval = self.page.retry_interval self._page_load_strategy = self.page.page_load_strategy -# class WebPageTab(SessionPage, ChromiumTab, BasePage): -# pass + +class WebPageTab(SessionPage, ChromiumTab): + def __init__(self, page, tab_id): + """ + :param page: WebPage对象 + :param tab_id: 要控制的标签页id + """ + self.page = page + self.address = page.address + self._debug = page._debug + self._debug_recorder = page._debug_recorder + self._mode = 'd' + self._has_driver = True + self._has_session = True + self._session = copy(page.session) + + self._response = None + self._download_set = None + self._download_path = None + self._set = None + super(SessionPage, self)._set_runtime_settings() + self._connect_browser(tab_id) + + def __call__(self, loc_or_str, timeout=None): + """在内部查找元素 + 例:ele = page('@id=ele_id') + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 超时时间 + :return: 子元素对象 + """ + if self._mode == 'd': + return super(SessionPage, self).__call__(loc_or_str, timeout) + elif self._mode == 's': + return super().__call__(loc_or_str) + + @property + def url(self): + """返回当前url""" + if self._mode == 'd': + return super(SessionPage, self).url if self._tab_obj else None + elif self._mode == 's': + return self._session_url + + @property + def title(self): + """返回当前页面title""" + if self._mode == 's': + return super().title + elif self._mode == 'd': + return super(SessionPage, self).title + + @property + def html(self): + """返回页面html文本""" + if self._mode == 's': + return super().html + elif self._mode == 'd': + return super(SessionPage, self).html if self._has_driver else '' + + @property + def json(self): + """当返回内容是json格式时,返回对应的字典""" + if self._mode == 's': + return super().json + elif self._mode == 'd': + return super(SessionPage, self).json + + @property + def response(self): + """返回 s 模式获取到的 Response 对象,切换到 s 模式""" + return self._response + + @property + def mode(self): + """返回当前模式,'s'或'd' """ + return self._mode + + @property + def cookies(self): + if self._mode == 's': + return super().get_cookies() + elif self._mode == 'd': + return super(SessionPage, self).get_cookies() + + @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.timeouts.implicit + + @timeout.setter + def timeout(self, second): + """设置通用超时时间 + :param second: 秒数 + :return: None + """ + self.set.timeouts(implicit=second) + + @property + def set(self): + """返回用于等待的对象""" + if self._set is None: + self._set = WebPageTabSetter(self) + return self._set + + @property + def download_set(self): + """返回下载设置对象""" + if self._download_set is None: + self._download_set = WebPageTabDownloadSetter(self) + return self._download_set + + @property + def download(self): + """返回下载器对象""" + return self.download_set._switched_DownloadKit + + def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs): + """跳转到一个url + :param url: 目标url + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数 + :param interval: 重试间隔(秒) + :param timeout: 连接超时时间(秒) + :param kwargs: 连接参数,s模式专用 + :return: url是否可用,d模式返回None时表示不确定 + """ + if self._mode == 'd': + return super(SessionPage, self).get(url, show_errmsg, retry, interval, timeout) + elif self._mode == 's': + if timeout is None: + timeout = self.timeouts.page_load if self._has_driver else self.timeout + return super().get(url, show_errmsg, retry, interval, timeout, **kwargs) + + def post(self, url: str, data=None, show_errmsg=False, retry=None, interval=None, **kwargs): + """用post方式跳转到url,会切换到s模式 + :param url: 目标url + :param data: post方式时提交的数据 + :param show_errmsg: 是否显示和抛出异常 + :param retry: 重试次数 + :param interval: 重试间隔(秒) + :param kwargs: 连接参数 + :return: url是否可用 + """ + if self.mode == 'd': + self.cookies_to_session() + return super().post(url, data, show_errmsg, retry, interval, **kwargs) + + def ele(self, loc_or_ele, timeout=None): + """返回第一个符合条件的元素、属性或节点文本 + :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 查找元素超时时间,默认与页面等待时间一致 + :return: 元素对象或属性、文本节点文本 + """ + if self._mode == 's': + return super().ele(loc_or_ele) + elif self._mode == 'd': + return super(SessionPage, self).ele(loc_or_ele, timeout=timeout) + + def eles(self, loc_or_str, timeout=None): + """返回页面中所有符合条件的元素、属性或节点文本 + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :param timeout: 查找元素超时时间,默认与页面等待时间一致 + :return: 元素对象或属性、文本组成的列表 + """ + if self._mode == 's': + return super().eles(loc_or_str) + elif self._mode == 'd': + return super(SessionPage, self).eles(loc_or_str, timeout=timeout) + + def s_ele(self, loc_or_ele=None): + """查找第一个符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 + :param loc_or_ele: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本 + """ + if self._mode == 's': + return super().s_ele(loc_or_ele) + elif self._mode == 'd': + return super(SessionPage, self).s_ele(loc_or_ele) + + def s_eles(self, loc_or_str): + """查找所有符合条件的元素以SessionElement形式返回,d模式处理复杂页面时效率很高 + :param loc_or_str: 元素的定位信息,可以是loc元组,或查询字符串 + :return: SessionElement对象或属性、文本组成的列表 + """ + if self._mode == 's': + return super().s_eles(loc_or_str) + elif self._mode == 'd': + return super(SessionPage, self).s_eles(loc_or_str) + + 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 + + self._mode = 's' if self._mode == 'd' else 'd' + + # s模式转d模式 + if self._mode == 'd': + if self._tab_obj is None: + self._connect_browser(self.page._driver_options) + + self._url = None if not self._has_driver else super(SessionPage, self).url + self._has_driver = True + + if self._session_url: + if copy_cookies: + self.cookies_to_browser() + + if go: + self.get(self._session_url) + + # d模式转s模式 + elif self._mode == 's': + self._has_session = True + self._url = self._session_url + + if self._has_driver: + if copy_cookies: + self.cookies_to_session() + + if go: + url = super(SessionPage, self).url + if url.startswith('http'): + self.get(url) + + def cookies_to_session(self, copy_user_agent=True): + """把driver对象的cookies复制到session对象 + :param copy_user_agent: 是否复制ua信息 + :return: None + """ + if copy_user_agent: + selenium_user_agent = self.run_cdp('Runtime.evaluate', expression='navigator.userAgent;')['result']['value'] + self.session.headers.update({"User-Agent": selenium_user_agent}) + + self.set.cookies(self._get_driver_cookies(as_dict=True), set_session=True) + + def cookies_to_browser(self): + """把session对象的cookies复制到浏览器""" + ex_url = extract(self._session_url) + domain = f'{ex_url.domain}.{ex_url.suffix}' + cookies = [] + for cookie in super().get_cookies(): + if cookie.get('domain', '') == '': + cookie['domain'] = domain + + if domain in cookie['domain']: + cookies.append(cookie) + self.set.cookies(cookies, set_driver=True) + + def get_cookies(self, as_dict=False, all_domains=False): + """返回cookies + :param as_dict: 是否以字典方式返回 + :param all_domains: 是否返回所有域的cookies + :return: cookies信息 + """ + if self._mode == 's': + return super().get_cookies(as_dict, all_domains) + elif self._mode == 'd': + return self._get_driver_cookies(as_dict) + + def _get_driver_cookies(self, as_dict=False): + """获取浏览器cookies + :param as_dict: 以dict形式返回 + :return: cookies信息 + """ + cookies = self.run_cdp('Network.getCookies')['cookies'] + if as_dict: + return {cookie['name']: cookie['value'] for cookie in cookies} + else: + return cookies + + def _find_elements(self, loc_or_ele, timeout=None, single=True, relative=False, raise_err=None): + """返回页面中符合条件的元素、属性或节点文本,默认返回第一个 + :param loc_or_ele: 元素的定位信息,可以是元素对象,loc元组,或查询字符串 + :param timeout: 查找元素超时时间,d模式专用 + :param single: True则返回第一个,False则返回全部 + :param relative: WebPage用的表示是否相对定位的参数 + :param raise_err: 找不到元素是是否抛出异常,为None时根据全局设置 + :return: 元素对象或属性、文本节点文本 + """ + if self._mode == 's': + return super()._find_elements(loc_or_ele, single=single) + elif self._mode == 'd': + return super(SessionPage, self)._find_elements(loc_or_ele, timeout=timeout, single=single, + relative=relative) + + +class WebPageTabSetter(ChromiumBaseSetter): + def __init__(self, page): + super().__init__(page) + self._session_setter = SessionPageSetter(self._page) + self._chromium_setter = ChromiumBaseSetter(self._page) + + def cookies(self, cookies, set_session=False, set_driver=False): + """添加cookies信息到浏览器或session对象 + :param cookies: 可以接收`CookieJar`、`list`、`tuple`、`str`、`dict`格式的`cookies` + :param set_session: 是否设置到Session对象 + :param set_driver: 是否设置到浏览器 + :return: None + """ + if set_driver and self._page._has_driver: + self._chromium_setter.cookies(cookies) + if set_session and self._page._has_session: + self._session_setter.cookies(cookies) + + def headers(self, headers) -> None: + """设置固定发送的headers + :param headers: dict格式的headers数据 + :return: None + """ + if self._page._has_session: + self._session_setter.headers(headers) + if self._page._has_driver: + self._chromium_setter.headers(headers) + + def user_agent(self, ua, platform=None): + """设置user agent,d模式下只有当前tab有效""" + if self._page._has_session: + self._session_setter.user_agent(ua) + if self._page._has_driver: + self._chromium_setter.user_agent(ua, platform) + + +class WebPageTabDownloadSetter(DownloadSetter): + """用于设置下载参数的类""" + + def __init__(self, page): + super().__init__(page) + self._session = page.session + + @property + def _switched_DownloadKit(self): + """返回从浏览器同步cookies后的Session对象""" + if self._page.mode == 'd': + ua = self._page.run_cdp('Runtime.evaluate', expression='navigator.userAgent;')['result']['value'] + self._page.session.headers.update({"User-Agent": ua}) + set_session_cookies(self._page.session, self._page.get_cookies(as_dict=True)) + return self.DownloadKit diff --git a/DrissionPage/chromium_tab.pyi b/DrissionPage/chromium_tab.pyi index ca00be9..60ca9e4 100644 --- a/DrissionPage/chromium_tab.pyi +++ b/DrissionPage/chromium_tab.pyi @@ -3,8 +3,18 @@ @Author : g1879 @Contact : g1879@qq.com """ -from .chromium_base import ChromiumBase +from typing import Union, Tuple, Any, List + +from DownloadKit import DownloadKit +from requests import Session, Response + +from .chromium_base import ChromiumBase, ChromiumBaseSetter +from .chromium_element import ChromiumElement +from .chromium_frame import ChromiumFrame from .chromium_page import ChromiumPage +from .session_element import SessionElement +from .session_page import SessionPage, SessionPageSetter, DownloadSetter +from .web_page import WebPage class ChromiumTab(ChromiumBase): @@ -13,3 +23,150 @@ class ChromiumTab(ChromiumBase): self.page: ChromiumPage = ... def _set_runtime_settings(self) -> None: ... + + +class WebPageTab(SessionPage, ChromiumTab): + def __init__(self, page: WebPage, tab_id: str): + self.page: WebPage = ... + self._mode: str = ... + self._has_driver = ... + self._has_session = ... + self._download_set = ... + self._download_path = ... + + def __call__(self, + loc_or_str: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + timeout: float = None) -> Union[ChromiumElement, SessionElement, ChromiumFrame, None]: ... + + @property + def url(self) -> Union[str, None]: ... + + @property + def title(self) -> str: ... + + @property + def html(self) -> str: ... + + @property + def json(self) -> dict: ... + + @property + def response(self) -> Response: ... + + @property + def mode(self) -> str: ... + + @property + def cookies(self) -> Union[dict, list]: ... + + @property + def session(self) -> Session: ... + + @property + def _session_url(self) -> str: ... + + @property + def timeout(self) -> float: ... + + @timeout.setter + def timeout(self, second: float) -> None: ... + + def get(self, + url: str, + show_errmsg: bool = False, + retry: int | None = None, + interval: float | None = None, + timeout: float | None = None, + params: dict | None = ..., + data: Union[dict, str, None] = ..., + json: Union[dict, str, None] = ..., + headers: dict | None = ..., + cookies: Any | None = ..., + files: Any | None = ..., + auth: Any | None = ..., + allow_redirects: bool = ..., + proxies: dict | None = ..., + hooks: Any | None = ..., + stream: Any | None = ..., + verify: Any | None = ..., + cert: Any | None = ...) -> Union[bool, None]: ... + + def ele(self, + loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement], + timeout: float = None) -> Union[ChromiumElement, SessionElement, ChromiumFrame, str, None]: ... + + def eles(self, + loc_or_str: Union[Tuple[str, str], str], + timeout: float = None) -> List[Union[ChromiumElement, SessionElement, ChromiumFrame, str]]: ... + + def s_ele(self, loc_or_ele: Union[Tuple[str, str], str] = None) \ + -> Union[SessionElement, str, None]: ... + + def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ... + + 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 get_cookies(self, as_dict: bool = False, all_domains: bool = False) -> Union[dict, list]: ... + + def _get_driver_cookies(self, as_dict: bool = False) -> dict: ... + + # ----------------重写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 = ..., + json: Union[dict, str, None] = ..., + headers: dict | None = ..., + cookies: Any | None = ..., + files: Any | None = ..., + auth: Any | None = ..., + allow_redirects: bool = ..., + proxies: dict | None = ..., + hooks: Any | None = ..., + stream: Any | None = ..., + verify: Any | None = ..., + cert: Any | None = ...) -> bool: ... + + @property + def set(self) -> WebPageTabSetter: ... + + @property + def download(self) -> DownloadKit: ... + + @property + def download_set(self) -> WebPageTabDownloadSetter: ... + + def _find_elements(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], + timeout: float = None, single: bool = True, relative: bool = False, raise_err: bool = None) \ + -> Union[ChromiumElement, SessionElement, ChromiumFrame, str, None, List[Union[SessionElement, str]], List[ + Union[ChromiumElement, str, ChromiumFrame]]]: ... + + +class WebPageTabSetter(ChromiumBaseSetter): + _page: WebPage = ... + _session_setter: SessionPageSetter = ... + _chromium_setter: ChromiumBaseSetter = ... + + def user_agent(self, ua: str, platform: str = None) -> None: ... + + def headers(self, headers: dict) -> None: ... + + def cookies(self, cookies, set_session: bool = False, set_driver: bool = False) -> None: ... + + +class WebPageTabDownloadSetter(DownloadSetter): + """用于设置下载参数的类""" + + def __init__(self, page: WebPageTab): + self._page: WebPageTab = ... + + @property + def _switched_DownloadKit(self) -> DownloadKit: ... diff --git a/DrissionPage/web_page.py b/DrissionPage/web_page.py index 04b27eb..42f704a 100644 --- a/DrissionPage/web_page.py +++ b/DrissionPage/web_page.py @@ -13,6 +13,7 @@ from .base import BasePage from .chromium_base import ChromiumBase, Timeout from .chromium_driver import ChromiumDriver from .chromium_page import ChromiumPage, ChromiumDownloadSetter, ChromiumPageSetter +from .chromium_tab import WebPageTab from .configs.chromium_options import ChromiumOptions from .configs.session_options import SessionOptions from .errors import CallMethodError @@ -380,6 +381,14 @@ class WebPage(SessionPage, ChromiumPage, BasePage): elif self._mode == 'd': return self._get_driver_cookies(as_dict) + def get_tab(self, tab_id=None): + """获取一个标签页对象 + :param tab_id: 要获取的标签页id,为None时获取当前tab + :return: 标签页对象 + """ + tab_id = tab_id or self.tab_id + return WebPageTab(self, tab_id) + def _get_driver_cookies(self, as_dict=False): """获取浏览器cookies :param as_dict: 以dict形式返回 @@ -424,7 +433,8 @@ class WebPage(SessionPage, ChromiumPage, BasePage): if self._mode == 's': return super()._find_elements(loc_or_ele, single=single) elif self._mode == 'd': - return super(SessionPage, self)._find_elements(loc_or_ele, timeout=timeout, single=single, relative=relative) + return super(SessionPage, self)._find_elements(loc_or_ele, timeout=timeout, single=single, + relative=relative) def quit(self): """关闭浏览器,关闭session""" diff --git a/DrissionPage/web_page.pyi b/DrissionPage/web_page.pyi index 4beca6e..7a4571e 100644 --- a/DrissionPage/web_page.pyi +++ b/DrissionPage/web_page.pyi @@ -13,6 +13,7 @@ from .chromium_driver import ChromiumDriver from .chromium_element import ChromiumElement from .chromium_frame import ChromiumFrame from .chromium_page import ChromiumPage, ChromiumDownloadSetter, ChromiumPageSetter +from .chromium_tab import WebPageTab from .configs.chromium_options import ChromiumOptions from .configs.driver_options import DriverOptions from .configs.session_options import SessionOptions @@ -122,6 +123,8 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def get_cookies(self, as_dict: bool = False, all_domains: bool = False) -> Union[dict, list]: ... + def get_tab(self, tab_id: str = None) -> WebPageTab: ... + def _get_driver_cookies(self, as_dict: bool = False) -> dict: ... def close_driver(self) -> None: ... @@ -156,7 +159,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): def set(self) -> WebPageSetter: ... def _find_elements(self, loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, SessionElement, ChromiumFrame], - timeout: float = None, single: bool = True, relative: bool = False, raise_err: bool =None) \ + timeout: float = None, single: bool = True, relative: bool = False, raise_err: bool = None) \ -> Union[ChromiumElement, SessionElement, ChromiumFrame, str, None, List[Union[SessionElement, str]], List[ Union[ChromiumElement, str, ChromiumFrame]]]: ... diff --git a/setup.py b/setup.py index 8ccacd1..56c9ef6 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ with open("README.md", "r", encoding='utf-8') as fh: setup( name="DrissionPage", - version="3.2.3", + version="3.2.4", author="g1879", author_email="g1879@qq.com", description="Python based web automation tool. It can control the browser and send and receive data packets.",