DriverElement和ShadowRootElement删除timeout属性,DriverPage增加wait属性,页面及下级元素每次查找元素使用同一个wait对象,除非元素查找临时指定与页面timeout属性不一致的值

This commit is contained in:
g1879 2020-12-07 22:57:36 +08:00
parent 0058414a8a
commit 1a0d850cef
4 changed files with 45 additions and 26 deletions

View File

@ -20,9 +20,8 @@ from .common import DrissionElement, str_to_loc, get_available_file_name, transl
class DriverElement(DrissionElement):
"""driver模式的元素对象包装了一个WebElement对象并封装了常用功能"""
def __init__(self, ele: WebElement, page=None, timeout: float = 10):
def __init__(self, ele: WebElement, page=None):
super().__init__(ele, page)
self.timeout = timeout
def __repr__(self):
attrs = [f"{attr}='{self.attrs[attr]}'" for attr in self.attrs]
@ -39,7 +38,7 @@ class DriverElement(DrissionElement):
:param timeout: 超时时间
:return: DriverElement对象
"""
return self.ele(loc_or_str, mode, timeout or self.timeout)
return self.ele(loc_or_str, mode, timeout)
# -----------------共有属性-------------------
@property
@ -235,7 +234,6 @@ class DriverElement(DrissionElement):
if loc_or_str[0] == 'css selector' and loc_or_str[1].lstrip().startswith('>'):
loc_str = f'{self.css_path}{loc_or_str[1]}'
timeout = timeout or self.timeout
loc_or_str = loc_or_str[0], loc_str
return execute_driver_find(self, loc_or_str, mode, timeout)
@ -567,7 +565,7 @@ class DriverElement(DrissionElement):
def execute_driver_find(page_or_ele,
loc: Tuple[str, str],
mode: str = 'single',
timeout: float = 10) -> Union[DriverElement, List[DriverElement], str, None]:
timeout: float = None) -> Union[DriverElement, List[DriverElement], str, None]:
"""执行driver模式元素的查找 \n
页面查找元素及元素查找下级元素皆使用此方法 \n
:param page_or_ele: DriverPage对象或DriverElement对象
@ -588,15 +586,19 @@ def execute_driver_find(page_or_ele,
driver = page_or_ele.driver
try:
wait = WebDriverWait(driver, timeout=timeout)
if timeout and timeout != page.timeout:
wait = WebDriverWait(driver, timeout=timeout)
else:
wait = page.wait
if loc[0] == 'xpath':
return wait.until(ElementsByXpath(page, loc[1], mode, timeout))
else:
if mode == 'single':
return DriverElement(wait.until(ec.presence_of_element_located(loc)), page, timeout)
return DriverElement(wait.until(ec.presence_of_element_located(loc)), page)
elif mode == 'all':
eles = wait.until(ec.presence_of_all_elements_located(loc))
return [DriverElement(ele, page, timeout) for ele in eles]
return [DriverElement(ele, page) for ele in eles]
except TimeoutException:
return [] if mode == 'all' else None
@ -622,8 +624,6 @@ class ElementsByXpath(object):
def __call__(self, ele_or_driver: Union[WebDriver, WebElement]) \
-> Union[str, DriverElement, None, List[str or DriverElement]]:
driver, the_node = ((ele_or_driver, 'document') if isinstance(ele_or_driver, WebDriver)
else (ele_or_driver.parent, ele_or_driver))
def get_nodes(node=None, xpath_txt=None, type_txt='7'):
"""用js通过xpath获取元素、节点或属性
@ -669,12 +669,18 @@ class ElementsByXpath(object):
"""
return driver.execute_script(js, node)
# 把lxml元素对象包装成DriverElement对象并按需要返回第一个或全部
if isinstance(ele_or_driver, WebDriver):
driver, the_node = ele_or_driver, 'document'
else:
driver, the_node = ele_or_driver.parent, ele_or_driver
# 把lxml元素对象包装成DriverElement对象并按需要返回第一个或全部
if self.mode == 'single':
try:
e = get_nodes(the_node, xpath_txt=self.xpath, type_txt='9')
if isinstance(e, WebElement):
return DriverElement(e, self.page, self.timeout)
return DriverElement(e, self.page)
elif isinstance(e, str):
return format_html(e)
else:
@ -685,7 +691,7 @@ class ElementsByXpath(object):
return None
elif self.mode == 'all':
return ([DriverElement(x, self.page, self.timeout) if isinstance(x, WebElement)
return ([DriverElement(x, self.page) if isinstance(x, WebElement)
else format_html(x)
for x in get_nodes(the_node, xpath_txt=self.xpath)
if x != '\n'])

View File

@ -13,6 +13,7 @@ from urllib.parse import quote
from selenium.common.exceptions import NoAlertPresentException
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait
from .common import str_to_loc, get_available_file_name, translate_loc, format_html
from .driver_element import DriverElement, execute_driver_find
@ -24,9 +25,10 @@ class DriverPage(object):
def __init__(self, driver: WebDriver, timeout: float = 10):
"""初始化函数接收一个WebDriver对象用来操作网页"""
self._driver = driver
self.timeout = timeout
self._timeout = timeout
self._url = None
self._url_available = None
self._wait = None
@property
def driver(self) -> WebDriver:
@ -60,6 +62,22 @@ class DriverPage(object):
"""返回网页title"""
return self.driver.title
@property
def timeout(self) -> float:
return self._timeout
@timeout.setter
def timeout(self, second: float) -> None:
self._timeout = second
self._wait = None
@property
def wait(self) -> WebDriverWait:
if self._wait is None:
self._wait = WebDriverWait(self.driver, timeout=self.timeout)
return self._wait
def get_cookies(self, as_dict: bool = False) -> Union[list, dict]:
"""返回当前网站cookies"""
if as_dict:
@ -165,7 +183,7 @@ class DriverPage(object):
# 接收到WebElement对象打包成DriverElement对象返回
elif isinstance(loc_or_ele, WebElement):
return DriverElement(loc_or_ele, self, self.timeout)
return DriverElement(loc_or_ele, self)
# 接收到的类型不正确,抛出异常
else:

View File

@ -10,10 +10,9 @@ from .driver_element import execute_driver_find, DriverElement
class ShadowRootElement(DrissionElement):
def __init__(self, inner_ele: WebElement, parent_ele: DriverElement, timeout: float = 10):
def __init__(self, inner_ele: WebElement, parent_ele: DriverElement):
super().__init__(inner_ele, parent_ele.page)
self.parent_ele = parent_ele
self.timeout = timeout
def __repr__(self):
return f'<ShadowRootElement in {self.parent_ele} >'
@ -29,7 +28,7 @@ class ShadowRootElement(DrissionElement):
:param timeout: 超时时间
:return: DriverElement对象
"""
return self.ele(loc_or_str, mode, timeout or self.timeout)
return self.ele(loc_or_str, mode, timeout)
@property
def tag(self):
@ -107,8 +106,6 @@ class ShadowRootElement(DrissionElement):
else:
raise ValueError('Argument loc_or_str can only be tuple or str.')
timeout = timeout or self.timeout
if loc_or_str[0] == 'css selector':
return execute_driver_find(self, loc_or_str, mode, timeout)
elif loc_or_str[0] == 'text':
@ -192,18 +189,18 @@ class ShadowRootElement(DrissionElement):
if text == txt:
if mode == 'single':
return DriverElement(ele, self.page, self.timeout)
return DriverElement(ele, self.page)
elif mode == 'all':
results.append(DriverElement(ele, self.page, self.timeout))
results.append(DriverElement(ele, self.page))
# 模糊匹配
elif match == 'fuzzy':
if text in txt:
if mode == 'single':
return DriverElement(ele, self.page, self.timeout)
return DriverElement(ele, self.page)
elif mode == 'all':
results.append(DriverElement(ele, self.page, self.timeout))
results.append(DriverElement(ele, self.page))
return None if mode == 'single' else results

View File

@ -1846,7 +1846,6 @@ Parameter Description:
- ele: WebElement- WebElement object
- page: DriverPage- the page object where the element is located
- timeout: float - Find the timeout of the element (it can be set separately each time the element is searched)
@ -2555,7 +2554,6 @@ Parameter Description:
- parent_ele: DriverElement-the element to which the shadow-root is attached
- timeout: float-timeout