diff --git a/DrissionPage/chromium_base.py b/DrissionPage/chromium_base.py index 0ab42ba..82a299d 100644 --- a/DrissionPage/chromium_base.py +++ b/DrissionPage/chromium_base.py @@ -15,7 +15,8 @@ from .chromium_driver import ChromiumDriver from .chromium_element import ChromiumWaiter, ChromiumScroll, ChromiumElement, run_js, make_chromium_ele, \ ChromiumElementWaiter from .common.constants import HANDLE_ALERT_METHOD, ERROR, NoneElement -from .common.errors import ContextLossError, ElementLossError, AlertExistsError, CallMethodError, TabClosedError +from .common.errors import ContextLossError, ElementLossError, AlertExistsError, CallMethodError, TabClosedError, \ + NoRectError from .common.locator import get_loc from .common.tools import get_usable_path from .common.web import offset_scroll, cookies_to_tuple @@ -346,6 +347,8 @@ class ChromiumBase(BasePage): raise TabClosedError elif r[ERROR] == 'alert exists': pass + elif r[ERROR] in ('Node does not have a layout object', 'Could not compute box model.'): + raise NoRectError elif r['type'] == 'call_method_error': raise CallMethodError(f'\n错误:{r["error"]}\nmethod:{r["method"]}\nargs:{r["args"]}') else: @@ -924,7 +927,7 @@ class ChromiumPageScroll(ChromiumScroll): """ ele = self._driver.ele(loc_or_ele) try: - self._driver.run_cdp('DOM.scrollIntoViewIfNeeded', nodeId=ele.node_id) + self._driver.run_cdp('DOM.scrollIntoViewIfNeeded', nodeId=ele.ids.node_id) except Exception: ele.run_js("this.scrollIntoView();") diff --git a/DrissionPage/chromium_element.py b/DrissionPage/chromium_element.py index 93ab47f..4a29eba 100644 --- a/DrissionPage/chromium_element.py +++ b/DrissionPage/chromium_element.py @@ -11,7 +11,7 @@ from warnings import warn from .base import DrissionElement, BaseElement from .common.constants import FRAME_ELEMENT, NoneElement -from .common.errors import ContextLossError, ElementLossError, JavaScriptError +from .common.errors import ContextLossError, ElementLossError, JavaScriptError, NoRectError from .common.locator import get_loc 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 @@ -1515,37 +1515,37 @@ class Locations(object): def location(self): """返回元素左上角的绝对坐标""" cl = self.viewport_location - return self._get_page_coord(cl[0], cl[1]) if cl else (0, 0) + return self._get_page_coord(cl[0], cl[1]) @property def midpoint(self): """返回元素中间点的绝对坐标""" cl = self.viewport_midpoint - return self._get_page_coord(cl[0], cl[1]) if cl else (0, 0) + return self._get_page_coord(cl[0], cl[1]) @property def click_point(self): """返回元素接受点击的点的绝对坐标""" cl = self.viewport_click_point - return self._get_page_coord(cl[0], cl[1]) if cl else (0, 0) + return self._get_page_coord(cl[0], cl[1]) @property def viewport_location(self): """返回元素左上角在视口中的坐标""" m = self._get_viewport_rect('border') - return (int(m[0]), int(m[1])) if m else (0, 0) + return int(m[0]), int(m[1]) @property def viewport_midpoint(self): """返回元素中间点在视口中的坐标""" m = self._get_viewport_rect('border') - return (int(m[0] + (m[2] - m[0]) // 2), int(m[3] + (m[5] - m[3]) // 2)) if m else (0, 0) + return int(m[0] + (m[2] - m[0]) // 2), int(m[3] + (m[5] - m[3]) // 2) @property def viewport_click_point(self): """返回元素接受点击的点视口坐标""" m = self._get_viewport_rect('padding') - return (int(self.viewport_midpoint[0]), int(m[1]) + 1) if m else (0, 0) + return int(self.viewport_midpoint[0]), int(m[1]) + 1 @property def screen_location(self): @@ -1573,10 +1573,7 @@ class Locations(object): :param quad: 方框类型,margin border padding :return: 四个角坐标,大小为0时返回None """ - try: - return self._ele.page.run_cdp('DOM.getBoxModel', nodeId=self._ele.ids.node_id)['model'][quad] - except Exception: - return None + return self._ele.page.run_cdp('DOM.getBoxModel', nodeId=self._ele.ids.node_id)['model'][quad] def _get_page_coord(self, x, y): """根据绝对坐标获取窗口坐标""" @@ -1628,25 +1625,29 @@ class Click(object): return True if not by_js: - self._ele.page.scroll.to_see(self._ele) - if self._ele.states.is_in_viewport: - client_x, client_y = self._ele.locations.viewport_click_point - if client_x: - loc_x, loc_y = self._ele.locations.click_point + try: + self._ele.page.scroll.to_see(self._ele) + if self._ele.states.is_in_viewport: + client_x, client_y = self._ele.locations.viewport_click_point + if client_x: + loc_x, loc_y = self._ele.locations.click_point - click = do_it(client_x, client_y, loc_x, loc_y) - if click: - self._ele.page.wait.load_start(wait_loading) - return True - - timeout = timeout if timeout is not None else self._ele.page.timeout - end_time = perf_counter() + timeout - while click is False and perf_counter() < end_time: click = do_it(client_x, client_y, loc_x, loc_y) + if click: + self._ele.page.wait.load_start(wait_loading) + return True - if click is not None: - self._ele.page.wait.load_start(wait_loading) - return True + timeout = timeout if timeout is not None else self._ele.page.timeout + end_time = perf_counter() + timeout + while click is False and perf_counter() < end_time: + click = do_it(client_x, client_y, loc_x, loc_y) + + if click is not None: + self._ele.page.wait.load_start(wait_loading) + return True + + except NoRectError: + by_js = True if by_js is not False: self._ele.run_js('this.click();') diff --git a/DrissionPage/chromium_frame.py b/DrissionPage/chromium_frame.py index bea28ee..92f30bd 100644 --- a/DrissionPage/chromium_frame.py +++ b/DrissionPage/chromium_frame.py @@ -84,7 +84,7 @@ class ChromiumFrame(ChromiumBase): self._reload() try: - self.run_cdp('DOM.describeNode', nodeId=self.ids.node_id) + self.page.run_cdp('DOM.describeNode', nodeId=self.ids.node_id) except Exception: self._reload() # sleep(2) @@ -291,7 +291,7 @@ class ChromiumFrame(ChromiumBase): :return: 运行的结果 """ self._check_ok() - return self.doc_ele.run_js(script, as_expr=as_expr, *args) + return self.doc_ele.run_js(script, *args, as_expr=as_expr) def parent(self, level_or_loc=1): """返回上面某一级父元素,可指定层数或用查询语法定位 @@ -531,7 +531,7 @@ class ChromiumFrameScroll(ChromiumPageScroll): """ ele = loc_or_ele if isinstance(loc_or_ele, ChromiumElement) else self._driver.ele(loc_or_ele) try: - self._driver.page.run_cdp('DOM.scrollIntoViewIfNeeded', nodeId=ele.node_id) + self._driver.page.run_cdp('DOM.scrollIntoViewIfNeeded', nodeId=ele.ids.node_id) except Exception: ele.run_js("this.scrollIntoView();") diff --git a/DrissionPage/common/errors.py b/DrissionPage/common/errors.py index 5f16a79..489346a 100644 --- a/DrissionPage/common/errors.py +++ b/DrissionPage/common/errors.py @@ -38,3 +38,7 @@ class NotElementFoundError(BaseError): class JavaScriptError(BaseError): _info = 'JavaScript运行错误。' + + +class NoRectError(BaseError): + _info = '该元素没有位置及大小。'