通过浏览器向后移动时陈旧元素引用异常,即使在刷新后也是如此
Stale Element Reference Exception when moving backwards through browser, even after refresh
我正在尝试制作一个将通过一堆链接的抓取工具,将指南导出为 PDF,并循环浏览父文件夹中的所有指南。它运行正常,但是当我尝试向后退时,它会抛出陈旧的异常,即使我确保刷新代码中的元素或刷新页面也是如此。
from selenium import webdriver
import time, bs4
browser = webdriver.Firefox()
browser.get('MYURL')
loginElem = browser.find_element_by_id('email')
loginElem.send_keys('LOGIN')
pwdElem = browser.find_element_by_id('password')
pwdElem.send_keys('PASSWORD')
pwdElem.submit()
time.sleep(3)
category = browser.find_elements_by_class_name('title')
for i in category:
i.click()
time.sleep(3)
guide = browser.find_elements_by_class_name('cell')
for j in guide:
j.click()
time.sleep(3)
soup = bs4.BeautifulSoup(browser.page_source, features="html.parser")
guidetitle = soup.find_all(id='guide-intro-title')
print(guidetitle)
browser.find_element_by_link_text('Options').click()
time.sleep(0.5)
browser.find_element_by_partial_link_text('Download PDF').click()
browser.find_element_by_id('download').click()
browser.execute_script("window.history.go(-2)")
print("went back")
time.sleep(5)
print("waited")
guide = browser.find_elements_by_class_name('thumb')
print("refreshed elements")
print("made it to outer loop")
如果我都使用脚本将浏览器移回或 driver.back() 方法,就会发生这种情况。我可以看到它返回到子目录,然后等待并刷新元素。但是,似乎无法加载新元素以进入下一个指南。我在 SO 上发现了类似的问题,但有人只是提供了针对该问题量身定制的代码而不是解释,所以我仍然感到困惑。
我也知道使用 waitdriver 但我现在只是使用 sleep 因为我不完全了解 EC 等待条件。无论如何,增加睡眠时间并不能解决这个问题。
Stale Element Reference Exception 由于 DOM 中的元素 UUID 更改而在页面刷新时发生。
如何避免: 始终尝试在交互之前搜索元素。
在您的代码中,您搜索了单元格,找到它们并将它们存储在 guide
中。所以现在,guide
有一个 selenium UUID 列表。但是,你正在循环遍历列表,并且在每次刷新时(我相信当你返回时发生),单元格的 UUID 发生变化,所以你存储的旧的不再附加到 DOM.当尝试与它们交互时,Selenium 无法在 DOM 中找到它们并抛出此异常。
与其按照自己的方式循环 guide
,不如每次都尝试重新查找元素,例如:
guide = browser.find_elements_by_class_name('cell')
for j in range(len(guide)):
browser.find_elements_by_class_name('cell')[j].click()
注意,看起来 category
可能有类似的问题,因此请尝试将此解决方案也应用于 category
。
希望这对您有所帮助。 是一个类似的问题和解决方案。
我正在尝试制作一个将通过一堆链接的抓取工具,将指南导出为 PDF,并循环浏览父文件夹中的所有指南。它运行正常,但是当我尝试向后退时,它会抛出陈旧的异常,即使我确保刷新代码中的元素或刷新页面也是如此。
from selenium import webdriver
import time, bs4
browser = webdriver.Firefox()
browser.get('MYURL')
loginElem = browser.find_element_by_id('email')
loginElem.send_keys('LOGIN')
pwdElem = browser.find_element_by_id('password')
pwdElem.send_keys('PASSWORD')
pwdElem.submit()
time.sleep(3)
category = browser.find_elements_by_class_name('title')
for i in category:
i.click()
time.sleep(3)
guide = browser.find_elements_by_class_name('cell')
for j in guide:
j.click()
time.sleep(3)
soup = bs4.BeautifulSoup(browser.page_source, features="html.parser")
guidetitle = soup.find_all(id='guide-intro-title')
print(guidetitle)
browser.find_element_by_link_text('Options').click()
time.sleep(0.5)
browser.find_element_by_partial_link_text('Download PDF').click()
browser.find_element_by_id('download').click()
browser.execute_script("window.history.go(-2)")
print("went back")
time.sleep(5)
print("waited")
guide = browser.find_elements_by_class_name('thumb')
print("refreshed elements")
print("made it to outer loop")
如果我都使用脚本将浏览器移回或 driver.back() 方法,就会发生这种情况。我可以看到它返回到子目录,然后等待并刷新元素。但是,似乎无法加载新元素以进入下一个指南。我在 SO 上发现了类似的问题,但有人只是提供了针对该问题量身定制的代码而不是解释,所以我仍然感到困惑。
我也知道使用 waitdriver 但我现在只是使用 sleep 因为我不完全了解 EC 等待条件。无论如何,增加睡眠时间并不能解决这个问题。
Stale Element Reference Exception 由于 DOM 中的元素 UUID 更改而在页面刷新时发生。 如何避免: 始终尝试在交互之前搜索元素。
在您的代码中,您搜索了单元格,找到它们并将它们存储在 guide
中。所以现在,guide
有一个 selenium UUID 列表。但是,你正在循环遍历列表,并且在每次刷新时(我相信当你返回时发生),单元格的 UUID 发生变化,所以你存储的旧的不再附加到 DOM.当尝试与它们交互时,Selenium 无法在 DOM 中找到它们并抛出此异常。
与其按照自己的方式循环 guide
,不如每次都尝试重新查找元素,例如:
guide = browser.find_elements_by_class_name('cell')
for j in range(len(guide)):
browser.find_elements_by_class_name('cell')[j].click()
注意,看起来 category
可能有类似的问题,因此请尝试将此解决方案也应用于 category
。
希望这对您有所帮助。