mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-10 04:00:23 +08:00
增加对shadow-dom支持,初步完成
This commit is contained in:
parent
7186620c97
commit
ca9d2124d9
@ -1,11 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
from html import unescape
|
from html import unescape
|
||||||
|
from re import split as re_SPLIT
|
||||||
from typing import Union, Any
|
from typing import Union, Any
|
||||||
|
|
||||||
from selenium.webdriver.remote.webelement import WebElement
|
from selenium.webdriver.remote.webelement import WebElement
|
||||||
|
|
||||||
from .common import DrissionElement, get_loc_from_str
|
from .common import DrissionElement
|
||||||
from .driver_element import execute_driver_find
|
from .driver_element import execute_driver_find
|
||||||
|
|
||||||
|
|
||||||
@ -16,6 +17,9 @@ class ShadowRootElement(DrissionElement):
|
|||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self._driver = inner_ele.parent
|
self._driver = inner_ele.parent
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<ShadowRootElement in {self.parent_ele} >'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def driver(self):
|
def driver(self):
|
||||||
"""返回控制元素的WebDriver对象"""
|
"""返回控制元素的WebDriver对象"""
|
||||||
@ -41,18 +45,18 @@ class ShadowRootElement(DrissionElement):
|
|||||||
loc = 'xpath', f'.{"/.." * (num - 1)}'
|
loc = 'xpath', f'.{"/.." * (num - 1)}'
|
||||||
return self.parent_ele.ele(loc, timeout=0.01, show_errmsg=False)
|
return self.parent_ele.ele(loc, timeout=0.01, show_errmsg=False)
|
||||||
|
|
||||||
# @property
|
@property
|
||||||
# def next(self):
|
def next(self):
|
||||||
# """返回后一个兄弟元素"""
|
"""返回后一个兄弟元素"""
|
||||||
# return
|
return self.nexts()
|
||||||
#
|
|
||||||
# def nexts(self, num: int = 1):
|
def nexts(self, num: int = 1):
|
||||||
# """返回后面第num个兄弟元素 \n
|
"""返回后面第num个兄弟元素 \n
|
||||||
# :param num: 后面第几个兄弟元素
|
:param num: 后面第几个兄弟元素
|
||||||
# :return: DriverElement对象
|
:return: DriverElement对象
|
||||||
# """
|
"""
|
||||||
# # loc = 'xpath', f'./following-sibling::*[{num}]'
|
loc = 'css selector', f':nth-child({num})'
|
||||||
# return
|
return self.parent_ele.ele(loc)
|
||||||
|
|
||||||
def ele(self,
|
def ele(self,
|
||||||
loc_or_str: Union[tuple, str],
|
loc_or_str: Union[tuple, str],
|
||||||
@ -60,33 +64,21 @@ class ShadowRootElement(DrissionElement):
|
|||||||
timeout: float = None,
|
timeout: float = None,
|
||||||
show_errmsg: bool = False):
|
show_errmsg: bool = False):
|
||||||
if isinstance(loc_or_str, str):
|
if isinstance(loc_or_str, str):
|
||||||
loc_or_str = get_loc_from_str(loc_or_str)
|
loc_or_str = get_css_from_str(loc_or_str)
|
||||||
elif isinstance(loc_or_str, tuple) and len(loc_or_str) == 2:
|
elif isinstance(loc_or_str, tuple) and len(loc_or_str) == 2:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise ValueError('Argument loc_or_str can only be tuple or str.')
|
raise ValueError('Argument loc_or_str can only be tuple or str.')
|
||||||
|
|
||||||
if loc_or_str[0] == 'xpath':
|
if loc_or_str[0] == 'xpath':
|
||||||
# 确保查询语句最前面是.
|
raise ValueError('不支持xpath')
|
||||||
# loc_str = loc_or_str[1] if loc_or_str[1].startswith(('.', '/')) else f'.//{loc_or_str[1]}'
|
|
||||||
# loc_str = loc_str if loc_str.startswith('.') else f'.{loc_str}'
|
|
||||||
loc_str = loc_or_str[1]
|
|
||||||
# print(self.inner_ele)
|
|
||||||
# print(loc_str)
|
|
||||||
js = f'''return document.evaluate('{loc_str}', arguments[0]).iterateNext()''' #
|
|
||||||
print(js)
|
|
||||||
return self.inner_ele.parent.execute_script(js, self.inner_ele)
|
|
||||||
# return self.run_script(js)
|
|
||||||
# else:
|
|
||||||
# if loc_or_str[1].lstrip().startswith('>'):
|
|
||||||
# loc_or_str = loc_or_str[0], f'{self.css_path}{loc_or_str[1]}'
|
|
||||||
|
|
||||||
timeout = timeout or self.timeout
|
timeout = timeout or self.timeout
|
||||||
|
|
||||||
return execute_driver_find(self.inner_ele, loc_or_str, mode, show_errmsg, timeout)
|
return execute_driver_find(self.inner_ele, loc_or_str, mode, show_errmsg, timeout)
|
||||||
|
|
||||||
def eles(self, loc: Union[tuple, str], show_errmsg: bool = True):
|
def eles(self,
|
||||||
pass
|
loc_or_str: Union[tuple, str],
|
||||||
|
timeout: float = None,
|
||||||
|
show_errmsg: bool = False):
|
||||||
|
return self.ele(loc_or_str, mode='all', show_errmsg=show_errmsg, timeout=timeout)
|
||||||
|
|
||||||
def run_script(self, script: str, *args) -> Any:
|
def run_script(self, script: str, *args) -> Any:
|
||||||
"""执行js代码,传入自己为第一个参数 \n
|
"""执行js代码,传入自己为第一个参数 \n
|
||||||
@ -107,3 +99,47 @@ class ShadowRootElement(DrissionElement):
|
|||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_css_from_str(loc: str) -> tuple:
|
||||||
|
"""处理元素查找语句 \n
|
||||||
|
查找方式:属性、tag name及属性、css selector \n
|
||||||
|
=表示精确匹配,:表示模糊匹配,无控制字符串时默认搜索该字符串 \n
|
||||||
|
示例: \n
|
||||||
|
@class:ele_class - class含有ele_class的元素 \n
|
||||||
|
@class=ele_class - class等于ele_class的元素 \n
|
||||||
|
@class - 带class属性的元素 \n
|
||||||
|
tag:div - div元素 \n
|
||||||
|
tag:div@class:ele_class - class含有ele_class的div元素 \n
|
||||||
|
tag:div@class=ele_class - class等于ele_class的div元素 \n
|
||||||
|
css:div.ele_class \n
|
||||||
|
"""
|
||||||
|
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:]}]'
|
||||||
|
elif loc.startswith(('tag=', 'tag:')): # 根据tag name查找
|
||||||
|
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] == 'text()':
|
||||||
|
raise ValueError('不支持按文本查找')
|
||||||
|
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]}]'
|
||||||
|
elif loc.startswith(('css=', 'css:')): # 用css selector查找
|
||||||
|
loc_str = loc[4:]
|
||||||
|
elif loc.startswith(('text=', 'text:')): # 根据文本查找
|
||||||
|
raise ValueError('不支持按文本查找')
|
||||||
|
elif loc.startswith(('xpath=', 'xpath:')): # 用xpath查找
|
||||||
|
raise ValueError('不支持xpath')
|
||||||
|
else:
|
||||||
|
raise ValueError('不支持的查询语句')
|
||||||
|
return 'css selector', loc_str
|
||||||
|
Loading…
x
Reference in New Issue
Block a user