基于Python+Selenium的Edge网页自动化:数据保存失败求助
问题解决方案
核心问题梳理
- 使用
send_keys填充输入字段无效,改用JavaScript设置值后数据显示但无法触发后端保存 - 页面存在多个保存按钮,全局定位易命中错误按钮,点击后未触发实际保存
- 无法捕获"saved successfully"提示框,无法确认保存完成状态
- 硬编码
time.sleep适配性差,无法应对服务器响应缓慢的场景
针对性解决方案
1. 修复输入字段的前端交互触发逻辑
现代前端框架(如React、Vue)通常依赖input、blur事件而非仅change事件来更新表单状态,修改JavaScript赋值逻辑以触发完整交互链:
# 替换原JavaScript赋值代码 driver.execute_script(""" arguments[0].value = arguments[1]; arguments[0].dispatchEvent(new Event('input', { bubbles: true })); arguments[0].dispatchEvent(new Event('blur', { bubbles: true })); """, input_field, new_value)
2. 精准定位当前行关联的保存按钮
避免全局查找保存按钮,改为从当前操作的行元素内部定位关联按钮,确保点击的是当前行的保存控件:
# 替换原保存按钮定位代码 save_button = row_element.find_element(By.XPATH, ".//button[contains(@class, 'MuiButton-containedSAVE') and @type='submit']") driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", save_button) wait.until(EC.element_to_be_clickable(save_button)).click()
3. 等待保存成功提示框确认状态
通过显式等待提示框的出现和消失,确保服务器完成数据持久化操作:
# 点击保存后添加以下代码 try: # 等待提示框出现 success_toast = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[normalize-space(text())='Saved successfully']"))) # 等待提示框消失 wait.until(EC.invisibility_of_element_located((By.XPATH, "//*[normalize-space(text())='Saved successfully']"))) print("保存成功提示已确认") except Exception as e: print(f"未捕获到保存成功提示: {e}")
4. 替换硬编码sleep为显式等待
移除固定时长的time.sleep,改用WebDriverWait等待关键元素状态,提升脚本稳定性:
# 替换原页面加载等待 # time.sleep(20) wait.until(EC.presence_of_element_located((By.ID, 'eyePassword'))) # 替换点击show more后的sleep # time.sleep(15) wait.until(EC.staleness_of(driver.find_element(By.CSS_SELECTOR, "button[aria-label='show more']")))
5. 增加保存后的数据验证
保存完成后重新读取输入字段的值,确认数据已成功持久化:
# 保存后添加验证逻辑 time.sleep(2) print(f"开始验证{habitation_code}保存后数据") for j in range(7, 16): input_xpath = f"{row_xpath}/td[{j+1}]/div/div/input" input_field = wait.until(EC.visibility_of_element_located((By.XPATH, input_xpath))) saved_value = format_decimal(input_field.get_attribute('value')) expected_value = data_columns[j -7] if saved_value == expected_value: print(f"Column {j+1}数据验证通过") else: print(f"Column {j+1}数据验证失败: 预期{expected_value}, 实际{saved_value}")
修改后的完整代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.edge.service import Service from selenium.webdriver.edge.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import pandas as pd import time # Load Excel data excel_file = "***FILE PATH***" # Load Habitation Code (Column B) and data from Columns H to P df = pd.read_excel(excel_file, usecols="B,H:P", skiprows=0) df.columns = ['Habitation Code'] + [f'Field_{i}' for i in range(1, 10)] # Function to format decimal values def format_decimal(value): if pd.isna(value): return '' try: if '.' in str(value): return f"{float(value):.3f}" else: return str(value) except ValueError: return str(value) # Apply formatting to relevant fields for col in df.columns[1:]: df[col] = df[col].apply(format_decimal) # Configure Edge options edge_options = Options() edge_options.add_argument("--disable-notifications") edge_options.add_argument("--disable-popup-blocking") edge_options.add_argument("--start-maximized") # 直接最大化窗口,替代后续maximize_window # Path to Edge WebDriver executable edge_driver_path = r"C:\WebDriver\Edge\msedgedriver.exe" # 用原始字符串避免转义问题 # Set up the Edge Service and WebDriver service = Service(executable_path=edge_driver_path) driver = webdriver.Edge(service=service, options=edge_options) # Open the URL driver.get('***URL***') # Initialize WebDriverWait wait = WebDriverWait(driver, 30) # 延长等待时间适配服务器缓慢场景 # Wait for login elements to load (替换硬编码sleep) wait.until(EC.presence_of_element_located((By.ID, 'eyePassword'))) # Locate and interact with login elements try: wait.until(EC.visibility_of_element_located((By.XPATH, "//input[@id=':r2:']"))).send_keys('***USER ID***') wait.until(EC.visibility_of_element_located((By.ID, 'eyePassword'))).send_keys('***PASSWORD***') wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Login']"))).click() print("Login successful.") except Exception as e: print(f"Error during login: {e}") driver.quit() # Navigate to Edit page try: wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "svg[data-testid='ExpandMoreIcon']"))).click() wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "svg[data-testid='SchemaIcon']"))).click() wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "svg[data-testid='EditIcon']"))).click() print("Navigated to Edit page.") except Exception as e: print(f"Error during navigation: {e}") driver.quit() # Locate and click the fifth "show more" button try: show_more_buttons = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "button[aria-label='show more']"))) if len(show_more_buttons) >=5: target_button = show_more_buttons[4] wait.until(EC.element_to_be_clickable(target_button)).click() # 等待页面加载完成,替代sleep wait.until(EC.staleness_of(target_button)) print("Clicked the fifth 'show more' button.") else: print("不足5个show more按钮") except Exception as e: print(f"Error finding 'show more' button: {e}") driver.quit() # Function to input data into table rows def fill_table_data(): for i, row in df.iterrows(): habitation_code = row['Habitation Code'] data_columns = row[1:].tolist() updated = False try: # Find the row element by habitation code row_xpath = f"//tr[td[2][contains(text(), '{habitation_code}')]]" row_element = wait.until(EC.presence_of_element_located((By.XPATH, row_xpath))) print(f"Found row for Habitation Code {habitation_code}") # Locate all input fields in the last 9 td elements of the row for j in range(7, 16): try: input_xpath = f"{row_xpath}/td[{j+1}]/div/div/input" input_field = wait.until(EC.visibility_of_element_located((By.XPATH, input_xpath))) driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", input_field) new_value = data_columns[j -7] # 触发完整的输入事件 driver.execute_script(""" arguments[0].value = arguments[1]; arguments[0].dispatchEvent(new Event('input', { bubbles: true })); arguments[0].dispatchEvent(new Event('blur', { bubbles: true })); """, input_field, new_value) # 验证输入值 entered_value = input_field.get_attribute('value') formatted_entered_value = format_decimal(entered_value) print(f"Column {j+1}: 预期{new_value}, 实际{formatted_entered_value}") if formatted_entered_value != new_value: print(f"Column {j+1}数据不一致,清空重试") driver.execute_script("arguments[0].value = '';", input_field) driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", input_field) time.sleep(1) continue updated = True print(f"Column {j+1}填充成功") # 短等待避免操作过快 time.sleep(1) except Exception as e: print(f"Error processing column {j+1} for {habitation_code}: {e}") if updated: # 定位当前行的保存按钮 try: save_button = row_element.find_element(By.XPATH, ".//button[contains(@class, 'MuiButton-containedSAVE') and @type='submit']") driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", save_button) wait.until(EC.element_to_be_clickable(save_button)).click() print("Clicked row save button.") # 等待保存成功提示 try: success_toast = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[normalize-space(text())='Saved successfully']"))) wait.until(EC.invisibility_of_element_located((By.XPATH, "//*[normalize-space(text())='Saved successfully']"))) print(f"{habitation_code}保存成功,提示已确认") except Exception as e: print(f"{habitation_code}保存后未捕获到成功提示: {e}") # 保存后验证数据 time.sleep(2) print(f"开始验证{habitation_code}保存后数据") for j in range(7, 16): input_xpath = f"{row_xpath}/td[{j+1}]/div/div/input" input_field = wait.until(EC.visibility_of_element_located((By.XPATH, input_xpath))) saved_value = format_decimal(input_field.get_attribute('value')) expected_value = data_columns[j -7] if saved_value == expected_value: print(f"Column {j+1}数据验证通过") else: print(f"Column {j+1}数据验证失败: 预期{expected_value}, 实际{saved_value}") except Exception as e: print(f"Error clicking save button for {habitation_code}: {e}") except Exception as e: print(f"Error processing row {habitation_code}: {e}") # Call the function to fill table data fill_table_data() # Keep the browser open until manually closed print("Browser is open. Press Ctrl+C in the terminal to close it.") try: while True: time.sleep(1) except KeyboardInterrupt: print("Browser closed.") driver.quit()
内容的提问来源于stack exchange,提问作者Seenivasan Chinnachamy
相关产品推荐
相关产品推荐

