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

View File

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

View File

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

View File

@ -1846,7 +1846,6 @@ Parameter Description:
- ele: WebElement- WebElement object - ele: WebElement- WebElement object
- page: DriverPage- the page object where the element is located - 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 - parent_ele: DriverElement-the element to which the shadow-root is attached
- timeout: float-timeout