找不到元素返回NoneElement代替None;增加各种出错提示

This commit is contained in:
g1879 2023-02-15 17:59:09 +08:00
parent b5a86326c5
commit b9801caee7
34 changed files with 169 additions and 110 deletions

View File

@ -5,7 +5,7 @@
""" """
from time import sleep from time import sleep
from .functions.web import location_in_viewport from .common.web import location_in_viewport
from .keys import _modifierBit, _keyDescriptionForString from .keys import _modifierBit, _keyDescriptionForString

View File

@ -7,8 +7,8 @@ from abc import abstractmethod
from re import sub from re import sub
from urllib.parse import quote from urllib.parse import quote
from .functions.web import format_html from .common.web import format_html
from .functions.locator import get_loc from .common.locator import get_loc
class BaseParser(object): class BaseParser(object):

View File

@ -14,11 +14,11 @@ from .base import BasePage
from .chromium_driver import ChromiumDriver from .chromium_driver import ChromiumDriver
from .chromium_element import ChromiumWaiter, ChromiumScroll, ChromiumElement, run_js, make_chromium_ele, \ from .chromium_element import ChromiumWaiter, ChromiumScroll, ChromiumElement, run_js, make_chromium_ele, \
ChromiumElementWaiter ChromiumElementWaiter
from .functions.constants import HANDLE_ALERT_METHOD from .common.constants import HANDLE_ALERT_METHOD, ERROR, NoneElement
from .functions.errors import ContextLossError, ElementLossError, AlertExistsError, CallMethodException from .common.errors import ContextLossError, ElementLossError, AlertExistsError, CallMethodError, TabClosedError
from .functions.locator import get_loc from .common.locator import get_loc
from .functions.tools import get_usable_path from .common.tools import get_usable_path
from .functions.web import offset_scroll, cookies_to_tuple from .common.web import offset_scroll, cookies_to_tuple
from .session_element import make_session_ele from .session_element import make_session_ele
@ -106,9 +106,9 @@ class ChromiumBase(BasePage):
if self._debug_recorder: if self._debug_recorder:
self._debug_recorder.add_data((perf_counter(), '获取document', '开始')) self._debug_recorder.add_data((perf_counter(), '获取document', '开始'))
try: # 处理标签页关闭的情况 try: # 遇到过网站在标签页关闭时触发读取文档导致错误,屏蔽掉
self._wait_loaded() self._wait_loaded()
except ConnectionError: except TabClosedError:
return return
while True: while True:
@ -331,22 +331,22 @@ class ChromiumBase(BasePage):
:return: 执行的结果 :return: 执行的结果
""" """
if self.driver.has_alert and cmd != HANDLE_ALERT_METHOD: if self.driver.has_alert and cmd != HANDLE_ALERT_METHOD:
raise AlertExistsError('存在未处理的提示框。') raise AlertExistsError
r = self.driver.call_method(cmd, **cmd_args) r = self.driver.call_method(cmd, **cmd_args)
if 'error' not in r: if ERROR not in r:
return r return r
if r['error'] == 'Cannot find context with specified id': if r[ERROR] == 'Cannot find context with specified id':
raise ContextLossError('页面被刷新,请操作前尝试等待页面刷新或加载完成。') raise ContextLossError
elif r['error'] in ('Could not find node with given id', 'Could not find object with given id'): elif r[ERROR] in ('Could not find node with given id', 'Could not find object with given id'):
raise ElementLossError('该元素已不在当前页面中。') raise ElementLossError
elif r['error'] == 'tab closed': elif r[ERROR] == 'tab closed':
raise RuntimeError('标签页已关闭。') raise TabClosedError
elif r['error'] == 'alert exists': elif r[ERROR] == 'alert exists':
pass pass
elif r['type'] == 'call_method_error': elif r['type'] == 'call_method_error':
raise CallMethodException(f'\n错误:{r["error"]}\nmethod{r["method"]}\nargs{r["args"]}') raise CallMethodError(f'\n错误:{r["error"]}\nmethod{r["method"]}\nargs{r["args"]}')
else: else:
raise RuntimeError(r) raise RuntimeError(r)
@ -486,7 +486,7 @@ class ChromiumBase(BasePage):
count = search_result['resultCount'] count = search_result['resultCount']
if not nodeIds: if not nodeIds:
return None if single else [] return NoneElement() if single else []
if single: if single:
return make_chromium_ele(self, node_id=nodeIds['nodeIds'][0]) return make_chromium_ele(self, node_id=nodeIds['nodeIds'][0])
@ -583,7 +583,7 @@ class ChromiumBase(BasePage):
pic_type = 'png' pic_type = 'png'
else: else:
if as_bytes not in ('jpg', 'jpeg', 'png', 'webp'): if as_bytes not in ('jpg', 'jpeg', 'png', 'webp'):
raise ValueError("只能接收'jpg', 'jpeg', 'png', 'webp'四种格式。") raise ValueError("只能接收 'jpg', 'jpeg', 'png', 'webp' 四种格式。")
pic_type = 'jpeg' if as_bytes == 'jpg' else as_bytes pic_type = 'jpeg' if as_bytes == 'jpg' else as_bytes
else: else:

