diff --git a/DrissionPage/_base/browser.py b/DrissionPage/_base/browser.py index 88da578..4f12011 100644 --- a/DrissionPage/_base/browser.py +++ b/DrissionPage/_base/browser.py @@ -5,7 +5,7 @@ """ from time import sleep, perf_counter -from .chromium_driver import BrowserDriver, ChromiumDriver +from .driver import BrowserDriver, Driver from .._functions.tools import stop_process_on_port, raise_error from .._units.downloader import DownloadManager @@ -42,7 +42,7 @@ class Browser(object): self.id = browser_id self._frames = {} self._drivers = {} - # self._drivers = {t: ChromiumDriver(t, 'page', address) for t in self.tabs} + # self._drivers = {t: Driver(t, 'page', address) for t in self.tabs} self._connected = False self._process_id = None @@ -57,16 +57,16 @@ class Browser(object): self._driver.set_callback('Target.targetCreated', self._onTargetCreated) def _get_driver(self, tab_id): - """获取对应tab id的ChromiumDriver + """获取对应tab id的Driver :param tab_id: 标签页id - :return: ChromiumDriver对象 + :return: Driver对象 """ - return self._drivers.pop(tab_id, ChromiumDriver(tab_id, 'page', self.address)) + return self._drivers.pop(tab_id, Driver(tab_id, 'page', self.address)) def _onTargetCreated(self, **kwargs): """标签页创建时执行""" if kwargs['targetInfo']['type'] == 'page' and not kwargs['targetInfo']['url'].startswith('devtools://'): - self._drivers[kwargs['targetInfo']['targetId']] = ChromiumDriver(kwargs['targetInfo']['targetId'], 'page', + self._drivers[kwargs['targetInfo']['targetId']] = Driver(kwargs['targetInfo']['targetId'], 'page', self.address) def _onTargetDestroyed(self, **kwargs): diff --git a/DrissionPage/_base/browser.pyi b/DrissionPage/_base/browser.pyi index 3bf21be..b5d0161 100644 --- a/DrissionPage/_base/browser.pyi +++ b/DrissionPage/_base/browser.pyi @@ -5,7 +5,7 @@ """ from typing import List, Optional, Union -from .chromium_driver import BrowserDriver, ChromiumDriver +from .driver import BrowserDriver, Driver from .._pages.chromium_page import ChromiumPage from .._units.downloader import DownloadManager @@ -26,7 +26,7 @@ class Browser(object): def __init__(self, address: str, browser_id: str, page: ChromiumPage): ... - def _get_driver(self, tab_id: str) -> ChromiumDriver: ... + def _get_driver(self, tab_id: str) -> Driver: ... def run_cdp(self, cmd, **cmd_args) -> dict: ... diff --git a/DrissionPage/_base/chromium_driver.py b/DrissionPage/_base/driver.py similarity index 98% rename from DrissionPage/_base/chromium_driver.py rename to DrissionPage/_base/driver.py index 422eeb4..77b1329 100644 --- a/DrissionPage/_base/chromium_driver.py +++ b/DrissionPage/_base/driver.py @@ -12,7 +12,7 @@ from requests import get from websocket import WebSocketTimeoutException, WebSocketConnectionClosedException, create_connection -class ChromiumDriver(object): +class Driver(object): def __init__(self, tab_id, tab_type, address): """ :param tab_id: 标签页id @@ -211,12 +211,12 @@ class ChromiumDriver(object): self.event_handlers.pop(event, None) def __str__(self): - return f"" + return f"" __repr__ = __str__ -class BrowserDriver(ChromiumDriver): +class BrowserDriver(Driver): BROWSERS = {} def __new__(cls, tab_id, tab_type, address, browser): diff --git a/DrissionPage/_base/chromium_driver.pyi b/DrissionPage/_base/driver.pyi similarity index 89% rename from DrissionPage/_base/chromium_driver.pyi rename to DrissionPage/_base/driver.pyi index 28d8692..e2833da 100644 --- a/DrissionPage/_base/chromium_driver.pyi +++ b/DrissionPage/_base/driver.pyi @@ -14,14 +14,14 @@ from .browser import Browser class GenericAttr(object): - def __init__(self, name: str, tab: ChromiumDriver): ... + def __init__(self, name: str, tab: Driver): ... def __getattr__(self, item: str) -> Callable: ... def __setattr__(self, key: str, value: Callable) -> None: ... -class ChromiumDriver(object): +class Driver(object): id: str address: str type: str @@ -58,8 +58,8 @@ class ChromiumDriver(object): def __str__(self) -> str: ... -class BrowserDriver(ChromiumDriver): - BROWSERS: Dict[str, ChromiumDriver] = ... +class BrowserDriver(Driver): + BROWSERS: Dict[str, Driver] = ... browser: Browser = ... def __new__(cls, tab_id: str, tab_type: str, address: str, browser: Browser): ... diff --git a/DrissionPage/_elements/chromium_element.pyi b/DrissionPage/_elements/chromium_element.pyi index e4598d0..bb39b75 100644 --- a/DrissionPage/_elements/chromium_element.pyi +++ b/DrissionPage/_elements/chromium_element.pyi @@ -26,12 +26,12 @@ PIC_TYPE = Literal['jpg', 'jpeg', 'png', 'webp', True] class ChromiumElement(DrissionElement): - def __init__(self, page: ChromiumBase, node_id: str = None, obj_id: str = None, backend_id: str = None): + def __init__(self, page: ChromiumBase, node_id: str = None, obj_id: str = None, backend_id: int = None): self._tag: str = ... self.page: Union[ChromiumPage, WebPage] = ... self._node_id: str = ... self._obj_id: str = ... - self._backend_id: str = ... + self._backend_id: int = ... self._doc_id: str = ... self._scroll: ElementScroller = ... self._clicker: Clicker = ... @@ -196,9 +196,9 @@ class ChromiumElement(DrissionElement): def drag_to(self, ele_or_loc: Union[tuple, ChromiumElement], duration: float = 0.5) -> None: ... - def _get_obj_id(self, node_id: str = None, backend_id: str = None) -> str: ... + def _get_obj_id(self, node_id: str = None, backend_id: int = None) -> str: ... - def _get_node_id(self, obj_id: str = None, backend_id: str = None) -> str: ... + def _get_node_id(self, obj_id: str = None, backend_id: int = None) -> str: ... def _get_backend_id(self, node_id: str) -> str: ... @@ -207,10 +207,10 @@ class ChromiumElement(DrissionElement): class ShadowRoot(BaseElement): - def __init__(self, parent_ele: ChromiumElement, obj_id: str = None, backend_id: str = None): + def __init__(self, parent_ele: ChromiumElement, obj_id: str = None, backend_id: int = None): self._obj_id: str = ... self._node_id: str = ... - self._backend_id: str = ... + self._backend_id: int = ... self.page: ChromiumPage = ... self.parent_ele: ChromiumElement = ... self._states: ShadowRootStates = ... @@ -277,7 +277,7 @@ class ShadowRoot(BaseElement): def _get_obj_id(self, back_id: str) -> str: ... - def _get_backend_id(self, node_id: str) -> str: ... + def _get_backend_id(self, node_id: str) -> int: ... def find_in_chromium_ele(ele: ChromiumElement, loc: Union[str, Tuple[str, str]], diff --git a/DrissionPage/_elements/session_element.py b/DrissionPage/_elements/session_element.py index be1402f..430e6c4 100644 --- a/DrissionPage/_elements/session_element.py +++ b/DrissionPage/_elements/session_element.py @@ -4,7 +4,7 @@ @Contact : g1879@qq.com """ from html import unescape -from re import match, DOTALL +from re import match, sub, DOTALL from lxml.etree import tostring from lxml.html import HtmlElement, fromstring @@ -342,15 +342,18 @@ def make_session_ele(html_or_ele, loc=None, single=True): # 各种页面对象 elif isinstance(html_or_ele, BasePage): page = html_or_ele - html_or_ele = fromstring(html_or_ele.html) + html = html_or_ele.html + if html.startswith('', '', html) + html_or_ele = fromstring(html) # 直接传入html文本 elif isinstance(html_or_ele, str): page = None html_or_ele = fromstring(html_or_ele) - # ShadowRoot, ChromiumFrame - elif isinstance(html_or_ele, BaseElement) or the_type.endswith(".ChromiumFrame'>"): + # ShadowRoot + elif isinstance(html_or_ele, BaseElement): page = html_or_ele.page html_or_ele = fromstring(html_or_ele.html) diff --git a/DrissionPage/_functions/web.py b/DrissionPage/_functions/web.py index 96258dd..4e4cee7 100644 --- a/DrissionPage/_functions/web.py +++ b/DrissionPage/_functions/web.py @@ -251,20 +251,25 @@ def set_browser_cookies(page, cookies): cookie['expires'] = int(cookie['expiry']) cookie.pop('expiry') - if 'expires' in cookie and isinstance(cookie['expires'], str): - if cookie['expires'].isdigit(): - cookie['expires'] = int(cookie['expires']) + if 'expires' in cookie: + if not cookie['expires']: + cookie.pop('expires') - elif cookie['expires'].replace('.', '').isdigit(): - cookie['expires'] = float(cookie['expires']) + elif isinstance(cookie['expires'], str): + if cookie['expires'].isdigit(): + cookie['expires'] = int(cookie['expires']) + + elif cookie['expires'].replace('.', '').isdigit(): + cookie['expires'] = float(cookie['expires']) + + else: + try: + cookie['expires'] = datetime.strptime(cookie['expires'], + '%a, %d %b %Y %H:%M:%S GMT').timestamp() + except ValueError: + cookie['expires'] = datetime.strptime(cookie['expires'], + '%a, %d %b %y %H:%M:%S GMT').timestamp() - else: - try: - cookie['expires'] = datetime.strptime(cookie['expires'], - '%a, %d %b %Y %H:%M:%S GMT').timestamp() - except ValueError: - cookie['expires'] = datetime.strptime(cookie['expires'], - '%a, %d %b %y %H:%M:%S GMT').timestamp() if cookie['value'] is None: cookie['value'] = '' elif not isinstance(cookie['value'], str): diff --git a/DrissionPage/_pages/chromium_base.py b/DrissionPage/_pages/chromium_base.py index 63f7c19..e0d2a3e 100644 --- a/DrissionPage/_pages/chromium_base.py +++ b/DrissionPage/_pages/chromium_base.py @@ -156,31 +156,31 @@ class ChromiumBase(BasePage): timeout = timeout if timeout >= .5 else .5 self._is_reading = True end_time = perf_counter() + timeout - try: - b_id = self.run_cdp('DOM.getDocument', _timeout=timeout)['root']['backendNodeId'] - timeout = end_time - perf_counter() - timeout = .5 if timeout < 0 else timeout - self._root_id = self.run_cdp('DOM.resolveNode', backendNodeId=b_id, _timeout=timeout)['object']['objectId'] + while perf_counter() < end_time: + try: + b_id = self.run_cdp('DOM.getDocument', _timeout=timeout)['root']['backendNodeId'] + timeout = end_time - perf_counter() + timeout = .5 if timeout < 0 else timeout + self._root_id = self.run_cdp('DOM.resolveNode', + backendNodeId=b_id, _timeout=timeout)['object']['objectId'] + r = self.run_cdp('Page.getFrameTree') + for i in findall(r"'id': '(.*?)'", str(r)): + self.browser._frames[i] = self.tab_id + if self._debug: + print('获取文档结束') + result = True + break - r = self.run_cdp('Page.getFrameTree') - for i in findall(r"'id': '(.*?)'", str(r)): - self.browser._frames[i] = self.tab_id - if self._debug: - print('获取文档结束') - return True + except: + timeout = end_time - perf_counter() + timeout = .5 if timeout < 0 else timeout - except: - if self._debug: - print('获取文档失败。') - from traceback import print_exc - print_exc() - print('请把报错信息和重现方法告知作者,感谢。\nhttps://gitee.com/g1879/DrissionPage/issues/new') - raise - # return False + else: + result = False - finally: - self._is_loading = False - self._is_reading = False + self._is_loading = False + self._is_reading = False + return result def _onFrameDetached(self, **kwargs): self.browser._frames.pop(kwargs['frameId'], None) @@ -230,8 +230,8 @@ class ChromiumBase(BasePage): if self._load_mode == 'eager': self.run_cdp('Page.stopLoading') - self._get_document(self._load_end_time - perf_counter() - .1) - self._doc_got = True + if self._get_document(self._load_end_time - perf_counter() - .1): + self._doc_got = True self._ready_state = 'interactive' if self._debug: @@ -243,8 +243,7 @@ class ChromiumBase(BasePage): print(f'{self._frame_id}触发LoadEventFired') print('在LoadEventFired变成complete') - if self._doc_got is False: - self._get_document(self._load_end_time - perf_counter() - .1) + if self._doc_got is False and self._get_document(self._load_end_time - perf_counter() - .1): self._doc_got = True self._ready_state = 'complete' @@ -369,7 +368,7 @@ class ChromiumBase(BasePage): @property def driver(self): - """返回用于控制浏览器的ChromiumDriver对象""" + """返回用于控制浏览器的Driver对象""" if self._driver is None: raise RuntimeError('浏览器已关闭或链接已断开。') return self._driver @@ -960,6 +959,9 @@ class ChromiumBase(BasePage): sleep(interval) if self._debug or show_errmsg: print(f'重试{t + 1} {to_url}') + end_time1 = end_time - perf_counter() + while self._ready_state not in ('loading', 'complete') and perf_counter() < end_time1: # 等待出错信息显示 + sleep(.1) self.stop_loading() continue diff --git a/DrissionPage/_pages/chromium_base.pyi b/DrissionPage/_pages/chromium_base.pyi index e9acefc..db025c0 100644 --- a/DrissionPage/_pages/chromium_base.pyi +++ b/DrissionPage/_pages/chromium_base.pyi @@ -8,7 +8,7 @@ from typing import Union, Tuple, List, Any, Optional, Literal from .._base.base import BasePage from .._base.browser import Browser -from .._base.chromium_driver import ChromiumDriver +from .._base.driver import Driver from .._elements.chromium_element import ChromiumElement from .._elements.none_element import NoneElement from .._elements.session_element import SessionElement @@ -34,7 +34,7 @@ class ChromiumBase(BasePage): self._browser: Browser = ... self._page: ChromiumPage = ... self.address: str = ... - self._driver: ChromiumDriver = ... + self._driver: Driver = ... self._frame_id: str = ... self._is_reading: bool = ... self._is_timeout: bool = ... @@ -103,7 +103,7 @@ class ChromiumBase(BasePage): def title(self) -> str: ... @property - def driver(self) -> ChromiumDriver: ... + def driver(self) -> Driver: ... @property def url(self) -> str: ... diff --git a/DrissionPage/_pages/chromium_frame.pyi b/DrissionPage/_pages/chromium_frame.pyi index b7d6892..37df5a6 100644 --- a/DrissionPage/_pages/chromium_frame.pyi +++ b/DrissionPage/_pages/chromium_frame.pyi @@ -27,7 +27,7 @@ class ChromiumFrame(ChromiumBase): self.tab: ChromiumTab = ... self._tab_id: str = ... self._frame_ele: ChromiumElement = ... - self._backend_id: str = ... + self._backend_id: int = ... self._doc_ele: ChromiumElement = ... self._is_diff_domain: bool = ... self.doc_ele: ChromiumElement = ... diff --git a/DrissionPage/_pages/chromium_page.py b/DrissionPage/_pages/chromium_page.py index 61d9104..2c53511 100644 --- a/DrissionPage/_pages/chromium_page.py +++ b/DrissionPage/_pages/chromium_page.py @@ -37,7 +37,7 @@ class ChromiumPage(ChromiumBase): def _handle_options(self, addr_or_opts): """设置浏览器启动属性 - :param addr_or_opts: 'ip:port'、ChromiumOptions、ChromiumDriver + :param addr_or_opts: 'ip:port'、ChromiumOptions、Driver :return: 返回浏览器地址 """ if not addr_or_opts: diff --git a/DrissionPage/_pages/web_page.py b/DrissionPage/_pages/web_page.py index 505f06d..a62d30c 100644 --- a/DrissionPage/_pages/web_page.py +++ b/DrissionPage/_pages/web_page.py @@ -19,7 +19,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): """初始化函数 :param mode: 'd' 或 's',即driver模式和session模式 :param timeout: 超时时间,d模式时为寻找元素时间,s模式时为连接时间,默认10秒 - :param chromium_options: ChromiumDriver对象,只使用s模式时应传入False + :param chromium_options: Driver对象,只使用s模式时应传入False :param session_or_options: Session对象或SessionOptions对象,只使用d模式时应传入False """ chromium_options = chromium_options or driver_or_options diff --git a/DrissionPage/_pages/web_page.pyi b/DrissionPage/_pages/web_page.pyi index 6b238e4..a0b78d5 100644 --- a/DrissionPage/_pages/web_page.pyi +++ b/DrissionPage/_pages/web_page.pyi @@ -12,7 +12,7 @@ from .chromium_page import ChromiumPage from .chromium_tab import WebPageTab from .session_page import SessionPage from .._base.base import BasePage -from .._base.chromium_driver import ChromiumDriver +from .._base.driver import Driver from .._configs.chromium_options import ChromiumOptions from .._configs.session_options import SessionOptions from .._elements.chromium_element import ChromiumElement @@ -162,9 +162,7 @@ class WebPage(SessionPage, ChromiumPage, BasePage): -> Union[ChromiumElement, SessionElement, ChromiumFrame, str, None, List[Union[SessionElement, str]], List[ Union[ChromiumElement, str, ChromiumFrame]]]: ... - def _set_start_options(self, dr_opt: Union[ChromiumDriver, bool, None], + def _set_start_options(self, dr_opt: Union[Driver, bool, None], se_opt: Union[Session, SessionOptions, bool, None]) -> None: ... def quit(self, timeout: float = 5, force: bool = True) -> None: ... - - def _on_download_begin(self, **kwargs): ... diff --git a/DrissionPage/_units/actions.pyi b/DrissionPage/_units/actions.pyi index 3b6045c..982ead1 100644 --- a/DrissionPage/_units/actions.pyi +++ b/DrissionPage/_units/actions.pyi @@ -5,7 +5,7 @@ """ from typing import Union, Tuple, Any, Literal -from .._base.chromium_driver import ChromiumDriver +from .._base.driver import Driver from .._elements.chromium_element import ChromiumElement from .._pages.chromium_base import ChromiumBase @@ -43,7 +43,7 @@ class Actions: def __init__(self, page: ChromiumBase): self.page: ChromiumBase = ... - self._dr: ChromiumDriver = ... + self._dr: Driver = ... self.modifier: int = ... self.curr_x: int = ... self.curr_y: int = ... diff --git a/DrissionPage/_units/clicker.py b/DrissionPage/_units/clicker.py index 943e49c..27d6719 100644 --- a/DrissionPage/_units/clicker.py +++ b/DrissionPage/_units/clicker.py @@ -17,7 +17,7 @@ class Clicker(object): """ self._ele = ele - def __call__(self, by_js=None, timeout=1.5, wait_stop=True): + def __call__(self, by_js=False, timeout=1.5, wait_stop=True): """点击元素 如果遇到遮挡,可选择是否用js点击 :param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击 @@ -27,7 +27,7 @@ class Clicker(object): """ return self.left(by_js, timeout, wait_stop) - def left(self, by_js=None, timeout=1.5, wait_stop=True): + def left(self, by_js=False, timeout=1.5, wait_stop=True): """点击元素,可选择是否用js点击 :param by_js: 是否用js点击,为None时先用模拟点击,遇到遮挡改用js,为True时直接用js点击,为False时只用模拟点击 :param timeout: 模拟点击的超时时间,等待元素可见、可用、进入视口 diff --git a/DrissionPage/_units/clicker.pyi b/DrissionPage/_units/clicker.pyi index d62b99f..34286a9 100644 --- a/DrissionPage/_units/clicker.pyi +++ b/DrissionPage/_units/clicker.pyi @@ -3,7 +3,7 @@ @Author : g1879 @Contact : g1879@qq.com """ -from typing import Union +from typing import Union, Optional from .._elements.chromium_element import ChromiumElement @@ -12,9 +12,9 @@ class Clicker(object): def __init__(self, ele: ChromiumElement): self._ele: ChromiumElement = ... - def __call__(self, by_js: Union[None, bool] = None, timeout: float = 1.5, wait_stop: bool = True) -> bool: ... + def __call__(self, by_js: Optional[bool] = False, timeout: float = 1.5, wait_stop: bool = True) -> bool: ... - def left(self, by_js: Union[None, bool] = None, timeout: float = 1.5, wait_stop: bool = True) -> bool: ... + def left(self, by_js: Optional[bool] = False, timeout: float = 1.5, wait_stop: bool = True) -> bool: ... def right(self) -> None: ... diff --git a/DrissionPage/_units/cookies_setter.py b/DrissionPage/_units/cookies_setter.py new file mode 100644 index 0000000..160077e --- /dev/null +++ b/DrissionPage/_units/cookies_setter.py @@ -0,0 +1,64 @@ +# -*- coding:utf-8 -*- +from http.cookiejar import Cookie + +from .._functions.web import set_browser_cookies, set_session_cookies + + +class CookiesSetter(object): + def __init__(self, page): + self._page = page + + def __call__(self, cookies): + """设置一个或多个cookie + :param cookies: cookies信息 + :return: None + """ + if (isinstance(cookies, dict) and 'name' in cookies and 'value' in cookies) or isinstance(cookies, Cookie): + cookies = [cookies] + set_browser_cookies(self._page, cookies) + + def remove(self, name, url=None, domain=None, path=None): + """删除一个cookie + :param name: cookie的name字段 + :param url: cookie的url字段,可选 + :param domain: cookie的domain字段,可选 + :param path: cookie的path字段,可选 + :return: None + """ + d = {'name': name} + if url is not None: + d['url'] = url + if domain is not None: + d['domain'] = domain + if path is not None: + d['path'] = path + self._page.run_cdp('Network.deleteCookies', **d) + + def clear(self): + """清除cookies""" + self._page.run_cdp('Network.clearBrowserCookies') + + +class SessionCookiesSetter(object): + def __init__(self, page): + self._page = page + + def __call__(self, cookies): + """设置多个cookie,注意不要传入单个 + :param cookies: cookies信息 + :return: None + """ + if (isinstance(cookies, dict) and 'name' in cookies and 'value' in cookies) or isinstance(cookies, Cookie): + cookies = [cookies] + set_session_cookies(self._page.session, cookies) + + def remove(self, name): + """删除一个cookie + :param name: cookie的name字段 + :return: None + """ + self._page.session.cookies.set(name, None) + + def clear(self): + """清除cookies""" + self._page.session.cookies.clear() diff --git a/DrissionPage/_units/cookies_setter.pyi b/DrissionPage/_units/cookies_setter.pyi new file mode 100644 index 0000000..4bfc3e9 --- /dev/null +++ b/DrissionPage/_units/cookies_setter.pyi @@ -0,0 +1,30 @@ +# -*- coding:utf-8 -*- +from http.cookiejar import Cookie +from typing import Union + +from requests.cookies import RequestsCookieJar + +from .._pages.session_page import SessionPage +from .._pages.chromium_base import ChromiumBase + + +class CookiesSetter(object): + def __init__(self, page: ChromiumBase): + self._page: ChromiumBase = ... + + 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: ... + + +class SessionCookiesSetter(object): + def __init__(self, page: SessionPage): + 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: ... diff --git a/DrissionPage/_units/listener.py b/DrissionPage/_units/listener.py index 830f3c1..d18759f 100644 --- a/DrissionPage/_units/listener.py +++ b/DrissionPage/_units/listener.py @@ -11,7 +11,7 @@ from time import perf_counter, sleep from requests.structures import CaseInsensitiveDict -from .._base.chromium_driver import ChromiumDriver +from .._base.driver import Driver from .._functions.settings import Settings from ..errors import WaitTimeoutError @@ -84,7 +84,7 @@ class Listener(object): if self.listening: return - self._driver = ChromiumDriver(self._target_id, 'page', self._address) + self._driver = Driver(self._target_id, 'page', self._address) self._driver.run('Network.enable') self._set_callback() @@ -222,7 +222,7 @@ class Listener(object): debug = self._driver._debug self._driver.stop() if self.listening: - self._driver = ChromiumDriver(self._target_id, 'page', self._address) + self._driver = Driver(self._target_id, 'page', self._address) self._driver._debug = debug self._driver.run('Network.enable') self._set_callback() diff --git a/DrissionPage/_units/listener.pyi b/DrissionPage/_units/listener.pyi index d38d8be..c281c68 100644 --- a/DrissionPage/_units/listener.pyi +++ b/DrissionPage/_units/listener.pyi @@ -8,7 +8,7 @@ from typing import Union, Dict, List, Iterable, Tuple, Optional from requests.structures import CaseInsensitiveDict -from .._base.chromium_driver import ChromiumDriver +from .._base.driver import Driver from .._pages.chromium_base import ChromiumBase from .._pages.chromium_frame import ChromiumFrame @@ -22,7 +22,7 @@ class Listener(object): self._method: set = ... self._caught: Queue = ... self._is_regex: bool = ... - self._driver: ChromiumDriver = ... + self._driver: Driver = ... self._request_ids: dict = ... self._extra_info_ids: dict = ... self.listening: bool = ... diff --git a/DrissionPage/_units/selector.py b/DrissionPage/_units/selector.py index 0c168e6..8d945d2 100644 --- a/DrissionPage/_units/selector.py +++ b/DrissionPage/_units/selector.py @@ -251,7 +251,7 @@ class SelectElement(object): :return: None """ if isinstance(option, (list, tuple, set)): - if not self.is_multi: + if not self.is_multi and len(option) > 1: raise TypeError("只能对多项选框执行多选。") for o in option: o.run_js(f'this.selected={mode};') diff --git a/DrissionPage/_units/setter.py b/DrissionPage/_units/setter.py index 7d5486b..5c27059 100644 --- a/DrissionPage/_units/setter.py +++ b/DrissionPage/_units/setter.py @@ -7,8 +7,8 @@ from pathlib import Path from requests.structures import CaseInsensitiveDict +from .cookies_setter import SessionCookiesSetter, CookiesSetter from .._functions.tools import show_or_hide_browser -from .._functions.web import set_browser_cookies, set_session_cookies class BasePageSetter(object): @@ -28,6 +28,7 @@ class BasePageSetter(object): class ChromiumBaseSetter(BasePageSetter): def __init__(self, page): super().__init__(page) + self._cookies_setter = None @property def load_mode(self): @@ -39,6 +40,13 @@ class ChromiumBaseSetter(BasePageSetter): """返回用于设置页面滚动设置的对象""" return PageScrollSetter(self._page.scroll) + @property + def cookies(self): + """返回用于设置cookies的对象""" + if self._cookies_setter is None: + self._cookies_setter = CookiesSetter(self._page) + return self._cookies_setter + def retry_times(self, times): """设置连接失败重连次数""" self._page.retry_times = times @@ -108,23 +116,6 @@ class ChromiumBaseSetter(BasePageSetter): key=item, value=value) self._page.run_cdp_loaded('DOMStorage.disable') - def cookie(self, cookie): - """设置单个cookie - :param cookie: cookie信息 - :return: None - """ - if isinstance(cookie, str): - self.cookies(cookie) - else: - self.cookies([cookie]) - - def cookies(self, cookies): - """设置多个cookie,注意不要传入单个 - :param cookies: cookies信息 - :return: None - """ - set_browser_cookies(self._page, cookies) - def upload_files(self, files): """等待上传的文件路径 :param files: 文件路径列表或字符串,字符串时多个文件用回车分隔 @@ -233,6 +224,14 @@ class SessionPageSetter(BasePageSetter): :param page: SessionPage对象 """ super().__init__(page) + self._cookies_setter = None + + @property + def cookies(self): + """返回用于设置cookies的对象""" + if self._cookies_setter is None: + self._cookies_setter = SessionCookiesSetter(self._page) + return self._cookies_setter def retry_times(self, times): """设置连接失败时重连次数""" @@ -270,23 +269,6 @@ class SessionPageSetter(BasePageSetter): if self._page.response: self._page.response.encoding = encoding - def cookie(self, cookie): - """为Session对象设置单个cookie - :param cookie: cookie信息 - :return: None - """ - if isinstance(cookie, str): - self.cookies(cookie) - else: - self.cookies([cookie]) - - def cookies(self, cookies): - """为Session对象设置多个cookie,注意不要传入单个 - :param cookies: cookies信息 - :return: None - """ - set_session_cookies(self._page.session, cookies) - def headers(self, headers): """设置通用的headers :param headers: dict形式的headers diff --git a/DrissionPage/_units/setter.pyi b/DrissionPage/_units/setter.pyi index 582e1af..415decb 100644 --- a/DrissionPage/_units/setter.pyi +++ b/DrissionPage/_units/setter.pyi @@ -3,14 +3,13 @@ @Author : g1879 @Contact : g1879@qq.com """ -from http.cookiejar import Cookie from pathlib import Path from typing import Union, Tuple, Literal, Any, Optional from requests.adapters import HTTPAdapter from requests.auth import HTTPBasicAuth -from requests.cookies import RequestsCookieJar +from .cookies_setter import SessionCookiesSetter, CookiesSetter from .scroller import PageScroller from .._base.base import BasePage from .._elements.chromium_element import ChromiumElement @@ -34,6 +33,7 @@ class BasePageSetter(object): class ChromiumBaseSetter(BasePageSetter): def __init__(self, page): self._page: ChromiumBase = ... + self._cookies_setter: CookiesSetter = ... @property def load_mode(self) -> LoadMode: ... @@ -41,6 +41,9 @@ class ChromiumBaseSetter(BasePageSetter): @property def scroll(self) -> PageScrollSetter: ... + @property + def cookies(self) -> CookiesSetter: ... + def retry_times(self, times: int) -> None: ... def retry_interval(self, interval: float) -> None: ... @@ -53,10 +56,6 @@ class ChromiumBaseSetter(BasePageSetter): def local_storage(self, item: str, value: Union[str, bool]) -> None: ... - def cookie(self, cookies: Union[RequestsCookieJar, str, dict]) -> None: ... - - def cookies(self, cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: ... - def headers(self, headers: dict) -> None: ... def auto_handle_alert(self, on_off: bool = True, accept: bool = True) -> None: ... @@ -93,6 +92,10 @@ class ChromiumPageSetter(TabSetter): class SessionPageSetter(BasePageSetter): def __init__(self, page: SessionPage): self._page: SessionPage = ... + self._cookies_setter: SessionCookiesSetter = ... + + @property + def cookies(self) -> SessionCookiesSetter: ... def retry_times(self, times: int) -> None: ... @@ -104,10 +107,6 @@ class SessionPageSetter(BasePageSetter): def encoding(self, encoding: Optional[str, None], set_all: bool = True) -> None: ... - def cookie(self, cookie: Union[Cookie, str, dict]) -> None: ... - - def cookies(self, cookies: Union[RequestsCookieJar, list, tuple, str, dict]) -> None: ... - def headers(self, headers: dict) -> None: ... def header(self, attr: str, value: str) -> None: ... diff --git a/DrissionPage/_units/states.py b/DrissionPage/_units/states.py index f1744f9..8294fab 100644 --- a/DrissionPage/_units/states.py +++ b/DrissionPage/_units/states.py @@ -61,18 +61,14 @@ class ElementStates(object): @property def is_covered(self): - """返回元素是否被覆盖,与是否在视口中无关""" + """返回元素是否被覆盖,与是否在视口中无关,如被覆盖返回覆盖元素的backend id,否则返回False""" lx, ly = self._ele.rect.click_point try: - r = self._ele.page.run_cdp('DOM.getNodeForLocation', x=lx, y=ly) + bid = self._ele.page.run_cdp('DOM.getNodeForLocation', x=lx, y=ly).get('backendNodeId') + return bid if bid != self._ele._backend_id else False except CDPError: return False - if r.get('backendNodeId') != self._ele._backend_id: - return True - - return False - @property def has_rect(self): """返回元素是否拥有位置和大小,没有返回False,有返回四个角在页面中坐标组成的列表""" diff --git a/DrissionPage/_units/states.pyi b/DrissionPage/_units/states.pyi index fa8888c..dcd57e5 100644 --- a/DrissionPage/_units/states.pyi +++ b/DrissionPage/_units/states.pyi @@ -3,7 +3,7 @@ @Author : g1879 @Contact : g1879@qq.com """ -from typing import Union, Tuple, List, Optional +from typing import Union, Tuple, List, Optional, Literal from .._elements.chromium_element import ShadowRoot, ChromiumElement from .._pages.chromium_base import ChromiumBase @@ -36,7 +36,7 @@ class ElementStates(object): def is_whole_in_viewport(self) -> bool: ... @property - def is_covered(self) -> bool: ... + def is_covered(self) -> Union[Literal[False], int]: ... @property def has_rect(self) -> Union[bool, List[Tuple[float, float]]]: ...