修复WebPage的set.cookies问题;添加add_init_js()和remove_init_js();尝试修复获取元素大小报错

This commit is contained in:
g1879 2023-12-31 00:00:40 +08:00
parent 28544e2532
commit c0f50e2bbf
9 changed files with 115 additions and 52 deletions

View File

@ -269,10 +269,6 @@ def raise_error(result, ignore=None):
r = ElementLostError()
elif error in ('connection disconnected', 'No target with given id found'):
r = PageDisconnectedError()
elif error == 'timeout':
r = TimeoutError(f'超时(等待{result["timeout"]}秒)。\n错误:{result["error"]}\nmethod{result["method"]}\nargs'
f'{result["args"]}\n出现这个错误可能意味着程序有bug请把错误信息和重现方法告知作者谢谢。\n'
'报告网站https://gitee.com/g1879/DrissionPage/issues')
elif error == 'alert exists.':
r = AlertExistsError()
elif error in ('Node does not have a layout object', 'Could not compute box model.'):
@ -283,10 +279,12 @@ def raise_error(result, ignore=None):
r = StorageError()
elif error == 'Sanitizing cookie failed':
r = CookieFormatError(f'cookie格式不正确{result["args"]}')
elif result['type'] == 'call_method_error':
elif result['type'] in ('call_method_error', 'timeout'):
from DrissionPage import __version__
from time import process_time
r = CDPError(f'\n错误:{result["error"]}\nmethod{result["method"]}\nargs{result["args"]}\n'
f'出现这个错误可能意味着程序有bug请把错误信息和重现方法告知作者谢谢。'
f'\n报告网站https://gitee.com/g1879/DrissionPage/issues')
f'版本:{__version__}\n运行时间:{process_time()}\n出现这个错误可能意味着程序有bug请把错误信息和重现方法'
'告知作者,谢谢。\n报告网站https://gitee.com/g1879/DrissionPage/issues')
else:
r = RuntimeError(result)

View File

