元素增加css_path和xpath属性;修复selenium导致的DriverElement不能获取直接子元素的问题

This commit is contained in:
g1879 2020-08-12 00:11:52 +08:00
parent 16755abad6
commit 45756a64b3
3 changed files with 87 additions and 22 deletions

View File

@ -19,7 +19,6 @@ class DrissionElement(object):
def __init__(self, ele: Union[Element, WebElement]):
self._inner_ele = ele
self._xpath = None
@property
def inner_ele(self) -> Union[WebElement, Element]:
@ -54,26 +53,12 @@ class DrissionElement(object):
return
@property
def xpath(self):
self._xpath = self._xpath or self._get_xpath()
return self._xpath
def css_path(self):
return
def _get_xpath(self):
"""获取当前元素xpath字符串"""
xpath_str = ''
ele = self
while ele:
ele_id = ele.attr('id')
if ele_id:
return f'//{ele.tag}[@id="{ele_id}"]{xpath_str}'
else:
if 'SessionElement' in str(type(self)):
brothers = len(ele.eles(f'xpath:./preceding-sibling::{ele.tag}'))
else:
brothers = len(ele.eles(f'xpath:./preceding-sibling::{ele.tag}', timeout=0.001))
xpath_str = f'/{ele.tag}[{brothers + 1}]{xpath_str}' if brothers > 0 else f'/{ele.tag}{xpath_str}'
ele = ele.parent
return xpath_str
@property
def xpath(self):
return
@abstractmethod
def ele(self, loc: Union[tuple, str], mode: str = None, show_errmsg: bool = True):

View File

@ -71,6 +71,58 @@ class DriverElement(DrissionElement):
"""返回元素类型"""
return self._inner_ele.tag_name
@property
def css_path(self) -> str:
js = '''
function e(el) {
if (!(el instanceof Element)) return;
var path = '';
while (el.nodeType === Node.ELEMENT_NODE) {
if (el.id) {
return '#' + el.id + path;
} else {
var sib = el, nth = 0;
while (sib) {
if(sib.nodeType === Node.ELEMENT_NODE){nth += 1;}
sib = sib.previousSibling;
}
path = '>' + ":nth-child(" + nth + ")" + path;
}
el = el.parentNode;
}
return path.substr(1);
}
return e(arguments[0]);
'''
return self.run_script(js)
@property
def xpath(self) -> str:
js = '''
function e(el) {
if (!(el instanceof Element)) return;
var path = '';
while (el.nodeType === Node.ELEMENT_NODE) {
var tag = el.nodeName.toLowerCase();
if (el.id) {
return '//' + tag + '[@id="' + el.id + '"]' + path;
} else {
var sib = el, nth = 0;
while (sib) {
if(sib.nodeType === Node.ELEMENT_NODE && sib.nodeName.toLowerCase()==tag){nth += 1;}
sib = sib.previousSibling;
}
if(nth>1){path = '/' + tag + '[' + nth + ']' + path;}
else{path = '/' + tag + path;}
}
el = el.parentNode;
}
return path;
}
return e(arguments[0]);
'''
return self.run_script(js)
@property
def parent(self):
"""返回父级元素"""
@ -165,7 +217,7 @@ class DriverElement(DrissionElement):
loc_or_str = loc_or_str[0], loc_str
else:
if loc_or_str[1].lstrip().startswith('>'):
raise ValueError('WebElement does not support getting direct child elements.')
loc_or_str = loc_or_str[0], f'{self.css_path}{loc_or_str[1]}'
timeout = timeout or self.timeout
return execute_driver_find(self.inner_ele, loc_or_str, mode, show_errmsg, timeout)
@ -174,7 +226,7 @@ class DriverElement(DrissionElement):
loc_or_str: Union[tuple, str],
timeout: float = None,
show_errmsg: bool = False) -> list:
"""返回当前元素下级所有符合条件的子元素 \n
"""返回当前元素下级所有符合条件的子元素 \n
示例 \n
- 用loc元组查找 \n
ele.eles((By.CLASS_NAME, 'ele_class')) - 返回所有class为ele_class的子元素 \n

View File

@ -48,6 +48,34 @@ class SessionElement(DrissionElement):
"""返回元素类型"""
return self._inner_ele.tag
@property
def css_path(self) -> str:
"""返回css path路径"""
return self._get_ele_path('css')
@property
def xpath(self) -> str:
"""返回xpath路径"""
return self._get_ele_path('xpath')
def _get_ele_path(self, mode):
"""获取css路径或xpath路径"""
path_str = ''
ele = self
while ele:
ele_id = ele.attr('id')
if ele_id:
return f'#{ele_id}{path_str}' if mode == 'css' else f'//{ele.tag}[@id="{ele_id}"]{path_str}'
else:
if mode == 'css':
brothers = len(ele.eles(f'xpath:./preceding-sibling::*'))
path_str = f'>:nth-child({brothers + 1}){path_str}'
else:
brothers = len(ele.eles(f'xpath:./preceding-sibling::{ele.tag}'))
path_str = f'/{ele.tag}[{brothers + 1}]{path_str}' if brothers > 0 else f'/{ele.tag}{path_str}'
ele = ele.parent
return path_str[1:] if mode == 'css' else path_str
@property
def parent(self):
"""返回父级元素"""