Python, Selenium 查找具有 class 的元素并等待 class 更改

Python, Selenium find element with class and wait for class change

我有一个动态加载内容的网页,当页面加载时,有一个旋转轮,我已经找到了抓取内容立即加载到页面上的解决方案,但似乎我找不到抓取稍后加载的内容的解决方案dom.

我能想到的是找到那个轮子旋转的特定class的元素,然后等待它改变,一旦改变,就意味着内容加载到dom。

我在 Ubuntu 上使用 SeleniumFirefox webdriver

这是我要监视的class:

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

加载内容后,轮子停止旋转,class 更改为:

<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

在使用上有区别吗

您可以等待 class 值更改。例如:

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方法passes the driver to the method given,所以你可以很容易地做出你自己的预期条件。上面使用匿名 lambda 函数,但您也可以使用闭包或任何接受参数的可调用函数(ExpectedConditions 库只是一组可调用 classes)。这里有一个闭包:

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)

@LucasTierney 的回答是正确的。但是我仍然觉得解决方案可以优化如下:

由于 wheel 可见,因此您需要使用 visibility_of_element_located() 方法而不是 presence_of_element_located() 方法。

节点:

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

无法通过包含单个 class 的 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'))