【发布时间】:2021-08-07 12:16:58
【问题描述】:
我正在使用 Python3.9+Selenium 编写一个为我填写在线表单的小脚本。
一些上下文:该网页包含一个字段 (locationField),需要输入街道地址,并且位于某种“谷歌地图包装器”之上。
在字段中键入时,它会使用兼容的完整地址加载一个元素(locationField_sugg)的下拉列表,以及选择此选项时,将映射放大到城市所选的一部分。
除此之外,还有一个descriptionField 被填充一些随机文本,然后一个submitButton 被点击以发送表单。
我注意到如果我使用actionChains.move_to_element(locationField_sugg).click().perform()点击下拉列表中的地址,那么submitButton会抛出一个StaleElementReference异常,而如果我只是使用locationField_sugg.click()就不是这样了,代码继续进行。
我已经阅读了许多关于这个臭名昭著的异常处理的 Q/A,但似乎没有一个能够解释我的代码中发生这种情况的原因。
对我来说,这似乎与 move_to_element() 结合“地图包装”(?)的行为有关,但我不明白为什么,因为这个函数只是应该在给定元素的中间移动鼠标。
网页中似乎没有重新加载或其他更改(我验证如果我在开始时查询按钮并在脚本末尾重新查询,我会得到相同的确切实例表示字符串)。
此外,我在对其执行操作之前查询了submitButton,并且我认为它已正确找到,因为它可以打印。
下面是我的代码和我得到的输出的 sn-p(注意:如果我使用替代的注释选项,代码可以正常工作,但我很想知道我缺少什么)
代码片段
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
websiteUrl = "https://mywebsite"
option = webdriver.ChromeOptions()
option.add_argument("-incognito")
browser = webdriver.Chrome(executable_path="/Applications/chromedriver", options=option)
browser.get(websiteUrl)
actionChains = ActionChains(browser)
# Write and select complete address
locationField = browser.find_element_by_id("location")
print("locationField = ", locationField)
locationField.send_keys("my location")
locationField_sugg = WebDriverWait(browser, 10).until(EC.visibility_of_element_located((By.ID, "as-listbox")))
print("locationField_sugg = ", locationField_sugg)
#
# this throws stale element reference exception:
actionChains.move_to_element(locationField_sugg).click().perform()
#
# this does not:
# locationField_sugg.click()
# Write description
descriptionField = browser.find_element_by_id("description")
print("descriptionField = ", descriptionField)
descriptionField.send_keys("my description")
# Submit form
submitButton = WebDriverWait(browser, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "span.value")))
print("submitButton = ", submitButton)
actionChains.move_to_element(submitButton).click().perform()
输出
locationField = <selenium.webdriver.remote.webelement.WebElement (session="e10dc716790c61a0c160599624dd30c6", element="e75539a7-ebd0-4090-9c04-0c4994afe03f")>
locationField_sugg = <selenium.webdriver.remote.webelement.WebElement (session="e10dc716790c61a0c160599624dd30c6", element="53ef0269-aceb-451a-b559-d9e5e7aa7851")>
descriptionField = <selenium.webdriver.remote.webelement.WebElement (session="e10dc716790c61a0c160599624dd30c6", element="dce478de-a23d-4ca2-817c-81ee5ce0c232")>
nowButton = <selenium.webdriver.remote.webelement.WebElement (session="e10dc716790c61a0c160599624dd30c6", element="f2036f1c-d164-4211-a37c-2ee50e5c55c1")>
Traceback (most recent call last):
File "/Users/alice/Desktop/wasteComplaints_selenium.py", line 44, in <module>
actionChains.move_to_element(nowButton).click().perform()
File "/Users/alice/miniconda3/lib/python3.9/site-packages/selenium/webdriver/common/action_chains.py", line 80, in perform
self.w3c_actions.perform()
File "/Users/alice/miniconda3/lib/python3.9/site-packages/selenium/webdriver/common/actions/action_builder.py", line 76, in perform
self.driver.execute(Command.W3C_ACTIONS, enc)
File "/Users/alice/miniconda3/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/Users/alice/miniconda3/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, 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=92.0.4515.131)
【问题讨论】:
-
ActionChains 是一种自动化低级别交互的方法,例如鼠标移动、鼠标按钮操作、按键和上下文菜单交互。这对于执行更复杂的操作(例如悬停和拖放)很有用。
标签: python selenium staleelementreferenceexception