Python Selenium:等到元素不再陈旧?

Posted

技术标签:

【中文标题】Python Selenium:等到元素不再陈旧?【英文标题】:Python Selenium: wait until an element is no longer stale? 【发布时间】:2018-04-08 16:32:15 【问题描述】:

我有一种情况,我想等到一个元素不再是 STALE,即直到一个元素连接到 DOM。以下等待选项不起作用:

self.wait.until(EC.visibility_of_element_located((By.ID, "elementID")))
self.wait.until(EC.presence_of_element_located((By.ID, "elementID")))

它的相反等待函数存在,它一直等到一个元素变得陈旧,即:

self.wait.until(EC.staleness_of((By.ID, "elementID")))

但我希望它等到元素不再陈旧,即直到它连接到 DOM。我怎样才能实现这个功能?

编辑:这里有一个解决方案:here 但我正在寻找任何其他更好的方法。

【问题讨论】:

一旦元素为no longer STALE,您的下一步操作/步骤是什么? 我很困惑。 “陈旧”对我来说意味着该元素以前存在但现在消失了。所以,“不再陈旧”对我来说没有任何意义?!我认为它应该按照建议的答案工作(使用presence_of_element_located)。如果没有,则有其他问题。该站点是使用 java 还是其他可以动态更改它的站点?出于测试目的:如果您构建一个静态的极长等待时间(比如 120 秒),它是否有效? @nostradamus 的“不再陈旧”我的意思是该元素现在已连接到 DOM。是的,我使用了 time.sleep() 来使代码工作,但我想在不使用 time.sleep() 函数的情况下实现它。 我希望我的系统更准确地等待一个元素附加到 DOM @DebanjanB。之后我想选择它的文本属性。 您必须识别正在更改/更新元素的代码段,这会导致其陈旧。它很可能特定于您正在查看的页面,因此我们无法为您提供帮助。一个肮脏的解决方案怎么样:try ... except,如果元素陈旧,则捕获错误,等待 1 秒,重复此操作直到成功? 【参考方案1】:

陈旧元素是您存储的元素引用不再有效,因为页面、页面的一部分或可能只是元素被刷新。一个简单的例子

element = driver.find_element_by_id("elementID")
# do something that refreshes the page
element.click()

这里element.click() 将抛出一个过时的元素异常,因为引用是在刷新之前存储的,但是在刷新之后使用(单击)。在这种情况下,该引用不再有效。一旦引用过时,它就永远不会“过时”......该引用永远不能再次使用。解决这个问题的唯一方法是再次存储引用。

注意:您的代码示例不适用于 .staleness_of()。它需要一个 Web 元素引用,而不是定位器。您需要一个现有的引用来等待它过时。见the docs。

现在要解决问题...您需要等待刷新完成并然后获取新的引用

element = driver.find_element_by_id("elementID")
# do something that refreshes the element
self.wait.until(EC.staleness_of(element))
element = self.wait.until(EC.visibility_of_element_located((By.ID, "elementID")))
# do something with element

等待元素变得陈旧等待元素引用丢失,这意味着元素已更改/刷新。一旦我们知道元素发生了变化,我们现在就可以获得对它的新引用。在这种情况下,等待元素变得可见。我们现在有一个新的引用存储在我们的变量中,我们可以在没有过时元素异常的情况下使用它。

【讨论】:

这是对我有用的不那么丑陋的解决方案。【参考方案2】:

由于您想在 WebElement 不再过时后获取 text 属性,因此可以使用以下命令:

wait1 = WebDriverWait(driver, 10)
wait1.until(expected_conditions.text_to_be_present_in_element((By.ID, "elementID"), "expected_text1"))

wait2 = WebDriverWait(driver, 10)
wait2.until(expected_conditions.text_to_be_present_in_element_value((By.ID, "elementID"), "expected_text2"))

【讨论】:

这并没有检查陈旧,OP 也没有提到任何关于等待预期文本的内容。 对于提出的问题,您的回答可能不正确,但它可能会给我一个解决方案! @sangharsh Ahh,这是一个 3 岁的答案,那时我是 Selenium 的新人 :)【参考方案3】:

来自documentation:

陈旧性

class staleness_of(object):
    """ Wait until an element is no longer attached to the DOM.
    element is the element to wait for.
    returns False if the element is still attached to the DOM, true otherwise.
    """
    def __init__(self, element):
        self.element = element

    def __call__(self, ignored):
        try:
            # Calling any method forces a staleness check
            self.element.is_enabled()
            return False
        except StaleElementReferenceException:
            return True

可点击的元素

class element_to_be_clickable(object):
    """ An Expectation for checking an element is visible and enabled such that
    you can click it."""
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        element = visibility_of_element_located(self.locator)(driver)
        if element and element.is_enabled():
            return element
        else:
            return False

如您所见,两者都使用相同的方法 is_enabled() 来执行检查。

【讨论】:

我试过这个功能,但它会引发 StaleElementException。【参考方案4】:
WebDriverWait(browser, waitTime).until(EC.presence_of_element_located(
                (By.XPATH or By.id or w/e you want, " xpath or id name")))

【讨论】:

如问题中所述,此功能无济于事,仍然会引发 StaleElementException。

以上是关于Python Selenium:等到元素不再陈旧?的主要内容,如果未能解决你的问题,请参考以下文章

如何等到 Selenium 中不再存在元素

Python selenium:等到元素可点击 - 不工作

Python Selenium 2 API 并等待 DOM 准备好/元素可见

Selenium WebDriver 如何解决陈旧元素引用异常?

当我尝试使用for循环单击所有链接时,硒显示陈旧错误?

Python,Selenium:'元素不再附加到 DOM'