Ecco il mio tentativo di una soluzione completamente generica, in Python:
Innanzitutto, una generica funzione "wait" (usa un WebDriverWait se vuoi, li trovo brutti):
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__))
Successivamente, la soluzione si basa sul fatto che il selenio registra un numero ID (interno) per tutti gli elementi di una pagina, incluso il livello superiore <html>
elemento di . Quando una pagina si aggiorna o si carica, ottiene un nuovo elemento HTML con un nuovo ID.
Quindi, supponendo che si desideri fare clic su un collegamento con il testo "il mio collegamento", ad esempio:
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)
Per ulteriori helper Pythonic, riutilizzabili e generici, puoi creare un gestore di contesto:
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)
E poi puoi usarlo praticamente su qualsiasi interazione di selenio:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
Credo sia a prova di proiettile! Cosa ne pensi?
Maggiori informazioni in un post sul blog qui