繁体   English   中英

StaleElementReferenceException Selenium Python

[英]StaleElementReferenceException Selenium Python

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

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

更新:根据下面的@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()

现在,这段代码似乎是迄今为止我尝试过的最有效的代码,因为它产生的StaleElementReferenceException较少,但它仍然产生它们......

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

解决方案: 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的 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 class 结合使用时,即WebDriverWait(driver, timeout).until(EC.staleness_of(element))我们正在等待元素过时,这就是我们正在寻找的对吗? 好吧,由于陈旧异常的不一致,元素可能不是陈旧的,如果它不是陈旧的,那么我们将得到一个超时异常,这不是我们想要的结果。

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

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

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

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. 在一个循环中,一个一个地单击它们。 但是添加直到它们可以点击(循环)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM