StaleElementReferenceException:消息:过时的元素引用:元素未附加到使用 Selenium 和 Python 的页面文档 [英] StaleElementReferenceException: Message: stale element reference: element is not attached to the page document with Selenium and Python

查看:118
本文介绍了StaleElementReferenceException:消息:过时的元素引用:元素未附加到使用 Selenium 和 Python 的页面文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为一个包含下拉菜单的网站开发 selenium.

首先,我们有基本的代码:

from selenium import webdriver从 selenium.webdriver.chrome.options 导入选项从 selenium.webdriver.support.ui 导入选择选项 = 选项()browser = webdriver.Chrome(chrome_options= options,executable_path=r'C:Users...chromedriver.exe')browser.get('http://.../')

然后我正在实施该部分以处理下拉列表.我的目标是为每个下拉选项执行一些操作.

当我在做:

dropdown = Select(browser.find_element_by_name('DropDownList'))选项 = dropdown.options对于范围 (0, len(options) - 1) 中的索引:dropdown.select_by_index(index)#browser.refresh()打印(索引)

它工作得很好.

但是,当我为每个下拉选项执行一些操作时:

dropdown = Select(browser.find_element_by_name('DropDownList'))选项 = dropdown.options对于范围 (0, len(options) - 1) 中的索引:dropdown.select_by_index(index)浏览器刷新()打印(索引)

然后只有第一个下拉选项运行,然后显示错误:

<预><代码>0---------------------------------------------------------------------------StaleElementReferenceException Traceback(最近一次调用最后一次)<ipython-input-31-fa7ad153fc9f>在<模块>56 范围内的索引 (0, len(options) - 1):---->7 dropdown.select_by_index(index)8 browser.refresh()9 打印(索引)~anaconda3libsite-packagesseleniumwebdriversupportselect.py in select_by_index(self, index)第97话98匹配= str(索引)--->99 选择加入 self.options:100 如果 opt.get_attribute(index") == 匹配:第101话~anaconda3libsite-packagesseleniumwebdriversupportselect.py in options(self)45 个定义选项(自己):46 """返回属于这个选择标签的所有选项的列表"""--->47 return self._el.find_elements(By.TAG_NAME, 'option')48第49话~anaconda3libsite-packagesseleniumwebdriver emotewebelement.py in find_elements(self, by, value)683第684回-->第685话686第687话~anaconda3libsite-packagesseleniumwebdriver emotewebelement.py in _execute(self, command, params)631 参数 = {}第632话-->633返回self._parent.execute(命令,参数)634635 def find_element(self, by=By.ID, value=None):~anaconda3libsite-packagesseleniumwebdriver emotewebdriver.py in execute(self, driver_command, params)319响应= self.command_executor.execute(驱动程序命令,参数)320 如果响应:-->第321话322 响应['值'] = self._unwrap_value(第323话~anaconda3libsite-packagesseleniumwebdriver emoteerrorhandler.py in check_response(self, response)第 240 章241 引发异常类(消息,屏幕,堆栈跟踪,警报文本)-->242引发异常类(消息,屏幕,堆栈跟踪)243244 def_value_or_default(self,obj,key,default):StaleElementReferenceException:消息:过时的元素引用:元素未附加到页面文档(会话信息:chrome=83.0.4103.116)

谁能帮我解决这个问题?谢谢

解决方案

此错误信息...

StaleElementReferenceException: 消息: 的元素引用陈旧;元素不再附加到 DOM,不在当前框架上下文中,或者文档已刷新

...表示元素的前一个引用现在 stale 并且前一个元素引用不再存在于网页的 DOM TREE 中.

此异常背后的常见原因可能是以下任一原因:

  • 该元素已更改其在 HTML DOM 中的位置.
  • 该元素不再附加到 DOM TREE.
  • 该元素所在的网页已刷新.
  • 元素的前一个实例已被 JavaScript 刷新.

这个用例

有关相关 HTML 的更多细节将有助于我们构建更规范的答案.但是,根据您的第一个代码块:

dropdown = Select(browser.find_element_by_name('DropDownList'))选项 = dropdown.options对于范围 (0, len(options) - 1) 中的索引:dropdown.select_by_index(index)打印(索引)

似乎选择 元素不会导致 DOM 树.

但是在您的第二个代码块中:

dropdown = Select(browser.find_element_by_name('DropDownList'))选项 = dropdown.options对于范围 (0, len(options) - 1) 中的索引:dropdown.select_by_index(index)浏览器刷新()打印(索引)

当您在 print(index) 之前调用 browser.refresh() 时,HTML DOM 被刷新,旧引用变得陈旧.

因此,当您尝试 print(index) WebDriver 抱怨 StaleElementReferenceException


解决方案

print(index) 之前不需要 browser.refresh() 行.删除行 browser.refresh() 将解决您的问题.


参考

您可以在以下位置找到一些相关的详细讨论:

I am working on selenium for a website that consists of dropdown menu.

At first, we have the basic codes:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import Select

options = Options()
browser = webdriver.Chrome(chrome_options= options,executable_path=r'C:Users...chromedriver.exe')
browser.get('http://.../')

Then I am implementing the part to work on the dropdown. My goal is to perform something for each dropdown option.

When I am doing:

dropdown = Select(browser.find_element_by_name('DropDownList'))

options = dropdown.options

for index in range(0, len(options) - 1):
    dropdown.select_by_index(index)
    #browser.refresh()
    print(index)
   

It is working just fine.

However, when I am performing some stuff for each dropdown option:

dropdown = Select(browser.find_element_by_name('DropDownList'))

options = dropdown.options

for index in range(0, len(options) - 1):
    dropdown.select_by_index(index)
    browser.refresh()
    print(index)
   

Then only the first dropdown option runs and then it shows error:

0
---------------------------------------------------------------------------
StaleElementReferenceException            Traceback (most recent call last)
<ipython-input-31-fa7ad153fc9f> in <module>
      5 
      6 for index in range(0, len(options) - 1):
----> 7     dropdown.select_by_index(index)
      8     browser.refresh()
      9     print(index)

~anaconda3libsite-packagesseleniumwebdriversupportselect.py in select_by_index(self, index)
     97            """
     98         match = str(index)
---> 99         for opt in self.options:
    100             if opt.get_attribute("index") == match:
    101                 self._setSelected(opt)

~anaconda3libsite-packagesseleniumwebdriversupportselect.py in options(self)
     45     def options(self):
     46         """Returns a list of all options belonging to this select tag"""
---> 47         return self._el.find_elements(By.TAG_NAME, 'option')
     48 
     49     @property

~anaconda3libsite-packagesseleniumwebdriver
emotewebelement.py in find_elements(self, by, value)
    683 
    684         return self._execute(Command.FIND_CHILD_ELEMENTS,
--> 685                              {"using": by, "value": value})['value']
    686 
    687     def __hash__(self):

~anaconda3libsite-packagesseleniumwebdriver
emotewebelement.py in _execute(self, command, params)
    631             params = {}
    632         params['id'] = self._id
--> 633         return self._parent.execute(command, params)
    634 
    635     def find_element(self, by=By.ID, value=None):

~anaconda3libsite-packagesseleniumwebdriver
emotewebdriver.py in execute(self, driver_command, params)
    319         response = self.command_executor.execute(driver_command, params)
    320         if response:
--> 321             self.error_handler.check_response(response)
    322             response['value'] = self._unwrap_value(
    323                 response.get('value', None))

~anaconda3libsite-packagesseleniumwebdriver
emoteerrorhandler.py in check_response(self, response)
    240                 alert_text = value['alert'].get('text')
    241             raise exception_class(message, screen, stacktrace, alert_text)
--> 242         raise exception_class(message, screen, stacktrace)
    243 
    244     def _value_or_default(self, obj, key, default):

StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=83.0.4103.116)

