【发布时间】: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 时变得陈旧。
【问题讨论】: