修复disconnect()的问题;MixTab默认不创建Session对象;MixTab的close()增加session参数;MixTab和MixPage的post()必返回Response对象

This commit is contained in:
g1879 2024-08-29 22:38:47 +08:00
parent bbf1bc7e28
commit 70bff8555c
15 changed files with 148 additions and 135 deletions

View File

@ -74,6 +74,7 @@ class Chromium(object):
self.retry_times = self._chromium_options.retry_times self.retry_times = self._chromium_options.retry_times
self.retry_interval = self._chromium_options.retry_interval self.retry_interval = self._chromium_options.retry_interval
self.address = self._chromium_options.address self.address = self._chromium_options.address
self._disconnect_flag = False
self._driver = BrowserDriver(self.id, 'browser', self.address, self) self._driver = BrowserDriver(self.id, 'browser', self.address, self)
if ((not self._chromium_options._ua_set and self._is_headless != self._chromium_options.is_headless) if ((not self._chromium_options._ua_set and self._is_headless != self._chromium_options.is_headless)
@ -223,12 +224,14 @@ class Chromium(object):
self._run_cdp('Target.activateTarget', targetId=id_ind_tab) self._run_cdp('Target.activateTarget', targetId=id_ind_tab)
def reconnect(self): def reconnect(self):
self._disconnect_flag = True
self._driver.stop() self._driver.stop()
BrowserDriver.BROWSERS.pop(self.id) BrowserDriver.BROWSERS.pop(self.id)
self._driver = BrowserDriver(self.id, 'browser', self.address, self) self._driver = BrowserDriver(self.id, 'browser', self.address, self)
self._run_cdp('Target.setDiscoverTargets', discover=True) self._run_cdp('Target.setDiscoverTargets', discover=True)
self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed) self._driver.set_callback('Target.targetDestroyed', self._onTargetDestroyed)
self._driver.set_callback('Target.targetCreated', self._onTargetCreated) self._driver.set_callback('Target.targetCreated', self._onTargetCreated)
self._disconnect_flag = False
def clear_cache(self, cache=True, cookies=True): def clear_cache(self, cache=True, cookies=True):
if cache: if cache:
@ -396,6 +399,7 @@ class Chromium(object):
self._all_drivers.pop(tab_id, None) self._all_drivers.pop(tab_id, None)
def _on_disconnect(self): def _on_disconnect(self):
if not self._disconnect_flag:
Chromium._BROWSERS.pop(self.id, None) Chromium._BROWSERS.pop(self.id, None)
if self._chromium_options.is_auto_port and self._chromium_options.user_data_path: if self._chromium_options.is_auto_port and self._chromium_options.user_data_path:
path = Path(self._chromium_options.user_data_path) path = Path(self._chromium_options.user_data_path)
@ -469,10 +473,11 @@ def run_browser(chromium_options):
def _new_tab_by_js(browser: Chromium, url, obj, new_window): def _new_tab_by_js(browser: Chromium, url, obj, new_window):
tab = browser.get_mix_tab() if isinstance(obj, MixTab) else browser.get_tab() mix = isinstance(obj, MixTab)
tab = browser._get_tab(mix=mix)
url = f'"{url}"' if url else '' url = f'"{url}"' if url else ''
new = 'target="_new"' if new_window else 'target="_blank"' new = 'target="_new"' if new_window else 'target="_blank"'
tid = browser.latest_tab.tab_id tid = browser.latest_tab.tab_id
tab.run_js(f'window.open({url}, {new})') tab.run_js(f'window.open({url}, {new})')
tid = browser.wait.new_tab(curr_tab=tid) tid = browser.wait.new_tab(curr_tab=tid)
return browser.get_mix_tab(tid) if isinstance(obj, MixTab) else browser.get_tab(tid) return browser._get_tab(tid, mix=mix)

View File

@ -48,6 +48,7 @@ class Chromium(object):
_auto_handle_alert: Optional[bool] = ... _auto_handle_alert: Optional[bool] = ...
_is_exists: bool = ... _is_exists: bool = ...
_is_headless: bool = ... _is_headless: bool = ...
_disconnect_flag: bool = ...
def __new__(cls, def __new__(cls,
addr_or_opts: Union[str, int, ChromiumOptions] = None, addr_or_opts: Union[str, int, ChromiumOptions] = None,

View File

@ -199,7 +199,7 @@ class SessionOptions(object):
... ...
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)元组 """SSL客户端证书文件的路径(.pem格式),或('cert', 'key')元组
:param cert: 证书路径或元组 :param cert: 证书路径或元组
:return: 返回当前对象 :return: 返回当前对象
""" """

View File

@ -61,6 +61,7 @@ class ChromiumBase(BasePage):
self._auto_handle_alert = None self._auto_handle_alert = None
self._load_end_time = 0 self._load_end_time = 0
self._init_jss = [] self._init_jss = []
self._disconnect_flag = False
self._type = 'ChromiumBase' self._type = 'ChromiumBase'
if not hasattr(self, '_listener'): if not hasattr(self, '_listener'):
self._listener = None self._listener = None
@ -330,11 +331,11 @@ class ChromiumBase(BasePage):
@property @property
def tab_id(self): def tab_id(self):
return self._target_id return self.driver.id
@property @property
def _target_id(self): def _target_id(self):
return self.driver.id if self.driver.is_running else '' return self.driver.id
@property @property
def active_ele(self): def active_ele(self):
@ -650,8 +651,10 @@ class ChromiumBase(BasePage):
def disconnect(self): def disconnect(self):
if self._driver: if self._driver:
self._disconnect_flag = True
self._driver.stop() self._driver.stop()
self.browser._all_drivers.get(self._driver.id, set()).discard(self._driver) self.browser._all_drivers.get(self._driver.id, set()).discard(self._driver)
self._disconnect_flag = False
def reconnect(self, wait=0): def reconnect(self, wait=0):
t_id = self._target_id t_id = self._target_id

View File

@ -63,6 +63,7 @@ class ChromiumBase(BasePage):
_ready_state: Optional[str] = ... _ready_state: Optional[str] = ...
_rect: Optional[TabRect] = ... _rect: Optional[TabRect] = ...
_console: Optional[Console] = ... _console: Optional[Console] = ...
_disconnect_flag: bool = ...
_type: str = ... _type: str = ...
def __init__(self, def __init__(self,

View File

@ -67,4 +67,5 @@ class ChromiumTab(ChromiumBase):
return f'<ChromiumTab browser_id={self.browser.id} tab_id={self.tab_id}>' return f'<ChromiumTab browser_id={self.browser.id} tab_id={self.tab_id}>'
def _on_disconnect(self): def _on_disconnect(self):
if not self._disconnect_flag:
ChromiumTab._TABS.pop(self.tab_id, None) ChromiumTab._TABS.pop(self.tab_id, None)

View File

@ -106,3 +106,5 @@ class ChromiumTab(ChromiumBase):
:return: as_pdf为True时返回bytes否则返回文件文本 :return: as_pdf为True时返回bytes否则返回文件文本
""" """
... ...
def _on_disconnect(self): ...

View File

@ -153,8 +153,9 @@ class MixPage(SessionPage, ChromiumPage, BasePage):
# s模式转d模式 # s模式转d模式
if self._d_mode: if self._d_mode:
if self._driver is None: if self._driver is None or not self._driver.is_running:
self._connect_browser(self._chromium_options) self._driver_init(self.tab_id)
self._get_document()
self._url = None if not self._has_driver else super(SessionPage, self).url self._url = None if not self._has_driver else super(SessionPage, self).url
self._has_driver = True self._has_driver = True
@ -170,7 +171,7 @@ class MixPage(SessionPage, ChromiumPage, BasePage):
self._has_session = True self._has_session = True
self._url = self._session_url self._url = self._session_url
if self._has_driver: if self._has_driver and self._driver.is_running:
if copy_cookies: if copy_cookies:
self.cookies_to_session() self.cookies_to_session()
if go and not self.get(super(SessionPage, self).url): if go and not self.get(super(SessionPage, self).url):
@ -203,7 +204,7 @@ class MixPage(SessionPage, ChromiumPage, BasePage):
return self.browser._get_tabs(title=title, url=url, tab_type=tab_type, mix=True, as_id=as_id) return self.browser._get_tabs(title=title, url=url, tab_type=tab_type, mix=True, as_id=as_id)
def new_tab(self, url=None, new_window=False, background=False, new_context=False): def new_tab(self, url=None, new_window=False, background=False, new_context=False):
return self.browser.new_mix_tab(url=url, new_window=new_window, background=background, new_context=new_context) return self.browser._new_tab(url=url, new_window=new_window, background=background, new_context=new_context)
def close_driver(self): def close_driver(self):
if self._has_driver: if self._has_driver:

View File

@ -5,6 +5,7 @@
@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. @Copyright: (c) 2024 by g1879, Inc. All Rights Reserved.
@License : BSD 3-Clause. @License : BSD 3-Clause.
""" """
from http.cookiejar import CookieJar
from typing import Union, Tuple, List, Any, Optional, Literal from typing import Union, Tuple, List, Any, Optional, Literal
from requests import Session, Response from requests import Session, Response
@ -135,22 +136,22 @@ class MixPage(SessionPage, ChromiumPage, BasePage):
def get(self, def get(self,
url: str, url: str,
show_errmsg: bool = False, show_errmsg: bool = False,
retry: int | None = None, retry: Optional[int] = None,
interval: float | None = None, interval: Optional[float] = None,
timeout: float | None = None, timeout: Optional[float] = None,
params: dict | None = ..., params: Optional[dict] = None,
data: Union[dict, str, None] = ..., data: Union[dict, str, None] = None,
json: Union[dict, str, None] = ..., json: Union[dict, str, None] = None,
headers: Union[dict, str, None] = ..., headers: Optional[dict] = None,
cookies: Any | None = ..., cookies: Union[CookieJar, dict] = None,
files: Any | None = ..., files: Optional[Any] = None,
auth: Any | None = ..., auth: Optional[Any] = None,
allow_redirects: bool = ..., allow_redirects: bool = True,
proxies: dict | None = ..., proxies: Optional[dict] = None,
hooks: Any | None = ..., hooks: Optional[Any] = None,
stream: Any | None = ..., stream: bool = None,
verify: Any | None = ..., verify: Union[bool, str] = None,
cert: Any | None = ...) -> Union[bool, None]: cert: [str, Tuple[str, str]] = None) -> Union[bool, None]:
"""跳转到一个url """跳转到一个url
:param url: 目标url :param url: 目标url
:param show_errmsg: 是否显示和抛出异常 :param show_errmsg: 是否显示和抛出异常
@ -169,30 +170,30 @@ class MixPage(SessionPage, ChromiumPage, BasePage):
:param hooks: 回调方法 :param hooks: 回调方法
:param stream: 是否使用流式传输 :param stream: 是否使用流式传输
:param verify: 是否验证 SSL 证书 :param verify: 是否验证 SSL 证书
:param cert: SSL客户端证书文件的路径(.pem格式)(cert, key)元组 :param cert: SSL客户端证书文件的路径(.pem格式)('cert', 'key')元组
:return: s模式时返回url是否可用d模式时返回获取到的Response对象 :return: s模式时返回url是否可用d模式时返回获取到的Response对象
""" """
... ...
def post(self, def post(self,
url: str, url: str,
data: Union[dict, str, None] = None,
show_errmsg: bool = False, show_errmsg: bool = False,
retry: int | None = None, retry: Optional[int] = None,
interval: float | None = None, interval: Optional[float] = None,
timeout: float | None = ..., timeout: Optional[float] = None,
params: dict | None = ..., params: Optional[dict] = None,
json: Union[dict, str, None] = ..., data: Union[dict, str, None] = None,
headers: Union[dict, str, None] = ..., json: Union[dict, str, None] = None,
cookies: Any | None = ..., headers: Optional[dict] = None,
files: Any | None = ..., cookies: Union[CookieJar, dict] = None,
auth: Any | None = ..., files: Optional[Any] = None,
allow_redirects: bool = ..., auth: Optional[Any] = None,
proxies: dict | None = ..., allow_redirects: bool = True,
hooks: Any | None = ..., proxies: Optional[dict] = None,
stream: Any | None = ..., hooks: Optional[Any] = None,
verify: Any | None = ..., stream: bool = None,
cert: Any | None = ...) -> Union[bool, Response]: verify: Union[bool, str] = None,
cert: [str, Tuple[str, str]] = None) -> Response:
"""用post方式跳转到url """用post方式跳转到url
:param url: 目标url :param url: 目标url
:param show_errmsg: 是否显示和抛出异常 :param show_errmsg: 是否显示和抛出异常
@ -211,8 +212,8 @@ class MixPage(SessionPage, ChromiumPage, BasePage):
:param hooks: 回调方法 :param hooks: 回调方法
:param stream: 是否使用流式传输 :param stream: 是否使用流式传输
:param verify: 是否验证 SSL 证书 :param verify: 是否验证 SSL 证书
:param cert: SSL客户端证书文件的路径(.pem格式)(cert, key)元组 :param cert: SSL客户端证书文件的路径(.pem格式)('cert', 'key')元组
:return: s模式时返回url是否可用d模式时返回获取到的Response对象 :return: 获取到的Response对象
""" """
... ...

View File

@ -19,12 +19,13 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
def __init__(self, browser, tab_id): def __init__(self, browser, tab_id):
if Settings.singleton_tab_obj and hasattr(self, '_created'): if Settings.singleton_tab_obj and hasattr(self, '_created'):
return return
self._d_mode = True self._d_mode = True
self._has_driver = True self._session_options = None
self._has_session = True self._headers = None
super().__init__(session_or_options=browser._session_options or SessionOptions( self._response = None
read_file=browser._session_options is None)) self._session = None
self._encoding = None
self._timeout = 10
super(SessionPage, self).__init__(browser=browser, tab_id=tab_id) super(SessionPage, self).__init__(browser=browser, tab_id=tab_id)
self._type = 'MixTab' self._type = 'MixTab'
@ -52,15 +53,11 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
@property @property
def raw_data(self): def raw_data(self):
if self._d_mode: return super(SessionPage, self).html if self._d_mode else super().raw_data
return super(SessionPage, self).html if self._has_driver else ''
return super().raw_data
@property @property
def html(self): def html(self):
if self._d_mode: return super(SessionPage, self).html if self._d_mode else super().html
return super(SessionPage, self).html if self._has_driver else ''
return super().html
@property @property
def json(self): def json(self):
@ -99,15 +96,16 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
return super(SessionPage, self).get(url, show_errmsg, retry, interval, timeout) return super(SessionPage, self).get(url, show_errmsg, retry, interval, timeout)
if timeout is None: if timeout is None:
timeout = self.timeouts.page_load if self._has_driver else self.timeout timeout = self.timeouts.page_load
return super().get(url, show_errmsg, retry, interval, timeout, **kwargs) return super().get(url, show_errmsg, retry, interval, timeout, **kwargs)
def post(self, url, show_errmsg=False, retry=None, interval=None, **kwargs): def post(self, url, show_errmsg=False, retry=None, interval=None, timeout=None, **kwargs):
if self.mode == 'd': if self.mode == 'd':
self.cookies_to_session() self.cookies_to_session()
if timeout is None:
kwargs['timeout'] = self.timeouts.page_load
super().post(url, show_errmsg, retry, interval, **kwargs) super().post(url, show_errmsg, retry, interval, **kwargs)
return self.response return self.response
return super().post(url, show_errmsg, retry, interval, **kwargs)
def ele(self, locator, index=1, timeout=None): def ele(self, locator, index=1, timeout=None):
return super(SessionPage, self).ele(locator, index=index, timeout=timeout) if self._d_mode \ return super(SessionPage, self).ele(locator, index=index, timeout=timeout) if self._d_mode \
@ -133,13 +131,11 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
# s模式转d模式 # s模式转d模式
if self._d_mode: if self._d_mode:
if self._driver is None: # todo: 优化这里的逻辑 if self._driver is None or not self._driver.is_running:
tabs = self.browser.tab_ids self._driver_init(self.tab_id)
tid = self.tab_id if self.tab_id in tabs else tabs[0] self._get_document()
self._connect_browser(tid)
self._url = None if not self._has_driver else super(SessionPage, self).url self._url = super(SessionPage, self).url
self._has_driver = True
if self._session_url: if self._session_url:
if copy_cookies: if copy_cookies:
self.cookies_to_browser() self.cookies_to_browser()
@ -149,9 +145,13 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
return return
# d模式转s模式 # d模式转s模式
self._has_session = True if self._session is None:
self._s_set_start_options(
self.browser._session_options or SessionOptions(read_file=self.browser._session_options is None))
self._create_session()
self._url = self._session_url self._url = self._session_url
if self._has_driver: if self._driver:
if copy_cookies: if copy_cookies:
self.cookies_to_session() self.cookies_to_session()
@ -161,7 +161,7 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
self.get(url) self.get(url)
def cookies_to_session(self, copy_user_agent=True): def cookies_to_session(self, copy_user_agent=True):
if not self._has_session: if not self._session:
return return
if copy_user_agent: if copy_user_agent:
@ -171,7 +171,7 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
set_session_cookies(self.session, super(SessionPage, self).cookies()) set_session_cookies(self.session, super(SessionPage, self).cookies())
def cookies_to_browser(self): def cookies_to_browser(self):
if not self._has_driver: if self._driver is None or not self._driver.is_running:
return return
set_tab_cookies(self, super().cookies()) set_tab_cookies(self, super().cookies())
@ -179,8 +179,9 @@ class MixTab(SessionPage, ChromiumTab, BasePage):
return super(SessionPage, self).cookies(all_domains, all_info) if self._d_mode \ return super(SessionPage, self).cookies(all_domains, all_info) if self._d_mode \
else super().cookies(all_domains, all_info) else super().cookies(all_domains, all_info)
def close(self, others=False): def close(self, others=False, session=False):
self.browser.close_tabs(self.tab_id, others=others) self.browser.close_tabs(self.tab_id, others=others)
if session and self._session:
self._session.close() self._session.close()
if self._response is not None: if self._response is not None:
self._response.close() self._response.close()

View File

@ -5,6 +5,7 @@
@Copyright: (c) 2024 by g1879, Inc. All Rights Reserved. @Copyright: (c) 2024 by g1879, Inc. All Rights Reserved.
@License : BSD 3-Clause. @License : BSD 3-Clause.
""" """
from http.cookiejar import CookieJar
from typing import Union, Tuple, Any, Optional, Literal from typing import Union, Tuple, Any, Optional, Literal
from requests import Session, Response from requests import Session, Response
@ -24,8 +25,6 @@ from .._units.waiter import MixTabWaiter
class MixTab(SessionPage, ChromiumTab): class MixTab(SessionPage, ChromiumTab):
_tab: MixTab = ... _tab: MixTab = ...
_d_mode: bool = ... _d_mode: bool = ...
_has_driver: bool = ...
_has_session: bool = ...
_set: MixTabSetter = ... _set: MixTabSetter = ...
def __init__(self, browser: Chromium, tab_id: str): def __init__(self, browser: Chromium, tab_id: str):
@ -121,22 +120,22 @@ class MixTab(SessionPage, ChromiumTab):
def get(self, def get(self,
url: str, url: str,
show_errmsg: bool = False, show_errmsg: bool = False,
retry: int | None = None, retry: Optional[int] = None,
interval: float | None = None, interval: Optional[float] = None,
timeout: float | None = None, timeout: Optional[float] = None,
params: dict | None = ..., params: Optional[dict] = None,
data: Union[dict, str, None] = ..., data: Union[dict, str, None] = None,
json: Union[dict, str, None] = ..., json: Union[dict, str, None] = None,
headers: dict | None = ..., headers: Optional[dict] = None,
cookies: Any | None = ..., cookies: Union[CookieJar, dict] = None,
files: Any | None = ..., files: Optional[Any] = None,
auth: Any | None = ..., auth: Optional[Any] = None,
allow_redirects: bool = ..., allow_redirects: bool = True,
proxies: dict | None = ..., proxies: Optional[dict] = None,
hooks: Any | None = ..., hooks: Optional[Any] = None,
stream: Any | None = ..., stream: bool = None,
verify: Any | None = ..., verify: Union[bool, str] = None,
cert: Any | None = ...) -> Union[bool, None]: cert: [str, Tuple[str, str]] = None) -> Union[bool, None]:
"""跳转到一个url """跳转到一个url
:param url: 目标url :param url: 目标url
:param show_errmsg: 是否显示和抛出异常 :param show_errmsg: 是否显示和抛出异常
@ -155,7 +154,7 @@ class MixTab(SessionPage, ChromiumTab):
:param hooks: 回调方法 :param hooks: 回调方法
:param stream: 是否使用流式传输 :param stream: 是否使用流式传输
:param verify: 是否验证 SSL 证书 :param verify: 是否验证 SSL 证书
:param cert: SSL客户端证书文件的路径(.pem格式)(cert, key)元组 :param cert: SSL客户端证书文件的路径(.pem格式)('cert', 'key')元组
:return: s模式时返回url是否可用d模式时返回获取到的Response对象 :return: s模式时返回url是否可用d模式时返回获取到的Response对象
""" """
... ...
@ -163,22 +162,22 @@ class MixTab(SessionPage, ChromiumTab):
def post(self, def post(self,
url: str, url: str,
show_errmsg: bool = False, show_errmsg: bool = False,
retry: int | None = None, retry: Optional[int] = None,
interval: float | None = None, interval: Optional[float] = None,
timeout: float | None = ..., timeout: Optional[float] = None,
params: dict | None = ..., params: Optional[dict] = None,
data: Union[dict, str, None] = None, data: Union[dict, str, None] = None,
json: Union[dict, str, None] = ..., json: Union[dict, str, None] = None,
headers: dict | None = ..., headers: Optional[dict] = None,
cookies: Any | None = ..., cookies: Union[CookieJar, dict] = None,
files: Any | None = ..., files: Optional[Any] = None,
auth: Any | None = ..., auth: Optional[Any] = None,
allow_redirects: bool = ..., allow_redirects: bool = True,
proxies: dict | None = ..., proxies: Optional[dict] = None,
hooks: Any | None = ..., hooks: Optional[Any] = None,
stream: Any | None = ..., stream: bool = None,
verify: Any | None = ..., verify: Union[bool, str] = None,
cert: Any | None = ...) -> Union[bool, Response]: cert: [str, Tuple[str, str]] = None) -> Response:
"""用post方式跳转到url """用post方式跳转到url
:param url: 目标url :param url: 目标url
:param show_errmsg: 是否显示和抛出异常 :param show_errmsg: 是否显示和抛出异常
@ -197,8 +196,8 @@ class MixTab(SessionPage, ChromiumTab):
:param hooks: 回调方法 :param hooks: 回调方法
:param stream: 是否使用流式传输 :param stream: 是否使用流式传输
:param verify: 是否验证 SSL 证书 :param verify: 是否验证 SSL 证书
:param cert: SSL客户端证书文件的路径(.pem格式)(cert, key)元组 :param cert: SSL客户端证书文件的路径(.pem格式)('cert', 'key')元组
:return: s模式时返回url是否可用d模式时返回获取到的Response对象 :return: 获取到的Response对象
""" """
... ...

View File

@ -22,7 +22,7 @@ from .._units.setter import SessionPageSetter
class SessionPage(BasePage): class SessionPage(BasePage):
_headers: Optional[CaseInsensitiveDict] = ... _headers: Optional[CaseInsensitiveDict] = ...
_session: Optional[Session] = ... _session: Optional[Session] = ...
_session_options: SessionOptions = ... _session_options: Optional[SessionOptions] = ...
_url: str = ... _url: str = ...
_response: Optional[Response] = ... _response: Optional[Response] = ...
_url_available: bool = ... _url_available: bool = ...
@ -115,7 +115,7 @@ class SessionPage(BasePage):
@property @property
def encoding(self) -> str: def encoding(self) -> str:
"""返回设置的编码""" """返回设置的编码s模式专用"""
... ...
@property @property
@ -165,7 +165,7 @@ class SessionPage(BasePage):
:param hooks: 回调方法 :param hooks: 回调方法
:param stream: 是否使用流式传输 :param stream: 是否使用流式传输
:param verify: 是否验证 SSL 证书 :param verify: 是否验证 SSL 证书
:param cert: SSL客户端证书文件的路径(.pem格式)(cert, key)元组 :param cert: SSL客户端证书文件的路径(.pem格式)('cert', 'key')元组
:return: s模式时返回url是否可用d模式时返回获取到的Response对象 :return: s模式时返回url是否可用d模式时返回获取到的Response对象
""" """
... ...
@ -207,7 +207,7 @@ class SessionPage(BasePage):
:param hooks: 回调方法 :param hooks: 回调方法
:param stream: 是否使用流式传输 :param stream: 是否使用流式传输
:param verify: 是否验证 SSL 证书 :param verify: 是否验证 SSL 证书
:param cert: SSL客户端证书文件的路径(.pem格式)(cert, key)元组 :param cert: SSL客户端证书文件的路径(.pem格式)('cert', 'key')元组
:return: s模式时返回url是否可用d模式时返回获取到的Response对象 :return: s模式时返回url是否可用d模式时返回获取到的Response对象
""" """
... ...

View File

@ -103,8 +103,7 @@ class Clicker(object):
tid = self._ele.tab.browser.wait.new_tab(curr_tab=curr_tid) tid = self._ele.tab.browser.wait.new_tab(curr_tab=curr_tid)
if not tid: if not tid:
raise RuntimeError('没有出现新标签页。') raise RuntimeError('没有出现新标签页。')
return (self._ele.tab.browser.get_mix_tab(tid) if self._ele.tab._type == 'MixTab' return self._ele.tab.browser._get_tab(tid, mix=self._ele.tab._type == 'MixTab')
else self._ele.tab.browser.get_tab(tid))
def at(self, offset_x=None, offset_y=None, button='left', count=1): def at(self, offset_x=None, offset_y=None, button='left', count=1):
self._ele.owner.scroll.to_see(self._ele) self._ele.owner.scroll.to_see(self._ele)
@ -141,8 +140,7 @@ class Clicker(object):
tid = self._ele.tab.browser.wait.new_tab(timeout=timeout, curr_tab=curr_tid) tid = self._ele.tab.browser.wait.new_tab(timeout=timeout, curr_tab=curr_tid)
if not tid: if not tid:
raise RuntimeError('没有出现新标签页。') raise RuntimeError('没有出现新标签页。')
return (self._ele.tab.browser.get_mix_tab(tid) if self._ele.tab._type == 'MixTab' return self._ele.tab.browser._get_tab(tid, mix=self._ele.tab._type == 'MixTab')
else self._ele.tab.browser.get_tab(tid))
def for_url_change(self, text=None, exclude=False, by_js=False, timeout=None): def for_url_change(self, text=None, exclude=False, by_js=False, timeout=None):
if text is None: if text is None:

View File

@ -164,7 +164,7 @@ class SessionPageSetter(BaseSetter):
... ...
def cert(self, cert: Union[str, Tuple[str, str], None]) -> None: def cert(self, cert: Union[str, Tuple[str, str], None]) -> None:
"""SSL客户端证书文件的路径(.pem格式),或(cert, key)元组 """SSL客户端证书文件的路径(.pem格式),或('cert', 'key')元组
:param cert: 证书路径或元组 :param cert: 证书路径或元组
:return: None :return: None
""" """

View File

@ -49,5 +49,5 @@ def from_playwright(page_or_browser):
port = con_info.laddr.port port = con_info.laddr.port
break break
else: else:
raise RuntimeError('获取失败') raise RuntimeError('获取失败,请用管理员权限运行')
return Chromium(f'127.0.0.1:{port}') return Chromium(f'127.0.0.1:{port}')