mirror of
https://gitee.com/g1879/DrissionPage.git
synced 2024-12-05 05:28:43 +08:00
增加对shadow-dom支持,初步完成
This commit is contained in:
parent
7186620c97
commit
ca9d2124d9
@ -1,11 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
from html import unescape
|
||||
from re import split as re_SPLIT
|
||||
from typing import Union, Any
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -16,6 +17,9 @@ class ShadowRootElement(DrissionElement):
|
||||
self.timeout = timeout
|
||||
self._driver = inner_ele.parent
|
||||
|
||||
def __repr__(self):
|
||||
return f'<ShadowRootElement in {self.parent_ele} >'
|
||||
|
||||
@property
|
||||
def driver(self):
|
||||
"""返回控制元素的WebDriver对象"""
|
||||
@ -41,18 +45,18 @@ class ShadowRootElement(DrissionElement):
|
||||
loc = 'xpath', f'.{"/.." * (num - 1)}'
|
||||
return self.parent_ele.ele(loc, timeout=0.01, show_errmsg=False)
|
||||
|
||||
# @property
|
||||
# def next(self):
|
||||
# """返回后一个兄弟元素"""
|
||||
# return
|
||||
#
|
||||
# def nexts(self, num: int = 1):
|
||||
# """返回后面第num个兄弟元素 \n
|
||||
# :param num: 后面第几个兄弟元素
|
||||
# :return: DriverElement对象
|
||||
# """
|
||||
# # loc = 'xpath', f'./following-sibling::*[{num}]'
|
||||
# return
|
||||
@property
|
||||
def next(self):
|
||||
"""返回后一个兄弟元素"""
|
||||
return self.nexts()
|
||||
|
||||
def nexts(self, num: int = 1):
|
||||
"""返回后面第num个兄弟元素 \n
|
||||
:param num: 后面第几个兄弟元素
|
||||
:return: DriverElement对象
|
||||
"""
|
||||
loc = 'css selector', f':nth-child({num})'
|
||||
return self.parent_ele.ele(loc)
|
||||
|
||||
def ele(self,
|
||||
loc_or_str: Union[tuple, str],
|
||||
@ -60,33 +64,21 @@ class ShadowRootElement(DrissionElement):
|
||||
timeout: float = None,
|
||||
show_errmsg: bool = False):
|
||||
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:
|
||||
pass
|
||||
else:
|
||||
raise ValueError('Argument loc_or_str can only be tuple or str.')
|
||||
|
||||
if loc_or_str[0] == '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]}'
|
||||
|
||||
raise ValueError('不支持xpath')
|
||||
timeout = timeout or self.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):
|
||||
pass
|
||||
def eles(self,
|
||||
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:
|
||||
"""执行js代码,传入自己为第一个参数 \n
|
||||
@ -107,3 +99,47 @@ class ShadowRootElement(DrissionElement):
|
||||
return True
|
||||
except:
|
||||
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…
Reference in New Issue
Block a user