@ -58,6 +58,7 @@ class ChromiumBase(BasePage):
self._doc_got = False # 用于在LoadEventFired和FrameStoppedLoading间标记是否已获取doc
self._download_path = None
self._load_end_time = 0
self._init_jss = []
if not hasattr(self, '_listener'):
self._listener = None
@ -492,7 +493,7 @@ class ChromiumBase(BasePage):
:return: None
"""
run_js(self, script, as_expr, 0, args)
def get(self, url, show_errmsg=False, retry=None, interval=None, timeout=None):
"""访问url
:param url: 目标url
@ -796,6 +797,30 @@ class ChromiumBase(BasePage):
return self._get_screenshot(path=path, name=name, as_bytes=as_bytes, as_base64=as_base64,
full_page=full_page, left_top=left_top, right_bottom=right_bottom)
def add_init_js(self, js):
"""添加初始化脚本,在页面加载任何脚本前执行
:param js: js文本
:return: 添加的脚本的id
"""
js_id = self.run_cdp('Page.addScriptToEvaluateOnNewDocument', source=js,
includeCommandLineAPI=True)['identifier']
self._init_jss.append(js_id)
return js_id
def remove_init_js(self, js_id=None):
"""删除初始化脚本js_id传入None时删除所有
:param js_id: 脚本的id
:return: None
"""
if js_id is None:
for js_id in self._init_jss:
self.run_cdp('Page.removeScriptToEvaluateOnNewDocument', identifier=js_id)
self._init_jss.clear()
elif js_id in self._init_jss:
self.run_cdp('Page.removeScriptToEvaluateOnNewDocument', identifier=js_id)
self._init_jss.remove(js_id)
def clear_cache(self, session_storage=True, local_storage=True, cache=True, cookies=True):
"""清除缓存,可选要清除的项
:param session_storage: 是否清除sessionStorage

View File

@ -58,6 +58,7 @@ class ChromiumBase(BasePage):
self._has_alert: bool = ...
self._doc_got: bool = ...
self._load_end_time: float = ...
self._init_jss: list = ...
self._ready_state: Optional[str] = ...
self._rect: TabRect = ...
@ -214,6 +215,10 @@ class ChromiumBase(BasePage):
def get_local_storage(self, item: str = None) -> Union[str, dict, None]: ...
def add_init_js(self, js: str) -> str: ...
def remove_init_js(self, js_id: str = None) -> None: ...
def get_screenshot(self, path: [str, Path] = None, name: str = None, as_bytes: PIC_TYPE = None,
as_base64: PIC_TYPE = None, full_page: bool = False, left_top: Tuple[int, int] = None,
right_bottom: Tuple[int, int] = None) -> Union[str, bytes]: ...

View File

@ -66,3 +66,38 @@ class SessionCookiesSetter(object):
def clear(self):
"""清除cookies"""
self._page.session.cookies.clear()
class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
def __call__(self, cookies):
"""设置多个cookie注意不要传入单个
:param cookies: cookies信息
:return: None
"""
if self._page.mode == 'd' and self._page._has_driver:
super().__call__(cookies)
elif self._page.mode == 's' and self._page._has_session:
super(CookiesSetter, self).__call__(cookies)
def remove(self, name, url=None, domain=None, path=None):
"""删除一个cookie
:param name: cookie的name字段
:param url: cookie的url字段可选d模式时才有效
:param domain: cookie的domain字段可选d模式时才有效
:param path: cookie的path字段可选d模式时才有效
:return: None
"""
if self._page.mode == 'd' and self._page._has_driver:
super().remove(name, url, domain, path)
elif self._page.mode == 's' and self._page._has_session:
if url or domain or path:
raise AttributeError('url、domain、path参数只有d模式下有效。')
super(CookiesSetter, self).remove(name)
def clear(self):
"""清除cookies"""
if self._page.mode == 'd' and self._page._has_driver:
super().clear()
elif self._page.mode == 's' and self._page._has_session:
super(CookiesSetter, self).clear()

View File

@ -4,13 +4,16 @@ from typing import Union
from requests.cookies import RequestsCookieJar
from .._pages.session_page import SessionPage
from .._pages.chromium_base import ChromiumBase
from .._pages.chromium_tab import WebPageTab
from .._pages.session_page import SessionPage
from .._pages.web_page import WebPage
class CookiesSetter(object):
def __init__(self, page: ChromiumBase):
self._page: ChromiumBase = ...
_page: ChromiumBase
def __init__(self, page: ChromiumBase): ...
def __call__(self, cookies: Union[RequestsCookieJar, Cookie, list, tuple, str, dict]) -> None: ...
@ -20,11 +23,24 @@ class CookiesSetter(object):
class SessionCookiesSetter(object):
def __init__(self, page: SessionPage):
self._page: SessionPage = ...
_page: SessionPage
def __init__(self, page: SessionPage): ...
def __call__(self, cookies: Union[RequestsCookieJar, Cookie, list, tuple, str, dict]) -> None: ...
def remove(self, name: str) -> None: ...
def clear(self) -> None: ...
class WebPageCookiesSetter(CookiesSetter, SessionCookiesSetter):
_page: Union[WebPage, WebPageTab]
def __init__(self, page: SessionPage): ...
def __call__(self, cookies: Union[RequestsCookieJar, Cookie, list, tuple, str, dict]) -> None: ...
def remove(self, name: str, url: str = None, domain: str = None, path: str = None) -> None: ...
def clear(self) -> None: ...

View File

@ -30,7 +30,8 @@ class ElementRect(object):
@property
def size(self):
"""返回元素大小,格式(宽, 高)"""
border = self._ele.page.run_cdp('DOM.getBoxModel', backendNodeId=self._ele._backend_id)['model']['border']
border = self._ele.page.run_cdp('DOM.getBoxModel', backendNodeId=self._ele._backend_id,
nodeId=self._ele._node_id, objectId=self._ele._obj_id)['model']['border']
return border[2] - border[0], border[5] - border[1]
@property
@ -98,7 +99,8 @@ class ElementRect(object):
:param quad: 方框类型margin border padding
:return: 四个角坐标
"""
return self._ele.page.run_cdp('DOM.getBoxModel', backendNodeId=self._ele._backend_id)['model'][quad]
return self._ele.page.run_cdp('DOM.getBoxModel', backendNodeId=self._ele._backend_id,
nodeId=self._ele._node_id, objectId=self._ele._obj_id)['model'][quad]
def _get_page_coord(self, x, y):
"""根据视口坐标获取绝对坐标"""

