Все эти решения подходят для конкретных случаев, но они страдают по крайней мере от одной из пары возможных проблем:
Они не достаточно универсальны - они хотят, чтобы вы знали заранее, что для страницы, на которую вы переходите, будет выполнено какое-то конкретное условие (например, будет отображаться какой-то элемент)
Они открыты для состояния гонки, когда вы используете элемент, который фактически присутствует на старой и новой страницах.
Вот моя попытка общего решения, которое позволяет избежать этой проблемы (в Python):
Во-первых, общая функция ожидания (используйте WebDriverWait, если хотите, я нахожу их безобразными):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
Далее, решение основано на том факте, что селен записывает (внутренний) id-номер для всех элементов на странице, включая элемент <html>
верхнего уровня. Когда страница обновляется или загружается, она получает новый HTML-элемент с новым идентификатором.
Итак, если вы хотите нажать на ссылку с текстом «моя ссылка», например:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
Для большего Pythonic, многоразового, универсального помощника, вы можете сделать контекстный менеджер:
from contextlib import contextmanager
@contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
И затем вы можете использовать его практически для любого взаимодействия с селеном:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
Я считаю, что это пуленепробиваемый! Как вы думаете?
Подробнее об этом можно прочитать в блоге здесь