From 2bb8ca9dfb210236253c62cdb2a9a98c98b7c6d5 Mon Sep 17 00:00:00 2001 From: g1879 Date: Fri, 23 Dec 2022 23:06:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=A1=B5=E9=9D=A2=E6=9F=A5?= =?UTF-8?q?=E6=89=BE=E5=85=83=E7=B4=A0=E9=80=BB=E8=BE=91=EF=BC=9B=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0wait=5Floading=E6=96=B9=E6=B3=95=E5=92=8C=E5=8F=82?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DrissionPage/chromium_base.py | 29 +++++++++++------ DrissionPage/chromium_element.py | 53 +++++++++++++++++++------------ DrissionPage/chromium_element.pyi | 4 ++- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/DrissionPage/chromium_base.py b/DrissionPage/chromium_base.py index f90be65..b66a2f6 100644 --- a/DrissionPage/chromium_base.py +++ b/DrissionPage/chromium_base.py @@ -402,22 +402,31 @@ class ChromiumBase(BasePage): search_result = self._wait_driver.DOM.performSearch(query=loc, includeUserAgentShadowDOM=True) count = search_result['resultCount'] + nodeIds = None end_time = perf_counter() + timeout - while count == 0 and perf_counter() < end_time: + while True: + if count > 0: + count = 1 if single else count + try: + nodeIds = self._wait_driver.DOM.getSearchResults(searchId=search_result['searchId'], + fromIndex=0, toIndex=count) + break + except Exception: + sleep(.01) + + if perf_counter() >= end_time: + break + search_result = self._wait_driver.DOM.performSearch(query=loc, includeUserAgentShadowDOM=True) count = search_result['resultCount'] - if count == 0: + if not nodeIds: return None if single else [] - count = 1 if single else count - nodeIds = self._wait_driver.DOM.getSearchResults(searchId=search_result['searchId'], fromIndex=0, - toIndex=count) - eles = [] - for i in nodeIds['nodeIds']: - eles.append(make_chromium_ele(self, node_id=i)) - - return eles[0] if single else eles + if single: + return make_chromium_ele(self, node_id=nodeIds['nodeIds'][0]) + else: + return [make_chromium_ele(self, node_id=i) for i in nodeIds['nodeIds']] def wait_ele(self, loc_or_ele, timeout=None): """返回用于等待元素到达某个状态的等待器对象 \n diff --git a/DrissionPage/chromium_element.py b/DrissionPage/chromium_element.py index f9dd5af..3f3d32c 100644 --- a/DrissionPage/chromium_element.py +++ b/DrissionPage/chromium_element.py @@ -592,12 +592,13 @@ class ChromiumElement(DrissionElement): else: self.input(('\ue009', 'a', '\ue017'), clear=False) - def click(self, by_js=None, retry=False, timeout=.2): + def click(self, by_js=None, retry=False, timeout=.2, wait_loading=False): """点击元素 \n 如果遇到遮挡,会重新尝试点击直到超时,若都失败就改用js点击 \n :param by_js: 是否用js点击,为True时直接用js点击,为False时重试失败也不会改用js :param retry: 遇到其它元素遮挡时,是否重试 :param timeout: 尝试点击的超时时间,不指定则使用父页面的超时时间,retry为True时才生效 + :param wait_loading: 是否等待页面进入加载状态 :return: 是否点击成功 """ @@ -623,6 +624,8 @@ class ChromiumElement(DrissionElement): click = do_it(client_x, client_y, loc_x, loc_y) if click: + if wait_loading: + self.wait_loading() return True timeout = timeout if timeout is not None else self.page.timeout @@ -631,10 +634,14 @@ class ChromiumElement(DrissionElement): click = do_it(client_x, client_y, loc_x, loc_y) if click is not None: + if wait_loading: + self.wait_loading() return True if by_js is not False: self.run_script('this.click();') + if wait_loading: + self.wait_loading() return True return False @@ -735,6 +742,18 @@ class ChromiumElement(DrissionElement): current_x, current_y = x, y actions.release() + def wait_loading(self, timeout=2): + """阻塞程序,等待页面进入加载状态 \n + :param timeout: 超时时间 + :return: 等待结束时是否进入加载状态 + """ + end_time = perf_counter() + timeout + while perf_counter() < end_time: + if self.page.is_loading: + return True + sleep(.05) + return False + def _get_obj_id(self, node_id=None, backend_id=None): """根据传入node id获取js中的object id \n :param node_id: cdp中的node id @@ -1146,19 +1165,15 @@ def _find_by_xpath(ele, xpath, single, timeout, relative=True): userGesture=True) if single: - if r['result']['subtype'] == 'null': - return None - else: - return make_chromium_ele(ele.page, obj_id=r['result']['objectId']) + return None if r['result']['subtype'] == 'null' else make_chromium_ele(ele.page, obj_id=r['result']['objectId']) + if r['result']['description'] == 'NodeList(0)': + return [] else: - if r['result']['description'] == 'NodeList(0)': - return [] - else: - r = ele.page.driver.Runtime.getProperties(objectId=r['result']['objectId'], ownProperties=True)['result'] - return [make_chromium_ele(ele.page, obj_id=i['value']['objectId']) - if i['value']['type'] == 'object' else i['value']['value'] - for i in r[:-1]] + r = ele.page.driver.Runtime.getProperties(objectId=r['result']['objectId'], ownProperties=True)['result'] + return [make_chromium_ele(ele.page, obj_id=i['value']['objectId']) + if i['value']['type'] == 'object' else i['value']['value'] + for i in r[:-1]] def _find_by_css(ele, selector, single, timeout): @@ -1187,17 +1202,13 @@ def _find_by_css(ele, selector, single, timeout): userGesture=True) if single: - if r['result']['subtype'] == 'null': - return None - else: - return make_chromium_ele(ele.page, obj_id=r['result']['objectId']) + return None if r['result']['subtype'] == 'null' else make_chromium_ele(ele.page, obj_id=r['result']['objectId']) + if r['result']['description'] == 'NodeList(0)': + return [] else: - if r['result']['description'] == 'NodeList(0)': - return [] - else: - r = ele.page.driver.Runtime.getProperties(objectId=r['result']['objectId'], ownProperties=True)['result'] - return [make_chromium_ele(ele.page, obj_id=i['value']['objectId']) for i in r] + r = ele.page.driver.Runtime.getProperties(objectId=r['result']['objectId'], ownProperties=True)['result'] + return [make_chromium_ele(ele.page, obj_id=i['value']['objectId']) for i in r] def make_chromium_ele(page, node_id=None, obj_id=None): diff --git a/DrissionPage/chromium_element.pyi b/DrissionPage/chromium_element.pyi index a0905b5..31969b1 100644 --- a/DrissionPage/chromium_element.pyi +++ b/DrissionPage/chromium_element.pyi @@ -205,7 +205,7 @@ class ChromiumElement(DrissionElement): def clear(self, by_js: bool = ...) -> None: ... - def click(self, by_js: bool = ..., retry: bool = ..., timeout: float = ...) -> bool: ... + def click(self, by_js: bool = ..., retry: bool = ..., timeout: float = ..., wait_loading: bool = ...) -> bool: ... def click_at(self, offset_x: Union[int, str] = ..., offset_y: Union[int, str] = ..., button: str = ...) -> None: ... @@ -224,6 +224,8 @@ class ChromiumElement(DrissionElement): speed: int = ..., shake: bool = ...) -> None: ... + def wait_loading(self, timeout: float = ...) -> bool: ... + def _get_obj_id(self, node_id: str = ..., backend_id: str = ...) -> str: ... def _get_node_id(self, obj_id: str = ..., backend_id: str = ...) -> str: ...