我陷入了编写Python Selenium脚本的困境,似乎无法令人满意地解决我得到的这个StaleElementReferenceException。
我已加载页面并点击一个按钮,打开一个表单,允许用户在订单中添加新的信用卡。此时,我执行WebDriverWait暂停脚本,直到此窗体上的“保存”按钮变为可见。此时,重新创建页面对象,因为它已更改,我的目的是填充字段并保存卡片。
问题是刷新页面对象后脚本失败并出现StaleElementReferenceException。我的理解是WebDriverWait将暂停执行,使页面有时间加载需要加载的所有元素,但这似乎并没有发生。相反,页面对象的刷新中的某些东西是陈旧的并导致错误(每次创建对象的不同部分)。
如果我只是取消注释'time.sleep(2)'行,那么这个脚本运行正常,它将通过。所以我知道我只需要在刷新对象之前给页面时间重新加载。 WebDriverWait似乎对我没那么有效。
如果没有睡眠命令,是否有更正确的方法可以做到这一点?
checkout = CheckoutProcess(self.driver)
# Add Credit Card
checkout.add_credit_card()
# Wait for form to display
WebDriverWait(self.driver,30).until(
expected_conditions.presence_of_element_located((By.CLASS_NAME, 'total')))
# time.sleep(2)
# Refresh the page object so form can be filled in
checkout = CheckoutProcess(self.driver) # Script Fails Here
checkout.populate_credit_card_data(
credit_card_name, credit_card_number,
credit_card_expiration_date, credit_card_cvc)
checkout.click_credit_card_save_button()
答案 0 :(得分:3)
当您正在交互的元素被销毁然后重新创建时,抛出StaleElementReferenceException。如今,大多数复杂的网页都会在用户与之交互时动态移动,这需要销毁和重新创建DOM中的元素。
尝试
wait.until(ExpectedConditions.stalenessOf(whatever element));
或
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("whatever elemnt")))
希望它能帮到你
答案 1 :(得分:1)
我遇到了同样的问题并通过实现这个在捕获到异常时重试的包装器来解决它:
from selenium.common.exceptions import StaleElementReferenceException
def _loop_is_text_present(text, max_attempts=3):
attempt = 1
while True:
try:
return self.browser.is_text_present(text)
except StaleElementReferenceException:
if attempt == max_attempts:
raise
attempt += 1
灵感来自:http://darrellgrainger.blogspot.com/2012/06/staleelementexception.html
答案 2 :(得分:1)
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import StaleElementReferenceException
def objectIdentificationUsingWaits(self, maxTimeOut, locatorProperties, locatorType = "xpath"):
element = None
try:
WebDriverWait(self.driver, maxTimeOut, ignored_exceptions=[StaleElementReferenceException]).until(
EC.presence_of_element_located((self.getLocatorType(locatorType), locatorProperties)))
element = self.driver.find_element(locatorType, locatorProperties)
except:
print("Exception occurred during object identification.")
return element