使用Selenium提交表单时出现StaleElementReferenceException错误

f0brbegy  于 2023-04-12  发布在  其他
关注(0)|答案(2)|浏览(281)

我尝试使用Selenium和Python在网页上提交表单。表单有一个输入字段和一个提交按钮,我尝试使用find_element()By.NAMEBy.XPATH定位。
我可以成功地在输入字段中输入文本并单击提交按钮。然而,在提交表单并被重定向到新页面后,我不断收到以下错误:

  1. selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document

据我所知,当我试图与之交互的元素不再存在于页面上时,就会发生此错误。然而,我很困惑为什么会发生这种情况,因为我已经成功地单击了提交按钮,并且表单已提交。
下面是相关代码:

  1. import time
  2. from selenium import webdriver
  3. from selenium.webdriver.common.by import By
  4. # open browser and go to webpage
  5. driver = webdriver.Chrome()
  6. driver.get('https://twitter.com/account/begin_password_reset')
  7. # read usernames from txt file
  8. with open('usernames.txt', 'r') as file:
  9. usernames = file.readlines()
  10. # find input field and submit button
  11. input_field = driver.find_element(By.NAME,'account_identifier')
  12. submit_button = driver.find_element(By.XPATH,"//input[@type='submit' and @value='Search']")
  13. # iterate over usernames and submit form
  14. for username in usernames:
  15. # input username and submit form
  16. input_field.clear()
  17. input_field.send_keys(username)
  18. submit_button.click()
  19. # wait for form to submit
  20. time.sleep(10)
  21. # check if radio button exists and get label value
  22. try:
  23. label = driver.find_element_by_css_selector('input[name="method"][checked] + label')
  24. text = label.get_attribute('textContent')
  25. print(text)
  26. except:
  27. pass
  28. # close browser
  29. driver.quit()

