Selenium Python:循环中间-过时元素错误

Selenium Python:循环中间-过时元素错误,python,loops,selenium,iterator,staleelementreferenceexception,Python,Loops,Selenium,Iterator,Staleelementreferenceexception,因此,我的代码尝试遍历一个链接列表(所有链接的可见文本都是“年度”),然后,在新网页上,在一个年下拉列表中迭代大约20年,并下载每年的数据集。所以有两个循环。我的代码陷入了年份循环——也就是说,对于同一个“年度”,它在2年后得到了一个陈旧的元素错误 我正在开发chrome,这是我代码的相关部分: Links = browser.find_elements_by_link_text("Annual") for link in Links: link.click() time.sle

因此,我的代码尝试遍历一个链接列表(所有链接的可见文本都是“年度”),然后,在新网页上,在一个年下拉列表中迭代大约20年,并下载每年的数据集。所以有两个循环。我的代码陷入了年份循环——也就是说,对于同一个“年度”,它在2年后得到了一个陈旧的元素错误

我正在开发chrome,这是我代码的相关部分:

Links = browser.find_elements_by_link_text("Annual")
for link in Links:
    link.click()
    time.sleep(20)
    browser.switch_to_window(browser.window_handles[-1])
    select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
    options = select.options
    for index in range(0, len(options)):
        select.select_by_index(index)
        time.sleep(10)
        excelbutton = browser.find_element_by_xpath('//a[img[@title="Download as Excel"]]').click()
错误如下: selenium.common.exceptions.StaleElementReferenceException:消息:stale元素引用:元素未附加到页面文档

非常感谢您的帮助!我试着把答案通读一遍,但由于我使用了两个循环,其中一个循环运行了2年,效果很好,所以我无法理解

更新:完整错误消息:

Traceback (most recent call last):
  File "abc", line 56, in <module>
    select.select_by_index(index)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/selenium/webdriver/support/select.py", line 99, in select_by_index
    for opt in self.options:
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/selenium/webdriver/support/select.py", line 47, in options
    return self._el.find_elements(By.TAG_NAME, 'option')
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/selenium/webdriver/remote/webelement.py", line 527, in find_elements
    {"using": by, "value": value})['value']
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/selenium/webdriver/remote/webelement.py", line 493, in _execute
    return self._parent.execute(command, params)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/selenium/webdriver/remote/webdriver.py", line 249, in execute
    self.error_handler.check_response(response)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/selenium/webdriver/remote/errorhandler.py", line 193, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=67.0.3396.99)
  (Driver info: chromedriver=2.40.565386 (45a059dc425e08165f9a10324bd1380cc13ca363),platform=Mac OS X 10.11.6 x86_64)
回溯(最近一次呼叫最后一次):
文件“abc”,第56行,在
选择。按索引选择索引(索引)
文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/selenium/webdriver/support/select.py”,第99行,按索引选择
对于选择加入自选项:
文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/selenium/webdriver/support/select.py”,第47行,在选项中
返回self.\u el.find\u元素(By.TAG\u NAME,“option”)
文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/selenium/webdriver/remote/webelement.py”,第527行,在find_元素中
{“using”:by,“value”:value})[“value']
文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/selenium/webdriver/remote/webelement.py”,第493行,在
返回self.\u parent.execute(命令,参数)
文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/selenium/webdriver/remote/webdriver.py”,执行中第249行
self.error\u handler.check\u响应(响应)
文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site packages/selenium/webdriver/remote/errorhandler.py”,第193行,在check_响应中
引发异常类(消息、屏幕、堆栈跟踪)
selenium.common.exceptions.StaleElementReferenceException:消息:stale元素引用:元素未附加到页面文档
(会话信息:chrome=67.0.3396.99)
(驱动程序信息:chromedriver=2.40.565386(45a059dc425e08165f9a10324bd1380cc13ca363),平台=Mac OS X 10.11.6 x86_64)

更新-1

因为在您的情况下,stale元素位于选择框上,所以您需要像下面这样更改代码

select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
options = select.options
for index in range(0, len(options)):
    select.select_by_index(index)
    time.sleep(10)
    excelbutton = browser.find_element_by_xpath('//a[img[@title="Download as Excel"]]').click()
    select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
    options = select.options
原始答案

单击页面上的链接后,页面可能会重新加载或更改,因此您的元素集合将过时。因此,您需要应用不同的策略来克服相同的问题

Links = browser.find_elements_by_link_text("Annual")
link_count = len(Links)

for link_index in range(0, link_count):
    link = browser.find_elements_by_link_text("Annual")[link_index]

    link.click()
    time.sleep(20)
    browser.switch_to_window(browser.window_handles[-1])
    select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
    options = select.options
    for index in range(0, len(options)):
        select.select_by_index(index)
        time.sleep(10)
        excelbutton = browser.find_element_by_xpath('//a[img[@title="Download as Excel"]]').click()
以上代码假设返回页面时,链接的数量保持不变。也不是说最好的代码是可能的。但这是解决问题的一种方法


另一种解决方法是获取每个链接的
href
,然后导航到它们。当然,这只在您没有基于javascript的链接时才起作用

因为在您的情况下,stale元素位于选择框上,所以您需要像下面这样更改代码

select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
options = select.options
for index in range(0, len(options)):
    select.select_by_index(index)
    time.sleep(10)
    excelbutton = browser.find_element_by_xpath('//a[img[@title="Download as Excel"]]').click()
    select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
    options = select.options
原始答案

单击页面上的链接后,页面可能会重新加载或更改,因此您的元素集合将过时。因此,您需要应用不同的策略来克服相同的问题

Links = browser.find_elements_by_link_text("Annual")
link_count = len(Links)

for link_index in range(0, link_count):
    link = browser.find_elements_by_link_text("Annual")[link_index]

    link.click()
    time.sleep(20)
    browser.switch_to_window(browser.window_handles[-1])
    select = Select(browser.find_element_by_xpath('//select[@name="year"]'))
    options = select.options
    for index in range(0, len(options)):
        select.select_by_index(index)
        time.sleep(10)
        excelbutton = browser.find_element_by_xpath('//a[img[@title="Download as Excel"]]').click()
以上代码假设返回页面时,链接的数量保持不变。也不是说最好的代码是可能的。但这是解决问题的一种方法


另一种解决方法是获取每个链接的
href
,然后导航到它们。当然,这只有在您没有基于javascript的链接时才起作用

什么元素过时了?总体策略是在for循环中重新定位所需的元素。如果DOM被修改了,我是Python和Selenium新手,那么如何识别过时的元素呢?我已经更新了整个错误消息What element is stale?总体策略是在for循环中重新定位所需的元素。如果DOM被修改了,我是Python和Selenium新手,那么如何识别过时的元素呢?我已经更新了整个错误消息谢谢,但我不明白你建议我做什么。将HREF连接到单个链接将非常麻烦,这就是为什么要将其自动化。请查看更新1,您不需要原始答案谢谢,但我不明白您建议我做什么。将HREF连接到单个链接将非常麻烦,这就是为什么要将其自动化的原因。请查看更新1,您不需要原始答案