View File

@ -10,6 +10,7 @@ from DataRecorder import Recorder
from requests import Session from requests import Session
from requests.cookies import RequestsCookieJar from requests.cookies import RequestsCookieJar
from .common.constants import NoneElement
from .base import BasePage from .base import BasePage
from .chromium_driver import ChromiumDriver from .chromium_driver import ChromiumDriver
from .chromium_element import ChromiumElement, ChromiumScroll, ChromiumElementWaiter, ChromiumWaiter from .chromium_element import ChromiumElement, ChromiumScroll, ChromiumElementWaiter, ChromiumWaiter
@ -150,21 +151,21 @@ class ChromiumBase(BasePage):
def ele(self, def ele(self,
loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame],
timeout: float = None) -> Union[ChromiumElement, ChromiumFrame, None]: ... timeout: float = None) -> Union[ChromiumElement, ChromiumFrame, NoneElement]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> List[Union[ChromiumElement, ChromiumFrame]]: ... timeout: float = None) -> List[Union[ChromiumElement, ChromiumFrame]]: ...
def s_ele(self, loc_or_ele: Union[Tuple[str, str], str] = None) \ def s_ele(self, loc_or_ele: Union[Tuple[str, str], str] = None) \
-> Union[SessionElement, str, None]: ... -> Union[SessionElement, str, NoneElement]: ...
def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ...
def _ele(self, def _ele(self,
loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame], loc_or_ele: Union[Tuple[str, str], str, ChromiumElement, ChromiumFrame],
timeout: float = None, single: bool = True, relative: bool = False) \ timeout: float = None, single: bool = True, relative: bool = False) \
-> Union[ChromiumElement, ChromiumFrame, None, List[Union[ChromiumElement, ChromiumFrame]]]: ... -> Union[ChromiumElement, ChromiumFrame, NoneElement, List[Union[ChromiumElement, ChromiumFrame]]]: ...
def wait_ele(self, def wait_ele(self,
loc_or_ele: Union[str, tuple, ChromiumElement], loc_or_ele: Union[str, tuple, ChromiumElement],

View File

@ -11,7 +11,7 @@ from threading import Thread, Event
from websocket import WebSocketTimeoutException, WebSocketException, WebSocketConnectionClosedException, \ from websocket import WebSocketTimeoutException, WebSocketException, WebSocketConnectionClosedException, \
create_connection create_connection
from .functions.errors import CallMethodException from .common.errors import CallMethodError
class GenericAttr(object): class GenericAttr(object):
@ -171,7 +171,7 @@ class ChromiumDriver(object):
self.start() self.start()
# raise RuntimeError("不能在启动前调用方法。") # raise RuntimeError("不能在启动前调用方法。")
if args: if args:
raise CallMethodException("参数必须是key=value形式。") raise CallMethodError("参数必须是key=value形式。")
if self._stopped.is_set(): if self._stopped.is_set():
return {'error': 'tab closed', 'type': 'tab_closed'} return {'error': 'tab closed', 'type': 'tab_closed'}
@ -215,9 +215,9 @@ class ChromiumDriver(object):
if self._ws: if self._ws:
self._ws.close() self._ws.close()
self._ws = None self._ws = None
self.event_handlers = None self.event_handlers.clear()
self.method_results = None self.method_results.clear()
self.event_queue = None self.event_queue.queue.clear()
return True return True
def set_listener(self, event, callback): def set_listener(self, event, callback):

View File

@ -33,9 +33,9 @@ class ChromiumDriver(object):
_stopped: Event _stopped: Event
_started: bool _started: bool
status: str status: str
event_handlers: Union[dict, None] event_handlers: dict
method_results: Union[dict, None] method_results: dict
event_queue: Union[Queue, None] event_queue: Queue
def __init__(self, tab_id: str, tab_type: str, address: str): ... def __init__(self, tab_id: str, tab_type: str, address: str): ...

View File

@ -10,10 +10,10 @@ from time import perf_counter, sleep
from warnings import warn from warnings import warn
from .base import DrissionElement, BaseElement from .base import DrissionElement, BaseElement
from .functions.constants import FRAME_ELEMENT from .common.constants import FRAME_ELEMENT, NoneElement
from .functions.errors import ContextLossError, ElementLossError, CallMethodException from .common.errors import ContextLossError, ElementLossError, CallMethodError
from .functions.locator import get_loc from .common.locator import get_loc
from .functions.web import make_absolute_link, get_ele_txt, format_html, is_js_func, location_in_viewport, offset_scroll from .common.web import make_absolute_link, get_ele_txt, format_html, is_js_func, location_in_viewport, offset_scroll
from .keys import _keys_to_typing, _keyDescriptionForString, _keyDefinitions from .keys import _keys_to_typing, _keyDescriptionForString, _keyDefinitions
from .session_element import make_session_ele from .session_element import make_session_ele
@ -826,7 +826,7 @@ class ChromiumElement(DrissionElement):
""" """
try: try:
return self.page.run_cdp('DOM.getBoxModel', nodeId=self.node_id)['model'][quad] return self.page.run_cdp('DOM.getBoxModel', nodeId=self.node_id)['model'][quad]
except CallMethodException: except CallMethodError:
return None return None
def _get_absolute_rect(self, x, y): def _get_absolute_rect(self, x, y):
@ -1073,13 +1073,12 @@ class ChromiumShadowRootElement(BaseElement):
eles = make_session_ele(self.html).eles(loc) eles = make_session_ele(self.html).eles(loc)
if not eles: if not eles:
return None if single else eles return NoneElement() if single else eles
css_paths = [i.css_path[47:] for i in eles] css_paths = [i.css_path[47:] for i in eles]
if single: if single:
node_id = self.page.run_cdp('DOM.querySelector', node_id = self.page.run_cdp('DOM.querySelector', nodeId=self._node_id, selector=css_paths[0])['nodeId']
nodeId=self._node_id, selector=css_paths[0])['nodeId'] return make_chromium_ele(self.page, node_id=node_id) if node_id else NoneElement()
return make_chromium_ele(self.page, node_id=node_id) if node_id else None
else: else:
results = [] results = []
@ -1171,7 +1170,7 @@ def find_by_xpath(ele, xpath, single, timeout, relative=True):
userGesture=True) userGesture=True)
if single: if single:
return None if r['result']['subtype'] == 'null' else make_chromium_ele(ele.page, obj_id=r['result']['objectId']) return NoneElement() if r['result']['subtype'] == 'null' else make_chromium_ele(ele.page, obj_id=r['result']['objectId'])
if r['result']['description'] == 'NodeList(0)': if r['result']['description'] == 'NodeList(0)':
return [] return []
@ -1208,7 +1207,7 @@ def find_by_css(ele, selector, single, timeout):
userGesture=True) userGesture=True)
if single: if single:
return None if r['result']['subtype'] == 'null' else make_chromium_ele(ele.page, obj_id=r['result']['objectId']) return NoneElement() if r['result']['subtype'] == 'null' else make_chromium_ele(ele.page, obj_id=r['result']['objectId'])
if r['result']['description'] == 'NodeList(0)': if r['result']['description'] == 'NodeList(0)':
return [] return []
@ -1729,7 +1728,7 @@ class ChromiumElementWaiter(object):
return True return True
ele = self.driver(self.loc_or_ele, timeout=.5) ele = self.driver(self.loc_or_ele, timeout=.5)
if ele is None: if not ele:
return True return True
end_time = perf_counter() + self.timeout end_time = perf_counter() + self.timeout
@ -1753,7 +1752,7 @@ class ChromiumElementWaiter(object):
:return: 是否等待成功 :return: 是否等待成功
""" """
target = self.driver(self.loc_or_ele) target = self.driver(self.loc_or_ele)
if target is None: if not target:
return None return None
end_time = perf_counter() + self.timeout end_time = perf_counter() + self.timeout

