Селен, наличие одного из множества элементов находится?
Построение ответа на вопрос Как дождаться загрузки страницы Selenium для Python? Я пытаюсь создать метод, который позволяет опрашивать присутствие нескольких элементов с использованием ожидаемых условий.
Я получаю сообщение об ошибке "объект bool" не вызывается в строке, содержащей: wait.until(любой (ожидания)).
Мысленный процесс состоял в том, чтобы позволить нескольким путям Xpath быть переданы в качестве ожидаемых условий, затем использовать any(), аналогично этому ответу на основе Java. Пытаясь дождаться одного из двух элементов на странице, используя selenium xpath, проверьте, любое из условий присутствует.
Как правильно использовать any() в этом случае? Или, еще лучше, что нужно сделать, чтобы этот метод работал?
Предположим, что Selenium .get('url') уже был выполнен непосредственно перед вызовом этого метода.
def wait_with_xpath_expectation(self, search_elements, timeout=6, max_attempts=3):
"""
Selenium wait for an element(s) designated by Xpath to become available in the DOM. Useful for javascript AJAXy
loading pages where content may be be rendered dynamically on the client side after page load appears complete.
search_elements may be one Xpath as a string or many as a list. This allows for any of multiple elements on a
page or pages to be determined to have loaded based on expectations.
:param search_elements: string or list (strings converted to lists), Xpath(s)
:param timeout: int, seconds
:param max_attempts: int, time to wait before giving up on page loading
:return: Boolean, True if page has loaded, False if all attempts have failed
"""
# Page is not loaded yet
loaded = False
# Initialize attempt count
attempt = 0
# If only one element has been passed, ensure it is encapsulated by a list
if type(search_elements) is str:
search_elements = [search_elements]
# Begin the polling loop
while attempt < max_attempts:
try:
while loaded is False:
# Create a list of expected elements using list comprehension
expectations = [EC.presence_of_element_located((By.XPATH, element)) for element in search_elements]
# Define wait
wait = WebDriverWait(self.browser, timeout)
# Execute
wait.until(any(expectations))
# Acknowledge load
loaded = True
print("Success: Page loaded based on expectations")
# Exit returning True for load
return loaded
except TimeoutException as e:
# Increment attempts
attempt += 1
# Check again if max attempts has not been exceeded
while attempt < max_attempts:
# Increase timeout by 20%
timeout *= .2
# Try again
continue
# Print an error if max attempts is exceeded
print("Error: Max load with expectations attempts exceeded,", e)
# Exit returning False for load
return loaded
2 ответа
У вас может быть ожидаемый класс условий для ожидания комбинации ожидаемых условий. Вот пример одного.
class wait_for_all(object):
def __init__(self, methods):
self.methods = methods
def __call__(self, driver):
try:
for method in self.methods:
if not method(driver):
return False
return True
except StaleElementReferenceException:
return False
Затем это можно использовать, создав массив ожидаемых условий и проверив их все в одном и том же ожидании. (Примеры строк разделены для ясности.)
methods = []
methods.append(EC.visibility_of_element_located(BY.ID, "idElem1"))
methods.append(EC.visibility_of_element_located(BY.ID, "idElem2"))
method = wait_for_all(methods)
WebDriverWait(driver, 5).until(method)
Это выполнит одну пятисекундную задержку при проверке видимости двух разных элементов.
Я задокументировал это далее в блоге здесь.
Как только я понял, что у Xpath есть возможность объединения, работает следующий метод. Я оставлю этот ответ открытым, если у кого-то еще есть лучший ответ.
def wait_with_xpath_expectation(self, search_elements, timeout=6, max_attempts=3):
"""
Selenium wait for an element designated by Xpath to become available in the DOM. Useful for javascript AJAXy
loading pages where content may be be rendered dynamically on the client side after page load appears complete.
search_elements may be one Xpath as a string or many as a list. This allows for any of multiple elements on a
page or pages to be determined to have loaded based on expectations.
:param search_elements: string or list (strings converted to lists), Xpath(s)
:param timeout: int, seconds
:param max_attempts: int, time to wait before giving up on page loading
:return: Boolean, True if page has loaded, False if all attempts have failed
"""
# Page is not loaded yet
loaded = False
# Initialize attempt count
attempt = 0
# If only one element has been passed, ensure it is encapsulated by a list
if type(search_elements) is str:
search_elements = [search_elements]
# Begin the polling loop
while attempt < max_attempts:
try:
while loaded is False:
# Decompose the list of Xpaths to a union of nodes
node_union = " | ".join(search_elements)
expectation = EC.presence_of_element_located((By.XPATH, node_union))
# Define wait
wait = WebDriverWait(self.browser, timeout)
# Execute
wait.until(expectation)
# Acknowledge load
loaded = True
print("Success: Page loaded based on expectations")
# Exit returning True for load
return loaded
except TimeoutException as e:
# Increment attempts
attempt += 1
# Check again if max attempts has not been exceeded
while attempt < max_attempts:
# Increase timeout by 20%
timeout *= .2
# Try again
continue
# Print an error if max attempts is exceeded
print("Error: Max load with expectations attempts exceeded,", e)
# Exit returning False for load
return loaded