Python, Selenium находят элемент с классом и ждут смены класса - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть веб-страница, которая загружает контент динамически, и пока страница загружается, есть вращающееся колесо, я уже нашел решение, чтобы захватить контент, загруженный сразу на страницу, но, похоже, я не могу найти решение, чтобы захватить контент, загруженный позже в DOM.

Что я могу придумать, так это найти элемент с определенным классом вращения этого колеса и подождать, пока он изменится, как только он изменится, чем это означает, что контент загружен в DOM.

IЯ использую Selenium с Firefox webdriver на Ubuntu.

Вот класс, который я хочу отслеживать:

<div class="wheel spinning"></div>

После загрузки контента вращение колеса останавливаетсяи класс изменяется на:

<div class="wheel"></div>

Любой найдет решение для поиска и отслеживания class="wheel spinning", и как только оно будет изменено на class="wheel", чтобы продолжить захват данных.

Редактировать:

XPATH фактически решил одну часть решения, вот часть кода

try:
    element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//*[@class='wheel']))
)
title = driver.find_element_by_xpath('/html/body/div[1]/div[1]/div[3]')
print(title.text)

Но если элемент не появляется в течение 10 секунд, он выходит из строя, теперь, чтобы найти способ повторить попытку снова и снова, покаэлемент присутствует настр.

Есть ли разница в использовании presence_of_element_located((By.XPATH)) и find_element_by_xpath

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

@ Ответ LucasTierney (+1) был почти идеальным, но я все еще чувствую, что решение можно оптимизировать следующим образом:

Поскольку колесо видно, вместо метода presence_of_element_located() необходимо использовать метод visibility_of_element_located().

Узел:

<div class="wheel spinning"></div>

Невозможно найти через XPath , содержащий один класс, т. Е. Только wheel как в:

el = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, "//*[@class='wheel']")))

Вместо этого вы можете использовать любую из стратегий локатора :

  • cssSelector

    el = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.wheel.spinning")))
    WebDriverWait(driver, 10).until(lambda d: 'spinning' not in el.get_attribute('class'))
    
  • xpath

    el = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH, "//div[@class='wheel spinning']")))
    WebDriverWait(driver, 10).until(lambda d: 'spinning' not in el.get_attribute('class'))
    
0 голосов
/ 10 ноября 2018

Вы можете подождать, пока значение класса не изменится. Например:

from selenium.webdriver.support.ui import WebDriverWait

# Wait longer than 10 seconds since you're getting occasional timeout
el = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, "//*[@class='wheel']")))


wait = WebDriverWait(driver, 10)
wait.until(lambda d: 'spinning' not in el.get_attribute('class'))

Метод until передает драйвер методу, указанному , так что вы можете довольно легко создать собственное ожидаемое условие. Выше используется анонимная лямбда-функция, но вы также можете использовать замыкание или что-нибудь вызываемое в аргументе (библиотека ExpectedConditions - это просто набор вызываемых классов). Вот то же самое с закрытием:

from selenium.webdriver.support.ui import WebDriverWait


# Wait longer than 10 seconds since you're getting occasional timeout
el = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, "//*[@class='wheel']")))

def wait_not_spinning(driver):
    return 'spinning' not in el.get_attribute('class')

wait = WebDriverWait(driver, 10)
wait.until(wait_not_spinning)
...