Как дождаться с помощью Python полной загрузки страницы?
Есть список урлов, которые нужно обойти и собрать нужные элементы. Но иногда при проходе по этим урлам, некоторые из них как-будто не загружаются полностью и программа переходит к следующему урлу. Соответственно, нужные элементы не находятся, но они точно есть. Программа всегда по разному выполняется, иногда все ссылки открываются как надо, иногда рандомно с какой-то из них происходит такая ситуация. Подскажите, пожалуйста, как добавить обязательное условие, проверяющее загрузилась ли полностью страница перед поиском нужного элемента?
Например код:
from selenium import webdriver
from bs4 import BeautifulSoup
driver = webdriver.Chrome(executable_path='C:\\..\chromedriver.exe')
url = ['http://www.yandex.ru/', 'https://www.google.com/']
for i in url:
driver.get(i)
time.sleep(2)
html = driver.find_element_by_xpath("//div[@id='content-all']").get_attribute("innerHTML")
Ответы (1 шт):
1. Задавайте явное ожидание элемента, например:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome(executable_path='C:\\..\chromedriver.exe')
driver.get('https://ya.ru')
timeout = 5
try:
# Вместо body возможно нужен другой тег указывать, характерный для сайта
element_present = EC.presence_of_element_located((By.TAG_NAME, 'body'))
WebDriverWait(driver, timeout).until(element_present)
except TimeoutException:
print("Timed out waiting for page to load")
Можно разные условия ожидания элемента ставить (например, visibility_of_element_located), смотрите в expected_conditions as EC и разные способы поиска, например по атрибуту id, смотрите в By:
element_present = EC.presence_of_element_located((By.ID, 'element_id'))
2. Можно задавать через set_page_load_timeout
from selenium import webdriver
driver = webdriver.Chrome(executable_path='C:\\..\chromedriver.exe')
driver.set_page_load_timeout(0.1) # 100 ms явно не хватит :)
driver.get("https://www.google.com/maps")
3. Специфичный способ через проверку в js (источник) проверяя значение в document.readyState.
Но это сгодится когда используется подзагрузка данных, например через ajax.
Думаю, будет примерно так:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome(executable_path='C:\\..\chromedriver.exe')
driver.get(...)
timeout = 5
# Выполнение действий, затрагивающих подзагрузку, которая поменяет структуру страницы
# Например, пролистывание страницы
# driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
try:
WebDriverWait(driver, timeout).until(
lambda driver: driver.execute_script('return document.readyState') == 'complete'
)
except TimeoutException:
print("Timed out waiting for page to load")