使用Selenium提交表单时遭遇StaleElementReferenceException错误
问题:Selenium提交表单后出现StaleElementReferenceException错误
我用Python结合Selenium提交网页表单,表单包含输入框和提交按钮,通过find_element()、By.NAME和By.XPATH定位元素。能成功向输入框输入文本并点击提交按钮,但提交表单跳转至新页面后,持续出现以下错误:
selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
我理解该错误是因为要交互的元素已不在页面中,但困惑的是我已成功点击提交按钮且表单已提交。
相关代码
import time from selenium import webdriver from selenium.webdriver.common.by import By # open browser and go to webpage driver = webdriver.Chrome() driver.get('https://twitter.com/account/begin_password_reset') # read usernames from txt file with open('usernames.txt', 'r') as file: usernames = file.readlines() # find input field and submit button input_field = driver.find_element(By.NAME,'account_identifier') submit_button = driver.find_element(By.XPATH,"//input[@type='submit' and @value='Search']") # iterate over usernames and submit form for username in usernames: # input username and submit form input_field.clear() input_field.send_keys(username) submit_button.click() # wait for form to submit time.sleep(10) # check if radio button exists and get label value try: label = driver.find_element_by_css_selector('input[name="method"][checked] + label') text = label.get_attribute('textContent') print(text) except: pass # close browser driver.quit()
完整错误日志
Traceback (most recent call last): File "C:\Users\admin\AppData\Local\Programs\Python\Python311\tryreset.py", line 22, in <module> submit_button.click() File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 93, in click self._execute(Command.CLICK_ELEMENT) File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\webelement.py", line 410, in _execute return self._parent.execute(command, params) File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\webdriver.py", line 444, in execute self.error_handler.check_response(response) File "C:\Users\admin\AppData\Local\Programs\Python\Python311\Lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 249, 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=107.0.5304.107) Stacktrace: Backtrace: Ordinal0 [0x0082ACD3+2075859] Ordinal0 [0x007BEE61+1633889] Ordinal0 [0x006BB7BD+571325] Ordinal0 [0x006BE374+582516] Ordinal0 [0x006BE225+582181] Ordinal0 [0x006BE4C0+582848] Ordinal0 [0x006EC654+771668] Ordinal0 [0x006E1AED+727789] Ordinal0 [0x0070731C+881436] Ordinal0 [0x006E15BF+726463] Ordinal0 [0x00707534+881972] Ordinal0 [0x0071B56A+963946] Ordinal0 [0x00707136+880950] Ordinal0 [0x006DFEFD+720637] Ordinal0 [0x006E0F3F+724799] GetHandleVerifier [0x00ADEED2+2769538] GetHandleVerifier [0x00AD0D95+2711877] GetHandleVerifier [0x008BA03A+521194] GetHandleVerifier [0x008B8DA0+516432] Ordinal0 [0x007C682C+1665068] Ordinal0 [0x007CB128+1683752] Ordinal0 [0x007CB215+1683989] Ordinal0 [0x007D6484+1729668] BaseThreadInitThunk [0x771F00F9+25] RtlGetAppContainerNamedObjectPath [0x77337BBE+286] RtlGetAppContainerNamedObjectPath [0x77337B8E+238]
原因分析与修复方案
原因解释
错误并非出现在第一次提交后,而是第二次循环点击submit_button时。核心原因:
- 第一次点击提交后,页面发生跳转/刷新,原页面的
input_field和submit_button元素已被销毁,Selenium中缓存的元素引用变成了"过时"状态。 - 循环到第二个用户名时,你仍在尝试使用之前缓存的元素对象,这些对象对应的元素已不存在于当前页面,因此抛出
StaleElementReferenceException。
修复方案
每次循环都重新定位元素,确保使用当前页面的有效实例,同时用显式等待替换固定时长等待,提升稳定性:
修复后的代码
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # open browser and initialize wait driver = webdriver.Chrome() wait = WebDriverWait(driver, 10) # read usernames and strip newline characters with open('usernames.txt', 'r') as file: usernames = [name.strip() for name in file.readlines()] for username in usernames: # reload the reset page for each username driver.get('https://twitter.com/account/begin_password_reset') # wait for input field to be present, then input username input_field = wait.until(EC.presence_of_element_located((By.NAME, 'account_identifier'))) input_field.clear() input_field.send_keys(username) # wait for submit button to be clickable, then click submit_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@type='submit' and @value='Search']"))) submit_button.click() # wait for target label to appear and get its text try: label = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input[name="method"][checked] + label'))) print(label.get_attribute('textContent')) except: continue # close browser driver.quit()
关键修改点
- 每次循环重新加载初始页面:确保每次操作都在全新的表单页面进行,避免页面状态混乱。
- 用显式等待替换
time.sleep():WebDriverWait会等待元素满足条件后再执行操作,比固定时长等待更可靠,还能减少不必要的等待时间。 - 每次循环重新定位元素:不再缓存元素引用,每次都从当前页面获取最新元素实例,彻底避免过时元素引用问题。
内容的提问来源于stack exchange,提问作者Veiia
相关产品推荐
相关产品推荐