谁能解释一下为什么我仍然得到这个错误,即使提交按钮被成功点击,表单被提交?有没有办法修复这个错误?
提前感谢您的帮助!
编辑(对于完整的错误日志):

  1. Traceback (most recent call last):
  2. File "C:\Users\admin\AppData\Local\Programs\Python\Python311\tryreset.py", line 22, in <module>
  3. submit_button.click()
  4. File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 93, in click
  5. self._execute(Command.CLICK_ELEMENT)
  6. File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 410, in _execute
  7. return self._parent.execute(command, params)
  8. File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 444, in execute
  9. self.error_handler.check_response(response)
  10. File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 249, in check_response
  11. raise exception_class(message, screen, stacktrace)
  12. selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  13. (Session info: chrome=107.0.5304.107)
  14. Stacktrace:
  15. Backtrace:
  16. Ordinal0 [0x0082ACD3+2075859]
  17. Ordinal0 [0x007BEE61+1633889]
  18. Ordinal0 [0x006BB7BD+571325]
  19. Ordinal0 [0x006BE374+582516]
  20. Ordinal0 [0x006BE225+582181]
  21. Ordinal0 [0x006BE4C0+582848]
  22. Ordinal0 [0x006EC654+771668]
  23. Ordinal0 [0x006E1AED+727789]
  24. Ordinal0 [0x0070731C+881436]
  25. Ordinal0 [0x006E15BF+726463]
  26. Ordinal0 [0x00707534+881972]
  27. Ordinal0 [0x0071B56A+963946]
  28. Ordinal0 [0x00707136+880950]
  29. Ordinal0 [0x006DFEFD+720637]
  30. Ordinal0 [0x006E0F3F+724799]
  31. GetHandleVerifier [0x00ADEED2+2769538]
  32. GetHandleVerifier [0x00AD0D95+2711877]
  33. GetHandleVerifier [0x008BA03A+521194]
  34. GetHandleVerifier [0x008B8DA0+516432]
  35. Ordinal0 [0x007C682C+1665068]
  36. Ordinal0 [0x007CB128+1683752]
  37. Ordinal0 [0x007CB215+1683989]
  38. Ordinal0 [0x007D6484+1729668]
  39. BaseThreadInitThunk [0x771F00F9+25]
  40. RtlGetAppContainerNamedObjectPath [0x77337BBE+286]
  41. RtlGetAppContainerNamedObjectPath [0x77337B8E+238]
  42. ```
sg2wtvxw

sg2wtvxw1#

StaleElementReferenceException发生在您尝试与之交互的元素不再附加到DOM(文档对象模型)时,这意味着它已从页面中删除或被新的元素替换。
在您的例子中,当您尝试访问元素时,页面可能仍在加载或重定向到新页面的过程中,导致元素与DOM分离。
要修复此错误,您可以尝试在单击提交按钮后添加wait语句,以允许页面完全加载并将元素重新附加到DOM。您可以使用Selenium提供的WebDriverWait类来等待特定元素在页面上可用。
以下是如何修改代码以包含wait语句:

  1. from selenium.webdriver.support.ui import WebDriverWait
  2. from selenium.webdriver.support import expected_conditions as EC
  3. # iterate over usernames and submit form
  4. for username in usernames:
  5. # input username and submit form
  6. input_field.clear()
  7. input_field.send_keys(username)
  8. submit_button.click()
  9. # wait for form to submit and for page to fully load
  10. WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input[name="method"][checked] + label')))
  11. # check if radio button exists and get label value
  12. try:
  13. label = driver.find_element_by_css_selector('input[name="method"][checked] + label')
  14. text = label.get_attribute('textContent')
  15. print(text)
  16. except:
  17. pass

在这段代码中,我使用WebDriverWait类等待长达10秒的时间,等待CSS选择器'input[name=“method”][checked] + label'的元素出现在页面上,然后继续执行。一旦找到元素,脚本将继续执行try块中的其余代码。
通过添加此wait语句,您应该能够避免StaleElementReferenceException错误,并按预期与元素交互。

展开查看全部
whitzsjs

whitzsjs2#

问题是你在循环之前/之外获取和存储input_fieldsubmit_button。在循环内部,我敢肯定,当你点击提交按钮时,页面更改/刷新导致陈旧异常,因为你已经丢失了对这两个元素的引用。只要在循环内部获取这两个元素,就应该解决这个问题。一旦页面重新加载,这些元素是从当前页面中新获取的。
我还删除了循环中间的sleep。sleep是一个糟糕的做法,因为它们并不“聪明”。它们会等待你告诉它们等待的时间,这可能是足够的,也可能是太多的,这取决于网站的速度。相反,使用WebDriverWait来等待一些条件,它只会等待需要的时间,加快你的脚本速度,并(通常)消除间歇性问题。

  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. from selenium.webdriver.support import expected_conditions as EC
  4. from selenium.webdriver.support.wait import WebDriverWait
  5. # open browser and go to webpage
  6. driver = webdriver.Chrome()
  7. driver.get('https://twitter.com/account/begin_password_reset')
  8. # read usernames from txt file
  9. with open('usernames.txt', 'r') as file:
  10. usernames = file.readlines()
  11. # iterate over usernames and submit form
  12. for username in usernames:
  13. # input username and submit form
  14. input_field = driver.find_element(By.NAME,'account_identifier')
  15. input_field.clear()
  16. input_field.send_keys(username)
  17. submit_button = driver.find_element(By.XPATH,"//input[@type='submit' and @value='Search']")
  18. submit_button.click()
  19. # wait for form to submit
  20. wait = WebDriverWait(driver, 10)
  21. wait.until(EC.staleness_of(submit_button))
  22. # check if radio button exists and get label value
  23. try:
  24. label = wait.until(EC.visibility_of_element_located(By.CSS_SELECTOR, 'input[name="method"][checked] + label'))
  25. text = label.get_attribute('textContent')
  26. print(text)
  27. except:
  28. pass
  29. # close browser
  30. driver.quit()
展开查看全部

相关问题