View File

@ -6,6 +6,7 @@
from pathlib import Path from pathlib import Path
from typing import Union, Tuple, List, Any from typing import Union, Tuple, List, Any
from .common.constants import NoneElement
from .base import DrissionElement, BaseElement from .base import DrissionElement, BaseElement
from .chromium_base import ChromiumBase from .chromium_base import ChromiumBase
from .chromium_frame import ChromiumFrame from .chromium_frame import ChromiumFrame
@ -183,20 +184,20 @@ class ChromiumElement(DrissionElement):
def ele(self, def ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> Union[ChromiumElement, ChromiumFrame, str, None]: ... timeout: float = None) -> Union[ChromiumElement, ChromiumFrame, str, NoneElement]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> List[Union[ChromiumElement, ChromiumFrame, str]]: ... timeout: float = None) -> List[Union[ChromiumElement, ChromiumFrame, str]]: ...
def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = None) -> Union[SessionElement, str, None]: ... def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = None) -> Union[SessionElement, str, NoneElement]: ...
def s_eles(self, loc_or_str: Union[Tuple[str, str], str] = None) -> List[Union[SessionElement, str]]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str] = None) -> List[Union[SessionElement, str]]: ...
def _ele(self, def _ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None, single: bool = True, relative: bool = False) \ timeout: float = None, single: bool = True, relative: bool = False) \
-> Union[ChromiumElement, ChromiumFrame, str, None, List[Union[ChromiumElement, ChromiumFrame, str]]]: ... -> Union[ChromiumElement, ChromiumFrame, str, NoneElement, List[Union[ChromiumElement, ChromiumFrame, str]]]: ...
def style(self, style: str, pseudo_ele: str = '') -> str: ... def style(self, style: str, pseudo_ele: str = '') -> str: ...
@ -315,13 +316,13 @@ class ChromiumShadowRootElement(BaseElement):
def ele(self, def ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> Union[ChromiumElement, ChromiumFrame, None]: ... timeout: float = None) -> Union[ChromiumElement, ChromiumFrame, NoneElement]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> List[Union[ChromiumElement, ChromiumFrame]]: ... timeout: float = None) -> List[Union[ChromiumElement, ChromiumFrame]]: ...
def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = None) -> Union[SessionElement, str, None]: ... def s_ele(self, loc_or_str: Union[Tuple[str, str], str] = None) -> Union[SessionElement, str, NoneElement]: ...
def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ...
@ -329,7 +330,7 @@ class ChromiumShadowRootElement(BaseElement):
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None, timeout: float = None,
single: bool = True, relative: bool = False) \ single: bool = True, relative: bool = False) \
-> Union[ChromiumElement, ChromiumFrame, None, str, List[Union[ChromiumElement, ChromiumFrame, str]]]: ... -> Union[ChromiumElement, ChromiumFrame, NoneElement, str, List[Union[ChromiumElement, ChromiumFrame, str]]]: ...
def _get_node_id(self, obj_id: str) -> str: ... def _get_node_id(self, obj_id: str) -> str: ...
@ -342,21 +343,21 @@ def find_in_chromium_ele(ele: ChromiumElement,
loc: Union[str, Tuple[str, str]], loc: Union[str, Tuple[str, str]],
single: bool = True, single: bool = True,
timeout: float = None, timeout: float = None,
relative: bool = True) -> Union[ relative: bool = True)\
ChromiumElement, str, None, List[Union[ChromiumElement, str]]]: ... -> Union[ChromiumElement, str, NoneElement, List[Union[ChromiumElement, str]]]: ...
def find_by_xpath(ele: ChromiumElement, def find_by_xpath(ele: ChromiumElement,
xpath: str, xpath: str,
single: bool, single: bool,
timeout: float, timeout: float,
relative: bool = True) -> Union[ChromiumElement, List[ChromiumElement], None]: ... relative: bool = True) -> Union[ChromiumElement, List[ChromiumElement], NoneElement]: ...
def find_by_css(ele: ChromiumElement, def find_by_css(ele: ChromiumElement,
selector: str, selector: str,
single: bool, single: bool,
timeout: float) -> Union[ChromiumElement, List[ChromiumElement], None]: ... timeout: float) -> Union[ChromiumElement, List[ChromiumElement], NoneElement]: ...
def make_chromium_ele(page: ChromiumBase, node_id: str = ..., obj_id: str = ...) -> Union[ def make_chromium_ele(page: ChromiumBase, node_id: str = ..., obj_id: str = ...) -> Union[

View File

@ -12,12 +12,13 @@ from warnings import warn
from requests import Session from requests import Session
from .chromium_base import ChromiumBase, Timeout, ChromiumBaseSetter from .chromium_base import ChromiumBase, Timeout, ChromiumBaseSetter
from .chromium_driver import ChromiumDriver, CallMethodException from .chromium_driver import ChromiumDriver
from .chromium_tab import ChromiumTab from .chromium_tab import ChromiumTab
from .configs.chromium_options import ChromiumOptions from .configs.chromium_options import ChromiumOptions
from .configs.driver_options import DriverOptions from .configs.driver_options import DriverOptions
from .functions.browser import connect_browser from .common.browser import connect_browser
from .functions.web import set_session_cookies from .common.errors import CallMethodError
from .common.web import set_session_cookies
from .session_page import DownloadSetter from .session_page import DownloadSetter
@ -405,7 +406,7 @@ class ChromiumDownloadSetter(DownloadSetter):
try: try:
self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', downloadPath=path, self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', downloadPath=path,
eventsEnabled=True) eventsEnabled=True)
except CallMethodException: except CallMethodError:
warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。') warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。')
self._page.run_cdp('Page.setDownloadBehavior', behavior='allow', downloadPath=path) self._page.run_cdp('Page.setDownloadBehavior', behavior='allow', downloadPath=path)
@ -417,7 +418,7 @@ class ChromiumDownloadSetter(DownloadSetter):
self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', eventsEnabled=True, self._page.browser_driver.Browser.setDownloadBehavior(behavior='allow', eventsEnabled=True,
downloadPath=self._page.download_path) downloadPath=self._page.download_path)
self._page.browser_driver.Browser.downloadWillBegin = self._download_by_browser self._page.browser_driver.Browser.downloadWillBegin = self._download_by_browser
except CallMethodException: except CallMethodError:
self._page.driver.Page.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path) self._page.driver.Page.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path)
self._page.driver.Page.downloadWillBegin = self._download_by_browser self._page.driver.Page.downloadWillBegin = self._download_by_browser
@ -428,7 +429,7 @@ class ChromiumDownloadSetter(DownloadSetter):
try: try:
self._page.browser_driver.Browser.setDownloadBehavior(behavior='deny', eventsEnabled=True) self._page.browser_driver.Browser.setDownloadBehavior(behavior='deny', eventsEnabled=True)
self._page.browser_driver.Browser.downloadWillBegin = self._download_by_DownloadKit self._page.browser_driver.Browser.downloadWillBegin = self._download_by_DownloadKit
except CallMethodException: except CallMethodError:
raise RuntimeError('您的浏览器版本太低,不支持此方法,请升级。') raise RuntimeError('您的浏览器版本太低,不支持此方法,请升级。')
self._behavior = 'deny' self._behavior = 'deny'

