求助:Python Selenium无法填充Microsoft Report Builder页面日期框
问题解决:Microsoft Report Builder 日期填充自动化失败
核心问题分析
- 日期逻辑错误:当前代码生成的是当月第一天,而非需求的上月第一天/最后一天
- 仅修改DOM属性未触发页面事件:Report Viewer的输入框依赖
onchange事件同步值到后端,单纯设置value属性不会被页面识别 - 未等待输入框完全加载:进入AR页面后直接操作元素,可能元素还未渲染完成
- 使用了Selenium已废弃的API:
find_element_by_xpath在新版本中已被弃用
修正后的完整代码
import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from datetime import datetime, timedelta def open_and_click_button(url, username, password): driver = None try: # 初始化Chrome浏览器(可根据需要调整headless模式) options = Options() options.headless = True driver = webdriver.Chrome(options=options) driver.get(url) # 登录流程 username_field = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, 'mat-input-0')) ) username_field.send_keys(username) password_field = WebDriverWait(driver, 10).until( EC.visibility_of_element_located((By.ID, 'mat-input-1')) ) password_field.send_keys(password) login_button = driver.find_element(By.CLASS_NAME, 'mat-button-wrapper') login_button.click() # 点击Reports按钮 reports_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, '//img[@alt="Reports" and contains(@src, "appmenu_reports_24.svg")]')) ) driver.execute_script("arguments[0].click();", reports_button) # 点击AR按钮 ar_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.XPATH, '/html/body/app-root/div/app-layout/app-header/mat-sidenav-container/mat-sidenav-content/div/app-report-view/div[3]/app-inview-grid/ag-grid-angular/div/div[2]/div[2]/div[3]/div[1]/div/div[2]/div/div/div[4]/div[2]/span/span[4]/app-report-link-renderer/a')) ) driver.execute_script("arguments[0].click();", ar_button) # ------------------- 日期处理修正 ------------------- # 获取上月的第一天和最后一天 today = datetime.today() # 计算上月第一天:当月第一天减1天,再取当月第一天 first_day_last_month = (today.replace(day=1) - timedelta(days=1)).replace(day=1) # 计算上月最后一天:当月第一天减1天 last_day_last_month = today.replace(day=1) - timedelta(days=1) # 格式化日期为YYYY-MM-DD start_date = first_day_last_month.strftime("%Y-%m-%d") end_date = last_day_last_month.strftime("%Y-%m-%d") # ------------------- 填充开始日期 ------------------- # 等待开始日期输入框可交互 start_date_input = WebDriverWait(driver, 15).until( EC.element_to_be_clickable((By.ID, 'ReportViewerControl_ctl04_ctl03_txtValue')) ) # 清除原有内容(如果有) start_date_input.clear() # 输入日期 start_date_input.send_keys(start_date) # 触发onchange事件,确保页面识别到值变化 driver.execute_script("arguments[0].dispatchEvent(new Event('change'));", start_date_input) # ------------------- 填充结束日期(需根据实际ID调整) ------------------- # 请替换为实际结束日期框的ID end_date_input = WebDriverWait(driver, 15).until( EC.element_to_be_clickable((By.ID, 'ReportViewerControl_ctl04_ctl05_txtValue')) ) end_date_input.clear() end_date_input.send_keys(end_date) driver.execute_script("arguments[0].dispatchEvent(new Event('change'));", end_date_input) # ------------------- 后续操作:取消下拉框选项、下载报告(示例) ------------------- # 若下拉框为标准select元素,可使用以下代码 # from selenium.webdriver.support.ui import Select # dropdown = Select(driver.find_element(By.ID, '目标下拉框ID')) # dropdown.deselect_by_value('要取消的选项值') # 点击下载按钮示例 # download_btn = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '下载按钮的XPath'))) # download_btn.click() except Exception as e: print(f"错误信息: {e}") # 可选:保存错误截图用于排查 # if driver: # driver.save_screenshot('error_screenshot.png') finally: if driver: time.sleep(10) driver.quit() # 示例调用 url = "X" username = "X" password = "X" open_and_click_button(url, username, password)
关键改进点说明
- 日期逻辑修正:
- 通过
datetime和timedelta精准计算上月的第一天和最后一天,完全匹配需求
- 通过
- 元素交互优化:
- 等待输入框进入
可交互状态(而非仅可见),避免因元素未加载完成导致操作失败 - 先清空输入框再填入日期,避免原有内容干扰
- 触发
change事件:通过JS模拟输入框的onchange行为,让Report Viewer后端同步日期值(这是原代码失效的核心原因)
- 等待输入框进入
- API更新:
- 替换已废弃的
find_element_by_xpath为标准的WebDriverWait + By.ID写法,适配新版Selenium
- 替换已废弃的
- 鲁棒性提升:
- 优化driver生命周期管理,确保异常情况下浏览器能正常关闭
- 增加错误截图注释,方便问题排查
注意事项
- 结束日期框的ID需要根据实际页面元素调整(Report Viewer的日期控件ID通常有规律,比如开始为
ctl03,结束为ctl05) - 如果日期输入框是弹出日历控件,需先点击输入框唤起日历再选择日期;根据提供的元素代码,直接输入文本是可行的
- 下拉框操作需根据实际元素类型(标准select或自定义下拉)调整代码,注释中提供了标准Select类的使用示例
内容的提问来源于stack exchange,提问作者Gary Macdonald
相关产品推荐
相关产品推荐

