mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
适配新版浏览器的的ShadowRoot;在shadow root下查找元素现在可用完全版的定位语句
This commit is contained in:
parent
9e6e2cb264
commit
38ed85edb8
@ -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'<shadow_root>{self.inner_html}</shadow_root>'
|
||||
|
||||
@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
|
||||
|
Loading…
x
Reference in New Issue
Block a user