View File

@ -0,0 +1,31 @@
# -*- coding:utf-8 -*-
from .errors import NotElementFoundError
HANDLE_ALERT_METHOD = 'Page.handleJavaScriptDialog'
FRAME_ELEMENT = ('iframe', 'frame')
ERROR = 'error'
class NoneElement(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(NoneElement, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __call__(self, *args, **kwargs):
raise NotElementFoundError
def __getattr__(self, item):
raise NotElementFoundError
def __eq__(self, other):
if other is None:
return True
def __bool__(self):
return False
def __repr__(self):
return 'None'

View File

@ -0,0 +1,36 @@
# -*- coding:utf-8 -*-
class BaseError(Exception):
_info = None
def __init__(self, ErrorInfo=None):
super().__init__(self) # 初始化父类
self._info = ErrorInfo or self._info
def __str__(self):
return self._info
class AlertExistsError(BaseError):
_info = '存在未处理的提示框。'
class ContextLossError(BaseError):
_info = '页面被刷新,请操作前尝试等待页面刷新或加载完成。'
class ElementLossError(BaseError):
_info = '该元素对象已不在当前页面中。'
class CallMethodError(BaseError):
_info = '方法调用错误。'
class TabClosedError(BaseError):
_info = '标签页已关闭。'
class NotElementFoundError(BaseError):
_info = '没有找到元素。'

View File

@ -6,7 +6,7 @@
from pathlib import Path from pathlib import Path
from tempfile import gettempdir, TemporaryDirectory from tempfile import gettempdir, TemporaryDirectory
from DrissionPage.functions.tools import port_is_using, clean_folder from DrissionPage.common.tools import port_is_using, clean_folder
from .options_manage import OptionsManager from .options_manage import OptionsManager

View File

@ -5,7 +5,7 @@
""" """
from pathlib import Path from pathlib import Path
from DrissionPage.functions.web import cookies_to_tuple from DrissionPage.common.web import cookies_to_tuple
from .options_manage import OptionsManager from .options_manage import OptionsManager

View File

@ -14,9 +14,9 @@ from selenium.webdriver.chrome.options import Options
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
from tldextract import extract from tldextract import extract
from .functions.tools import get_pid_from_port from .common.tools import get_pid_from_port
from .functions.browser import connect_browser from .common.browser import connect_browser
from .functions.web import cookies_to_tuple from .common.web import cookies_to_tuple
from .configs.session_options import SessionOptions, session_options_to_dict from .configs.session_options import SessionOptions, session_options_to_dict
from .configs.driver_options import DriverOptions from .configs.driver_options import DriverOptions

View File

@ -15,9 +15,9 @@ from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support.wait import WebDriverWait
from .base import DrissionElement, BaseElement from .base import DrissionElement, BaseElement
from .functions.locator import str_to_loc, get_loc from .common.locator import str_to_loc, get_loc
from .functions.tools import get_usable_path from .common.tools import get_usable_path
from .functions.web import format_html, get_ele_txt from .common.web import format_html, get_ele_txt
from .session_element import make_session_ele from .session_element import make_session_ele

View File

@ -13,7 +13,7 @@ from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support.wait import WebDriverWait
from .base import BasePage from .base import BasePage
from .functions.tools import get_usable_path from .common.tools import get_usable_path
from .driver_element import DriverElement, make_driver_ele, Scroll, ElementWaiter from .driver_element import DriverElement, make_driver_ele, Scroll, ElementWaiter
from .session_element import make_session_ele from .session_element import make_session_ele

View File

@ -14,7 +14,7 @@ from .configs.chromium_options import ChromiumOptions
from .configs.driver_options import DriverOptions from .configs.driver_options import DriverOptions
from .configs.options_manage import OptionsManager from .configs.options_manage import OptionsManager
from .drission import Drission from .drission import Drission
from .functions.tools import unzip from .common.tools import unzip
from .session_page import SessionPage from .session_page import SessionPage
@ -287,8 +287,9 @@ def get_chrome_path(ini_path=None,
try: try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe', r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe',
# r'HKEY_CURRENT_USER\Software\Google\Chrome\BLBeacon\version',
reserved=0, access=winreg.KEY_READ) reserved=0, access=winreg.KEY_READ)
# key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Google\Chrome\BLBeacon\version',
# reserved=0, access=winreg.KEY_READ)
k = winreg.EnumValue(key, 0) k = winreg.EnumValue(key, 0)
winreg.CloseKey(key) winreg.CloseKey(key)

View File

@ -1,3 +0,0 @@
# -*- coding:utf-8 -*-
HANDLE_ALERT_METHOD = 'Page.handleJavaScriptDialog'
FRAME_ELEMENT = ('iframe', 'frame')

View File

@ -1,15 +0,0 @@
# -*- coding:utf-8 -*-
class AlertExistsError(Exception):
pass
class ContextLossError(Exception):
pass
class ElementLossError(Exception):
pass
class CallMethodException(Exception):
pass

View File

@ -4,6 +4,7 @@
@Contact : g1879@qq.com @Contact : g1879@qq.com
""" """
from .base import BasePage from .base import BasePage
from .common.constants import NoneElement
from .drission import Drission from .drission import Drission
from .driver_page import DriverPage from .driver_page import DriverPage
from .session_page import SessionPage from .session_page import SessionPage
@ -154,7 +155,8 @@ class MixPage(SessionPage, DriverPage, BasePage):
:return: 元素对象或属性文本节点文本 :return: 元素对象或属性文本节点文本
""" """
if self._mode == 's': if self._mode == 's':
return super()._ele(loc_or_ele, single=single) r = super()._ele(loc_or_ele, single=single)
return None if isinstance(r, NoneElement) else r
elif self._mode == 'd': elif self._mode == 'd':
return super(SessionPage, self)._ele(loc_or_ele, timeout=timeout, single=single) return super(SessionPage, self)._ele(loc_or_ele, timeout=timeout, single=single)

View File

@ -10,8 +10,9 @@ from lxml.etree import tostring
from lxml.html import HtmlElement, fromstring from lxml.html import HtmlElement, fromstring
from .base import DrissionElement, BasePage, BaseElement from .base import DrissionElement, BasePage, BaseElement
from .functions.web import get_ele_txt, make_absolute_link from .common.constants import NoneElement
from .functions.locator import get_loc from .common.locator import get_loc
from .common.web import get_ele_txt, make_absolute_link
class SessionElement(DrissionElement): class SessionElement(DrissionElement):
@ -343,7 +344,7 @@ def make_session_ele(html_or_ele, loc=None, single=True):
elif isinstance(ele, str): elif isinstance(ele, str):
return ele return ele
else: else:
return None return NoneElement()
else: # 返回全部 else: # 返回全部
return [SessionElement(e, page) if isinstance(e, HtmlElement) else e for e in ele if e != '\n'] return [SessionElement(e, page) if isinstance(e, HtmlElement) else e for e in ele if e != '\n']

View File

@ -7,12 +7,13 @@ from typing import Union, List, Tuple
from lxml.html import HtmlElement from lxml.html import HtmlElement
from .driver_page import DriverPage
from .base import DrissionElement, BaseElement from .base import DrissionElement, BaseElement
from .chromium_base import ChromiumBase from .chromium_base import ChromiumBase
from .chromium_element import ChromiumElement from .chromium_element import ChromiumElement
from .chromium_frame import ChromiumFrame from .chromium_frame import ChromiumFrame
from .common.constants import NoneElement
from .driver_element import DriverElement from .driver_element import DriverElement
from .driver_page import DriverPage
from .session_page import SessionPage from .session_page import SessionPage
@ -91,14 +92,14 @@ class SessionElement(DrissionElement):
def ele(self, def ele(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> Union['SessionElement', str, None]: ... timeout: float = None) -> Union['SessionElement', str, NoneElement]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> List[Union['SessionElement', str]]: ... timeout: float = None) -> List[Union['SessionElement', str]]: ...
def s_ele(self, def s_ele(self,
loc_or_str: Union[Tuple[str, str], str] = None) -> Union['SessionElement', str, None]: ... loc_or_str: Union[Tuple[str, str], str] = None) -> Union['SessionElement', str, NoneElement]: ...
def s_eles(self, def s_eles(self,
loc_or_str: Union[Tuple[str, str], str]) -> List[Union['SessionElement', str]]: ... loc_or_str: Union[Tuple[str, str], str]) -> List[Union['SessionElement', str]]: ...
@ -107,7 +108,7 @@ class SessionElement(DrissionElement):
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None, timeout: float = None,
single: bool = True, single: bool = True,
relative: bool = False) -> Union['SessionElement', str, None, List[Union['SessionElement', str]]]: ... relative: bool = False) -> Union['SessionElement', str, NoneElement, List[Union['SessionElement', str]]]: ...
def _get_ele_path(self, mode: str) -> str: ... def _get_ele_path(self, mode: str) -> str: ...
@ -115,4 +116,4 @@ class SessionElement(DrissionElement):
def make_session_ele(html_or_ele: Union[str, SessionElement, SessionPage, ChromiumElement, DriverElement, BaseElement, def make_session_ele(html_or_ele: Union[str, SessionElement, SessionPage, ChromiumElement, DriverElement, BaseElement,
ChromiumFrame, ChromiumBase, DriverPage], ChromiumFrame, ChromiumBase, DriverPage],
loc: Union[str, Tuple[str, str]] = None, loc: Union[str, Tuple[str, str]] = None,
single: bool = True) -> Union[SessionElement, str, None, List[Union[SessionElement, str]]]: ... single: bool = True) -> Union[SessionElement, str, NoneElement, List[Union[SessionElement, str]]]: ...

