You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 05:48:09