Python 2.x实现Power BI报表截图遇元素过期异常求助
解决Power BI登录截图中的Stale Element Reference错误
问题背景
需在Python 2.x环境(适配Power Automate)下编写脚本,完成Power BI报表截图:流程为输入邮箱→提交→输入密码→登录→确认保持登录,最终截取报表画面。当前脚本执行actionChains.click(password_field).send_keys(password).perform()时触发错误:Message: stale element reference: stale element not found。
原代码如下:
import datetime import time import os 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 from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import StaleElementReferenceException def login_powerbi(username, password): # Set up the ChromeDriver path in the PATH environment variable chromedriver_path = 'C:/Users/Desktop/Screenshot/chrome_driver/chromedriver.exe' driver = webdriver.Chrome(executable_path=chromedriver_path) # Set up the webdriver # driver = webdriver.Chrome() actionChains = ActionChains(driver) try: # Open the Power BI report URL (login page) driver.get("https://app.powerbi.com/") # Wait for the login page to load time.sleep(5) wait = WebDriverWait(driver, 60) email_field = wait.until(EC.presence_of_element_located((By.ID, "email"))) actionChains.click(email_field).send_keys(username).perform() driver.find_element(By.CSS_SELECTOR, "[id=submitBtn]").click() time.sleep(5) # Wait for the password field to load and then enter the password password_field = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "[type=password]"))) actionChains.click(password_field).send_keys(password).perform() # Submit the password form driver.find_element(By.CSS_SELECTOR, "[id=idSIButton9]").click() # Wait for the "Stay signed in?" prompt to load and then click "Yes" time.sleep(3) stay_signed_in_prompt = wait.until(EC.presence_of_element_located((By.ID, "idSIButton9"))) # idSIButton9 stay_signed_in_prompt.click() # Wait for the Power BI report to load after authentication driver.implicitly_wait(30) # Add a delay before taking the screenshot to ensure the report is fully loaded time.sleep(10) # Take the screenshot now = datetime.datetime.now() file_name = 'powerBI_{}.png'.format(now.strftime("%Y-%m-%d_%H-%M-%S")) output_path = "C:/Users/Desktop/Screenshot/output/" screenshot_output_file = os.path.join(output_path, file_name) screenshot_BI = driver.save_screenshot(screenshot_output_file) print(screenshot_BI) print("Screenshot saved as {}".format(screenshot_output_file)) except StaleElementReferenceException as e: # Re-locate the element and retry the action print("Stale element reference, retrying...") login_powerbi(username, password) except Exception as e: print("Error during login and screenshot capture: {}".format(e)) finally: # Close the browser driver.quit() if __name__ == "__main__": # Replace 'your_username' and 'your_password' with your actual Power BI login credentials login_powerbi("your@mail.com", "password")
错误原因
Stale Element Reference错误是因为页面DOM刷新/跳转后,之前定位的元素引用失效。原代码存在以下问题:
- 复用全局
ActionChains实例,页面跳转后实例关联的元素上下文过期 - 依赖硬编码
time.sleep(),无法精准等待元素加载完成,导致定位时机错误 - 页面跳转后未重新定位元素,直接使用旧引用
修正后的代码
import datetime import time import os 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 from selenium.common.exceptions import StaleElementReferenceException def login_powerbi(username, password, report_url="https://app.powerbi.com/"): chromedriver_path = 'C:/Users/Desktop/Screenshot/chrome_driver/chromedriver.exe' driver = webdriver.Chrome(executable_path=chromedriver_path) wait = WebDriverWait(driver, 60) try: # 打开目标Power BI页面 driver.get(report_url) # 输入邮箱并提交 email_field = wait.until(EC.visibility_of_element_located((By.ID, "email"))) email_field.clear() email_field.send_keys(username) submit_btn = wait.until(EC.element_to_be_clickable((By.ID, "submitBtn"))) submit_btn.click() # 等待密码页面加载,输入密码 password_field = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "[type=password]"))) password_field.clear() password_field.send_keys(password) login_btn = wait.until(EC.element_to_be_clickable((By.ID, "idSIButton9"))) login_btn.click() # 处理保持登录提示 stay_signed_btn = wait.until(EC.element_to_be_clickable((By.ID, "idSIButton9"))) stay_signed_btn.click() # 等待报表页面完全加载(需根据实际报表调整选择器) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".reportContainer"))) time.sleep(2) # 额外等待渲染完成 # 生成截图(确保输出目录存在) now = datetime.datetime.now() file_name = 'powerBI_{}.png'.format(now.strftime("%Y-%m-%d_%H-%M-%S")) output_path = "C:/Users/Desktop/Screenshot/output/" if not os.path.exists(output_path): os.makedirs(output_path) screenshot_output_file = os.path.join(output_path, file_name) driver.save_screenshot(screenshot_output_file) print("截图已保存至: {}".format(screenshot_output_file)) except StaleElementReferenceException: print("元素引用失效,正在重试...") driver.quit() login_powerbi(username, password, report_url) except Exception as e: print("执行出错: {}".format(e)) finally: driver.quit() if __name__ == "__main__": # 替换为实际账号密码和目标报表URL login_powerbi("your@mail.com", "password", "https://app.powerbi.com/groups/xxx/reports/xxx")
关键修改点
- 移除全局
ActionChains实例,直接使用元素自身的send_keys()和click()方法,避免上下文失效 - 用显式等待替换大部分
time.sleep(),确保元素可交互后再操作 - 页面跳转后重新定位元素,不复用旧引用
- 添加目录检查,自动创建截图输出目录
- 支持传入自定义报表URL,无需固定登录页
- 调整报表加载等待条件,使用页面特有元素选择器(需根据实际报表修改)
内容的提问来源于stack exchange,提问作者gourav
相关产品推荐
相关产品推荐