View File

@ -7,10 +7,9 @@ from pathlib import Path
from requests.structures import CaseInsensitiveDict
from .cookies_setter import SessionCookiesSetter, CookiesSetter
from .cookies_setter import SessionCookiesSetter, CookiesSetter, WebPageCookiesSetter
from .._functions.tools import show_or_hide_browser
__ERROR__ = 'error'
class BasePageSetter(object):
def __init__(self, page):
@ -199,19 +198,6 @@ class TabSetter(ChromiumBaseSetter):
"""使标签页处于最前面"""
self._page.browser.activate_tab(self._page.tab_id)
def add_init_script(self, script: str, raise_error=True):
'''添加初始化脚本,在页面加载任何脚本前执行
:param script: js文本
:return: identifier 添加的脚本的标识符失败时返回False或raise Error
'''
result = self.driver.run('Page.addScriptToEvaluateOnNewDocument', source=script)
if not result or __ERROR__ not in result:
return result['identifier']
else:
if raise_error:
raise_error(str(result))
return False
class ChromiumPageSetter(TabSetter):
@ -384,15 +370,12 @@ class WebPageSetter(ChromiumPageSetter):
self._session_setter = SessionPageSetter(self._page)
self._chromium_setter = ChromiumPageSetter(self._page)
def cookies(self, cookies):
"""添加cookies信息到浏览器或session对象
:param cookies: 可以接收`CookieJar``list``tuple``str``dict`格式的`cookies`
:return: None
"""
if self._page.mode == 'd' and self._page._has_driver:
self._chromium_setter.cookies(cookies)
elif self._page.mode == 's' and self._page._has_session:
self._session_setter.cookies(cookies)
@property
def cookies(self):
"""返回用于设置cookies的对象"""
if self._cookies_setter is None:
self._cookies_setter = WebPageCookiesSetter(self._page)
return self._cookies_setter
def headers(self, headers) -> None:
"""设置固定发送的headers
@ -418,15 +401,12 @@ class WebPageTabSetter(TabSetter):
self._session_setter = SessionPageSetter(self._page)
self._chromium_setter = ChromiumBaseSetter(self._page)
def cookies(self, cookies):
"""添加多个cookies信息到浏览器或session对象注意不要传入单个
:param cookies: 可以接收`CookieJar``list``tuple``str``dict`格式的`cookies`
:return: None
"""
if self._page.mode == 'd' and self._page._has_driver:
self._chromium_setter.cookies(cookies)
elif self._page.mode == 's' and self._page._has_session:
self._session_setter.cookies(cookies)
@property
def cookies(self):
"""返回用于设置cookies的对象"""
if self._cookies_setter is None:
self._cookies_setter = WebPageCookiesSetter(self._page)
return self._cookies_setter
def headers(self, headers) -> None:
"""设置固定发送的headers

View File

@ -9,7 +9,7 @@ from typing import Union, Tuple, Literal, Any, Optional
from requests.adapters import HTTPAdapter
from requests.auth import HTTPBasicAuth
from .cookies_setter import SessionCookiesSetter, CookiesSetter
from .cookies_setter import SessionCookiesSetter, CookiesSetter, WebPageCookiesSetter
from .scroller import PageScroller
from .._base.base import BasePage
from .._elements.chromium_element import ChromiumElement
@ -143,7 +143,8 @@ class WebPageSetter(ChromiumPageSetter):
def headers(self, headers: dict) -> None: ...
def cookies(self, cookies) -> None: ...
@property
def cookies(self) -> WebPageCookiesSetter: ...
class WebPageTabSetter(TabSetter):
@ -155,7 +156,8 @@ class WebPageTabSetter(TabSetter):
def headers(self, headers: dict) -> None: ...
def cookies(self, cookies) -> None: ...
@property
def cookies(self) -> WebPageCookiesSetter: ...
class ChromiumElementSetter(object):

View File

@ -412,7 +412,7 @@ class ElementWaiter(object):
while perf_counter() < end_time:
sleep(gap)
if self._ele.rect.size == size and location == self._ele.rect.location:
if self._ele.rect.size == size and self._ele.rect.location == location:
return True
size = self._ele.rect.size
location = self._ele.rect.location