Can anyone help me solve this issue? Thanks

解决方案

This error message...

StaleElementReferenceException: Message: The element reference of <span class="pagnCur"> 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

...implies that the previous reference of the element is now stale and the previous element reference is no longer present within the DOM TREE of the webpage.

The common reasons behind this this exception can be either of the following:

  • The element have changed it's position within the HTML DOM.
  • The element is no longer attached to the DOM TREE.
  • The webpage on which the element was part of has been refreshed.
  • The previous instance of element has been refreshed by a JavaScript.

This usecase

A bit of more details interms of the relevant HTML would have helped us to construct a more canonical answer. However, as per your first code block:

dropdown = Select(browser.find_element_by_name('DropDownList'))
options = dropdown.options
for index in range(0, len(options) - 1):
    dropdown.select_by_index(index)
    print(index)
    

It seems selecting the <option> elements doesn't result in any changes with in the DOM Tree.

But in your second code block:

dropdown = Select(browser.find_element_by_name('DropDownList'))
options = dropdown.options
for index in range(0, len(options) - 1):
    dropdown.select_by_index(index)
    browser.refresh()
    print(index)
    

As you are invoking browser.refresh() before print(index) all the elements within the HTML DOM gets refreshed and the olden references becomes stale.

Hence when you try to print(index) WebDriver complains of StaleElementReferenceException


Solution

You don't need the browser.refresh() line before print(index). Removing the line browser.refresh() will solve your issue.


Reference

You can find a couple of relevant detailed discussion in:

这篇关于StaleElementReferenceException:消息:过时的元素引用:元素未附加到使用 Selenium 和 Python 的页面文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