在python中使用Selenium时出现以下错误:
selenium.common.exceptions.StaleElementReferenceException: Message: u'stale element reference: element is not attached to the page document\n
有趣的是,错误会在for循环中的不同时间弹出。有时它通过例如。 4次迭代和其他时间,例如。 7。
正在运行的一些相关代码是:
for i in range(0, 22):
u = driver.find_elements_by_id("data")
text = u[0].get_attribute("innerHTML")
driver.find_elements_by_class_name("aclassname")[0].click()
这个错误意味着什么,我可以尝试解决这个问题?
答案 0 :(得分:16)
Selenium支持Explicit
和Implicit
等待。如果您认为等待一定的时间足以加载您的页面,请使用:
driver.implicitly_wait(secs)
但如果您想等待特殊事件(例如等待加载特定元素),您可以执行以下操作:
from selenium.webdriver.support.ui import WebDriverWait
...
...
def find(driver):
element = driver.find_elements_by_id("data")
if element:
return element
else:
return False
element = WebDriverWait(driver, secs).until(find)
答案 1 :(得分:11)
这意味着该元素不再位于DOM中,或者已更改。
你在for循环中。想一想迭代过程中会发生什么:
以下代码可帮助您找到元素:
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
your_element = WebDriverWait(your_driver, some_timeout,ignored_exceptions=ignored_exceptions)\
.until(expected_conditions.presence_of_element_located((By.ID, Your_ID)))
答案 2 :(得分:3)
除了此处的答案以外,如果您使用的是ActionChains,并且页面已更改,请确保重新实例化ActionChains对象(不要重用旧的对象),否则ActionChain将使用陈旧的DOM。即做到这一点;
action_chain = ActionChains(driver)
action_chain.double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
或者更好,但不要使用实例化;
ActionChains(driver).double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
答案 3 :(得分:2)
当网页刷新或从不同窗口或表单切换回来并尝试访问元素时,用户将获得staleelementexception。
在try forexcept块中使用webdriverwait for for循环: EX:
driver.find_element_by_id(tc.value).click()
修复:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver.find_element_by_id(tc.value).click()
for i in range(4):
try:
run_test = WebDriverWait(driver, 120).until( \
EC.presence_of_element_located((By.XPATH, "xpath")))
run_test.click()
break
except StaleElementReferenceException as e:
raise e
答案 4 :(得分:2)
对于我的python脚本,在相当简单的页面上,上述所有解决方案均无效。我在这里找到了最简单的解决方法-> https://www.softwaretestingmaterial.com/stale-element-reference-exception-selenium-webdriver/。点击之前只是刷新。
driver.refresh()
driver.find_element_by_id('normal').click()
注意:我使用的是driver.implicitly_wait(5)
而不是显式等待,但这在两个选项中都可以使用。
答案 5 :(得分:1)
>>>Stale Exceptions can be handled using **StaleElementReferenceException** to continue to execute the for loop.
from selenium.common import exceptions
# and customize your code of for loop as:
for i in range(0, 22):
try:
u = driver.find_elements_by_id("data")
text = u[0].get_attribute("innerHTML")
driver.find_elements_by_class_name("aclassname")[0].click()
except exceptions.StaleElementReferenceException:
pass
答案 6 :(得分:1)
就我而言,问题
陈旧元素参考:元素未附加到页面文档
是因为我尝试使用
actions.move_to_element(element).perform()
在通过旧 Selenium标签创建的操作上。
因此解决方案是在打开新标签后创建新的动作实例:
actions = ActionChains(browser)
actions.move_to_element(element).perform()
答案 7 :(得分:1)
from selenium.webdriver.support.expected_conditions import staleness_of
上面的导入为我节省了一天。
答案 8 :(得分:1)
这取决于您使用的网站。
如果您有一个不会自行更改的网站,请使用 Emilio 的答案。 WebDriverWait(...).until(...) 是网站的正确/最佳解决方案,网站本身不会改变(并且仅通过用户交互):
WebDriverWait(driver, delay, ignored_exceptions=(NoSuchElementException,StaleElementReferenceException)).until(expected_conditions.presence_of_element_located((By.ID, "my_id"))).click()
(有关解释,请参阅 Emilio 的回答)
如果您使用一个站点,该站点会因来自服务器的推送或基于时间或类似的内容而发生变化,那么唯一可行的解决方案是像 Rashids 的回答一样重试。
def retry_func(func, max_tries=MAX_TRIES):
for i in range(max_tries):
try:
return func()
except Exception as e:
if i >= max_tries - 1:
raise e
def click_button_helper(driver, selector, selector_type=By.XPATH, delay=DELAY, ignored_exceptions=IGNORED_EXCEPTIONS):
WebDriverWait(driver, delay, ignored_exceptions=ignored_exceptions).until(
EC.presence_of_element_located((selector_type, selector))).click()
def click_button(driver, selector, selector_type=By.XPATH, delay=DELAY, ignored_exceptions=IGNORED_EXCEPTIONS,
max_tries=MAX_TRIES):
retry_func(lambda: click_button_helper(driver, selector, selector_type, delay, ignored_exceptions), max_tries)
因为,抱歉@Emilio,您的回答没有解决像 Sylvan LE DEUNFF 提到的那样的具体情况。
仍然可能出现以下竞争条件(并且不能通过 WebDriverWait(...).until(...) 解决,但通常通过重试):
答案 9 :(得分:1)
就我而言,一种情况: 我查询了一次元素,并将其分配给一个变量以供重用,
captchaInput = driver.find_element_by_css_selector('input[name="CaptchaCode"]')
然后它冒着StaleElementReferenceException
的风险,用上面的代码再次查询元素有助于消除异常。
答案 10 :(得分:0)
这是解决此问题的python解决方案:
onVerificationCompleted(PhoneAuthCredential cred)
答案 11 :(得分:0)
我想在这里添加一个对我有用的解决方案。
刷新同一页面的内容区域后,我试图访问网页顶部菜单面板中的按钮,这给我带来以下错误,
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <span id="dk1-combobox" class="dk-selected combinationText visibleElements "> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
然后,我开始搜索解决方案以单击网页上的陈旧元素。经过两天的思考和谷歌搜索,我找到了解决方案。
要访问页面上的陈旧元素,首先,我们需要将鼠标放在特定部分上并执行单击选项
EditReport1 = driver.find_element_by_id('internalTab1')
ActionChains(driver).move_to_element(EditReport1).click(EditReport1).perform()
move_to_element将鼠标移到需要访问的陈旧元素上,一旦我们成功控制了元素,就可以完成点击操作。
这对我有用。如果有人发现它可以正常工作,请也评论您的,这将对以后的工作有所帮助。
谢谢