View File

@ -15,7 +15,7 @@ from tldextract import extract
from .base import BasePage from .base import BasePage
from .configs.session_options import SessionOptions from .configs.session_options import SessionOptions
from .functions.web import cookie_to_dict, set_session_cookies from .common.web import cookie_to_dict, set_session_cookies
from .session_element import SessionElement, make_session_ele from .session_element import SessionElement, make_session_ele

View File

@ -13,6 +13,7 @@ from requests.auth import HTTPBasicAuth
from requests.cookies import RequestsCookieJar from requests.cookies import RequestsCookieJar
from requests.structures import CaseInsensitiveDict from requests.structures import CaseInsensitiveDict
from .common.constants import NoneElement
from .base import BasePage from .base import BasePage
from .chromium_page import ChromiumPage from .chromium_page import ChromiumPage
from .configs.session_options import SessionOptions from .configs.session_options import SessionOptions
@ -52,7 +53,7 @@ class SessionPage(BasePage):
def __call__(self, def __call__(self,
loc_or_str: Union[Tuple[str, str], str, SessionElement], loc_or_str: Union[Tuple[str, str], str, SessionElement],
timeout: float = None) -> Union[SessionElement, str, None]: ... timeout: float = None) -> Union[SessionElement, str, NoneElement]: ...
# -----------------共有属性和方法------------------- # -----------------共有属性和方法-------------------
@property @property
@ -95,21 +96,22 @@ class SessionPage(BasePage):
def ele(self, def ele(self,
loc_or_ele: Union[Tuple[str, str], str, SessionElement], loc_or_ele: Union[Tuple[str, str], str, SessionElement],
timeout: float = None) -> Union[SessionElement, str, None]: ... timeout: float = None) -> Union[SessionElement, str, NoneElement]: ...
def eles(self, def eles(self,
loc_or_str: Union[Tuple[str, str], str], loc_or_str: Union[Tuple[str, str], str],
timeout: float = None) -> List[Union[SessionElement, str]]: ... timeout: float = None) -> List[Union[SessionElement, str]]: ...
def s_ele(self, def s_ele(self,
loc_or_ele: Union[Tuple[str, str], str, SessionElement] = None) -> Union[SessionElement, str, None]: ... loc_or_ele: Union[Tuple[str, str], str, SessionElement] = None) \
-> Union[SessionElement, str, NoneElement]: ...
def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ... def s_eles(self, loc_or_str: Union[Tuple[str, str], str]) -> List[Union[SessionElement, str]]: ...
def _ele(self, def _ele(self,
loc_or_ele: Union[Tuple[str, str], str, SessionElement], loc_or_ele: Union[Tuple[str, str], str, SessionElement],
timeout: float = None, timeout: float = None,
single: bool = True) -> Union[SessionElement, str, None, List[Union[SessionElement, str]]]: ... single: bool = True) -> Union[SessionElement, str, NoneElement, List[Union[SessionElement, str]]]: ...
def get_cookies(self, def get_cookies(self,
as_dict: bool = False, as_dict: bool = False,

View File

@ -9,7 +9,7 @@ from typing import Union
from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.remote.webelement import WebElement
from .base import BaseElement from .base import BaseElement
from .functions.locator import get_loc from .common.locator import get_loc
from .driver_element import make_driver_ele from .driver_element import make_driver_ele
from .session_element import make_session_ele, SessionElement from .session_element import make_session_ele, SessionElement

View File

@ -11,8 +11,9 @@ from tldextract import extract
from .base import BasePage from .base import BasePage
from .chromium_base import ChromiumBase, Timeout from .chromium_base import ChromiumBase, Timeout
from .chromium_driver import ChromiumDriver, CallMethodException from .chromium_driver import ChromiumDriver
from .chromium_page import ChromiumPage, ChromiumDownloadSetter, ChromiumPageSetter from .chromium_page import ChromiumPage, ChromiumDownloadSetter, ChromiumPageSetter
from .common.errors import CallMethodError
from .configs.chromium_options import ChromiumOptions from .configs.chromium_options import ChromiumOptions
from .configs.driver_options import DriverOptions from .configs.driver_options import DriverOptions
from .configs.session_options import SessionOptions from .configs.session_options import SessionOptions
@ -527,7 +528,7 @@ class WebPageDownloadSetter(ChromiumDownloadSetter):
try: try:
self._page.browser_driver.Browser.setDownloadBehavior(behavior=self._behavior, downloadPath=path, self._page.browser_driver.Browser.setDownloadBehavior(behavior=self._behavior, downloadPath=path,
eventsEnabled=True) eventsEnabled=True)
except CallMethodException: except CallMethodError:
warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。') warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。')
self._page.run_cdp('Page.setDownloadBehavior', behavior=self._behavior, downloadPath=path) self._page.run_cdp('Page.setDownloadBehavior', behavior=self._behavior, downloadPath=path)
@ -541,7 +542,7 @@ class WebPageDownloadSetter(ChromiumDownloadSetter):
downloadPath=self._page.download_path) downloadPath=self._page.download_path)
self._page.browser_driver.Browser.downloadWillBegin = self._download_by_browser self._page.browser_driver.Browser.downloadWillBegin = self._download_by_browser
except CallMethodException: except CallMethodError:
warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。') warn('\n您的浏览器版本太低,用新标签页下载文件可能崩溃,建议升级。')
self._page.driver.Page.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path) self._page.driver.Page.setDownloadBehavior(behavior='allow', downloadPath=self._page.download_path)
self._page.driver.Page.downloadWillBegin = self._download_by_browser self._page.driver.Page.downloadWillBegin = self._download_by_browser
@ -554,7 +555,7 @@ class WebPageDownloadSetter(ChromiumDownloadSetter):
try: try:
self._page.browser_driver.Browser.setDownloadBehavior(behavior='deny', eventsEnabled=True) self._page.browser_driver.Browser.setDownloadBehavior(behavior='deny', eventsEnabled=True)
self._page.browser_driver.Browser.downloadWillBegin = self._download_by_DownloadKit self._page.browser_driver.Browser.downloadWillBegin = self._download_by_DownloadKit
except CallMethodException: except CallMethodError:
raise RuntimeError('您的浏览器版本太低,不支持此方法,请升级。') raise RuntimeError('您的浏览器版本太低,不支持此方法,请升级。')
self._behavior = 'deny' self._behavior = 'deny'