Python Selenium 上的 StaleElementReferenceException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27003423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
StaleElementReferenceException on Python Selenium
提问by bill999
I am getting the following error while using Selenium in python:
在 python 中使用 Selenium 时出现以下错误:
selenium.common.exceptions.StaleElementReferenceException: Message: u'stale element reference: element is not attached to the page document\n
Interestingly enough, the error pops up at different times in the for loop. Sometimes it gets through eg. 4 iterations and other times eg. 7.
有趣的是,错误在 for 循环中的不同时间弹出。有时它会通过例如。4 次迭代和其他时间,例如。7.
Some of the relevant code being run is:
正在运行的一些相关代码是:
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()
What does this error mean and what is something I can try to fix this?
这个错误是什么意思,我可以尝试解决什么问题?
回答by Nima Soroush
Selenium Support Explicitand ImplicitWaits. If you think waiting for certain amount of time is enough for your page to be loaded, use:
硒支持Explicit和Implicit等待。如果您认为等待一定的时间足以加载您的页面,请使用:
driver.implicitly_wait(secs)
but if you want to wait for a special event (e.g. waiting for a particular element to be loaded) you can do something like:
但是如果你想等待一个特殊的事件(例如等待一个特定的元素被加载),你可以这样做:
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)
回答by rajkrish06
When webpage got refreshed or switched back from different window or form and trying to access an element user will get staleelementexception.
当网页刷新或从不同的窗口或表单切换回来并尝试访问元素时,用户将获得 staleelementexception。
Use webdriverwait in try --except block with for loop: EX :
在 try --except 块中使用 webdriverwait for 循环: EX :
Code in which I got staleelementexception :
我得到 staleelementexception 的代码:
driver.find_element_by_id(tc.value).click()
driver.find_element_by_xpath("xpath").click()
driver.find_element_by_xpath("xpath").click()
Fix :
使固定 :
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
回答by Emilio M.
It means the element is no longer in the DOM, or it changed.
这意味着该元素不再在 DOM 中,或者它发生了变化。
The following code will help you find the element by controlling and ignoring StaleElementExceptionsand handling them just like any other NoSuchElementException. It waits for the element to NOT be stale, just like it waits for the element to be present. It also serves as a good example on how to properly wait for conditions in Selenium.
以下代码将通过控制和忽略StaleElementExceptions并像处理任何其他NoSuchElementException一样处理它们来帮助您找到元素。它等待元素不再陈旧,就像它等待元素存在一样。它也是关于如何在 Selenium 中正确等待条件的一个很好的例子。
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
my_element_id = 'something123'
ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
your_element = WebDriverWait(your_driver, some_timeout,ignored_exceptions=ignored_exceptions)\
.until(expected_conditions.presence_of_element_located((By.ID, my_element_id)))
To better understand the problem, imagine you are inside a for loop and think what happens during the iterations:
为了更好地理解这个问题,想象你在一个 for 循环中并思考在迭代过程中会发生什么:
- something changes when you click on the element (last line)
- So the page is changing
- You enter the next iteration. Now are trying to find a new element (your first line inside the loop).
- You found the element
- It finishes changing
- You try to use it by getting an attribute
- Bam! The element is old. You got it in step 4, but it finished changing on step 5
- 单击元素时会发生变化(最后一行)
- 所以页面正在改变
- 您进入下一次迭代。现在正在尝试找到一个新元素(循环内的第一行)。
- 你找到了元素
- 它完成改变
- 您尝试通过获取属性来使用它
- 砰!该元素是旧的。您在第 4 步中得到了它,但它在第 5 步中完成了更改
回答by Rashid
This is the python solution for this problem:
这是这个问题的python解决方案:
def clickAndCatchStaleRefException(locator):
driver = sel2._current_browser()
result = False
attempts = 0
locator = locator[6:]
# This line is optional because sometimes you pass a xpath from a varibles file
# that starts with 'xpath='. This should be omitted otherwise the find_element_by_xpath
# function will throw an error.
# But if you pass an xpath directly you don't need this
while attempts < 2:
try:
driver.find_element_by_xpath(locator).click()
result = True
break
except EC as e:
raise e
finally:
attempts += 1
return result
回答by Vishal
>>>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,e:
print(e)
pass
Note: Python 3+ : replace exceptions.StaleElementReferenceException,e-> exceptions.StaleElementReferenceException as e
注意:Python 3+:将exceptions.StaleElementReferenceException,e-> exceptions.StaleElementReferenceException替换为 e
回答by Jeya Suriya Muthumari
I Would like to add one more solution here which is worked for me.
我想在这里添加一个对我有用的解决方案。
I was trying to access the button in the top menu panel on my webpage after refreshing the content area on the same page, Which gave me the following error,
在刷新同一页面上的内容区域后,我试图访问我网页顶部菜单面板中的按钮,这给了我以下错误,
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
Then I started to search for the solution to click the stale element on the web page. After two days of thinking and googling, I got a solution.
然后我开始搜索解决方法来单击网页上的陈旧元素。经过两天的思考和谷歌搜索,我得到了一个解决方案。
To access the stale element on the page, first, we need to focus the mouse over the particular section and perform click option
要访问页面上的陈旧元素,首先,我们需要将鼠标放在特定部分上并执行单击选项
EditReport1 = driver.find_element_by_id('internalTab1')
ActionChains(driver).move_to_element(EditReport1).click(EditReport1).perform()
move_to_element will move the mouse over the stale element which we need to access once we got our control on the element the click operation is successfully performed.
move_to_element 会将鼠标移动到我们需要访问的陈旧元素上,一旦我们控制了点击操作成功执行的元素。
This is worked for me. If anyone finds it working please comment your's as well which will help some other in future.
这对我有用。如果有人发现它有效,请评论你的,这将在未来帮助其他人。
Thank you
谢谢
回答by n00b
Beyond the answers here, if you are using ActionChains, and the page has changed, be sure to reinstantiate your ActionChains object (dont reuse an old one), otherwise your ActionChain will be using a stale DOM. I.e. do this;
除了这里的答案之外,如果您正在使用 ActionChain,并且页面已更改,请确保重新实例化您的 ActionChains 对象(不要重用旧的),否则您的 ActionChain 将使用陈旧的 DOM。即这样做;
action_chain = ActionChains(driver)
action_chain.double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
Or better yet dont use an instantiation;
或者最好不要使用实例化;
ActionChains(driver).double_click(driver.find_element_by_xpath("//tr[2]/p")).perform()
回答by Eugene Zalivadnyi
In my case, the problem
就我而言,问题
stale element reference: element is not attached to the page document
过时的元素引用:元素未附加到页面文档
was because I tried to use
actions.move_to_element(element).perform()on actionsthat created from oldSelenium tab.
是因为我试图用
actions.move_to_element(element).perform()在行动,从创建的旧硒标签。
So the solution is to create new actions instance after opening new tab:
所以解决方案是在打开新标签后创建新的动作实例:
actions = ActionChains(browser)
actions.move_to_element(element).perform()

