【问题标题】:StaleElementReferenceException Selenium PythonStaleElementReferenceException Selenium Python
【发布时间】:2021-04-02 23:48:32
【问题描述】:

好的,伙计们...我知道这个问题似乎已经得到了解答,但我尝试了几种解决方案,但都没有奏效。如果我再看到StaleElementReferenceException 一次,我就会失去它。我妻子的男朋友在嘲笑我,请帮忙。

编辑:删除了一些代码,因为我认为它不再相关以压缩这篇文章。

更新:根据下面的@vitaliis 建议,我将代码更改为:

        while True:
            xpath_atc = '//div[@class="fulfillment-add-to-cart-button"]'

            try:
                wait = WebDriverWait(self.driver, 60)
                wait.until(EC.visibility_of_all_elements_located((By.XPATH, xpath_atc)))
            except TimeoutException:
                print(f'A timeout occured after 60s. Refreshing page and trying again...')
                self.driver.refresh()
                continue
                
            element_arr = self.driver.find_elements_by_xpath(xpath_atc)
            for i in range(len(element_arr)):
                wait.until(EC.visibility_of(element_arr[i]))
                if element_arr[i].text == 'Add to Cart':
                    element_arr[i].click()
                    return

            time.sleep(30)
            self.driver.refresh()

现在,这段代码似乎是迄今为止我尝试过的最有效的代码,因为它产生less StaleElementReferenceExceptions 但它仍然确实产生它们。 ..

我真的很困惑,它不一致,有时会发生异常,有时不会。对此问题的任何其他想法将不胜感激。

解决方案: tldr;这行得通

element = self.driver.find_element_by_xpath(xpath)
while(EC.staleness_of(disc_ele).__call__(False)):
    element = self.driver.find_element_by_xpath(xpath)
text = element.text

如果有人对为什么有兴趣,我会给出我最好的猜测。 staleness_of 类定义如下:

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

当与WebDriverWait 类一起使用时,即WebDriverWait(driver, timeout).until(EC.staleness_of(element)),我们正在等待元素过时,这就是我们正在寻找的对吗?好吧,由于过时异常的不一致,元素可能不是过时的,如果它不是过时的,那么我们会得到一个超时异常,这不是我们想要的结果。

幸运的是,staleness_of 类有一个方法__call__(),如果元素过时返回 true,否则返回 false。因此,使用while 循环,我们可以通过每次迭代更新元素并在更新后的元素上使用__call__() 方法检查是否过时来不断检查元素是否过时。最终,更新后的元素不会过时,__call__() 方法将返回 false 退出循环。

编辑: 哎呀,不起作用。我猜有一种情况,元素在 while 循环条件时不是陈旧的,但在调用 .text 时变得陈旧。

【问题讨论】:

    标签: python selenium


    【解决方案1】:

    您的定位器是独一无二的吗?尝试等到您的元素可点击:

    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    
    wait = WebDriverWait(driver, 20)
    wait.until(EC.element_to_be_clickable(
                    (By.XPATH, '//div[@class="fulfillment-add-to-cart-button"]')))
    button = driver.find_element_by_xpath('//div[@class="fulfillment-add-to-cart-button"]')
    button.click()
    

    如果有许多元素具有相同的定位符,请尝试使用visibility_of_all_elements_located 而不是element_to_be_clickable

    我可以建议以下算法:

    1. 等待页面加载
    2. 使用find_elements_by_xpath 查找具有相同定位符的所有元素
    3. 在循环中一一单击它们。但添加直到它们可点击(循环)

    【讨论】:

    • 感谢您的建议,定位器是 2 个元素对象的列表
    • 传奇,visibility_of_all_elements_located 工作。没看到这个方法,非常感谢
    • 如果你有时间,你介意检查我的更新吗@vitaliis
    • 也许,稍后。但是我建议你问一个不同的问题,因为它现在完全不同了。阿洛斯,更多的人会关注它。并像以前一样编辑这个。
    • 好吧,这与获得异常的问题相同,我仍然会继续发布另一个问题
    猜你喜欢
    • 2018-09-14
    • 2014-11-15
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 2016-04-28
    相关资源
    最近更新 更多