diff --git a/DrissionPage/shadow_root_element.py b/DrissionPage/shadow_root_element.py index 20f0c25..0077819 100644 --- a/DrissionPage/shadow_root_element.py +++ b/DrissionPage/shadow_root_element.py @@ -4,7 +4,6 @@ @Contact : g1879@qq.com @File : shadow_root_element.py """ -from re import split as re_SPLIT from typing import Union, Any, Tuple, List from selenium.webdriver.remote.webelement import WebElement @@ -43,8 +42,13 @@ class ShadowRootElement(BaseElement): @property def html(self) -> str: + return f'{self.inner_html}' + + @property + def inner_html(self) -> str: """返回内部的html文本""" - return self.inner_ele.get_attribute('innerHTML') + shadow_root = WebElement(self.page.driver, self.inner_ele._id) + return shadow_root.get_attribute('innerHTML') def parent(self, level_or_loc: Union[str, int] = 1) -> DriverElement: """返回上面某一级父元素,可指定层数或用查询语法定位 \n @@ -133,21 +137,18 @@ class ShadowRootElement(BaseElement): :param single: True则返回第一个,False则返回全部 :return: DriverElement对象 """ - if isinstance(loc_or_str, str): - loc_or_str = str_to_css_loc(loc_or_str) + # 先转换为sessionElement,再获取所有元素,获取它们的css selector路径,再用路径在页面上执行查找 + eles = make_session_ele(self.html).eles(loc_or_str) - elif isinstance(loc_or_str, tuple) and len(loc_or_str) == 2: - if loc_or_str[0] == 'xpath': - raise ValueError('不支持xpath。') + if not eles: + return None if single else [] + css_paths = [i.css_path[47:] for i in eles] + + if single: + return make_driver_ele(self, f'css:{css_paths[0]}', single, timeout) else: - raise ValueError('loc_or_str参数只能是tuple或str类型。') - - if loc_or_str[0] == 'css selector': - return make_driver_ele(self, loc_or_str, single, timeout) - - elif loc_or_str[0] == 'text': - return self._find_eles_by_text(loc_or_str[1], loc_or_str[2], loc_or_str[3], single) + return [make_driver_ele(self, f'css:{css}', True, timeout) for css in css_paths] def run_script(self, script: str, *args) -> Any: """执行js代码,传入自己为第一个参数 \n @@ -155,7 +156,8 @@ class ShadowRootElement(BaseElement): :param args: 传入的参数 :return: js执行结果 """ - return self.inner_ele.parent.execute_script(script, self.inner_ele, *args) + shadow_root = WebElement(self.page.driver, self.inner_ele._id) + return shadow_root.parent.execute_script(script, shadow_root, *args) def is_enabled(self) -> bool: """是否可用""" @@ -166,6 +168,7 @@ class ShadowRootElement(BaseElement): try: self.is_enabled() return True + except Exception: return False @@ -214,76 +217,3 @@ class ShadowRootElement(BaseElement): results.append(DriverElement(ele, self.page)) return None if single else results - - -def str_to_css_loc(loc: str) -> tuple: - """处理元素查找语句 \n - 查找方式:属性、tag name及属性、文本、css selector \n - @表示属性,.表示class,#表示id,=表示精确匹配,:表示模糊匹配,无控制字符串时默认搜索该字符串 \n - """ - loc_by = 'css selector' - - # .和#替换为class和id查找 - if loc.startswith('.'): - if loc.startswith(('.=', '.:',)): - loc = loc.replace('.', '@class', 1) - else: - loc = loc.replace('.', '@class=', 1) - - elif loc.startswith('#'): - if loc.startswith(('#=', '#:',)): - loc = loc.replace('#', '@id', 1) - else: - loc = loc.replace('#', '@id=', 1) - - elif loc.startswith(('t:', 't=')): - loc = f'tag:{loc[2:]}' - - elif loc.startswith(('tx:', 'tx=')): - loc = f'text{loc[2:]}' - - elif loc.startswith(('x:', 'x=', 'xpath:', 'xpath=')): - raise ValueError('不支持xpath。') - - # 根据属性查找 - if loc.startswith('@'): - r = re_SPLIT(r'([:=])', loc[1:], maxsplit=1) - - if len(r) == 3: - mode = '=' if r[1] == '=' else '*=' - loc_str = f'*[{r[0]}{mode}{r[2]}]' - else: - loc_str = f'*[{loc[1:]}]' - - # 根据tag name查找 - elif loc.startswith(('tag=', 'tag:')): - if '@' not in loc[4:]: - loc_str = f'{loc[4:]}' - - else: - at_lst = loc[4:].split('@', maxsplit=1) - r = re_SPLIT(r'([:=])', at_lst[1], maxsplit=1) - - if len(r) == 3: - if r[0] in ('text()', 'tx()'): - match = 'exact' if r[1] == '=' else 'fuzzy' - return 'text', r[2], at_lst[0], match - mode = '=' if r[1] == '=' else '*=' - loc_str = f'{at_lst[0]}[{r[0]}{mode}"{r[2]}"]' - else: - loc_str = f'{at_lst[0]}[{r[0]}]' - - # 用css selector查找 - elif loc.startswith(('css=', 'css:')): - loc_str = loc[4:] - - # 根据文本查找 - elif loc.startswith(('text=', 'text:')): - match = 'exact' if loc[4] == '=' else 'fuzzy' - return 'text', loc[5:], '', match - - # 根据文本模糊查找 - else: - return 'text', loc, '', 'fuzzy' - - return loc_by, loc_str