如何使用Selenium点击Highcharts的SVG元素实现XLS文件自动下载
问题说明
此前曾提出过相关需求,目前仅有效率较低的临时替代方案,需要实现Highcharts图表对应XLS文件的自动化下载,操作逻辑如下:
- 第一步:点击页面Highcharts图表上的下载图标(示意图中绿色箭头标注位置)
- 第二步:点击弹出菜单中的「Download XLS」选项完成文件下载
页面中Highcharts的id属性每次页面加载时都会动态变化,原有尝试代码运行失败,原代码如下:
def unityengine_data(): driver.get("https://steamdb.info/tech/Engine/Unity/") wait WebDriverWait(driver,30).until(EC.visibility_of_element_located((By.XPATH, "div[contains(@id,'highcharts-')]//*[local-name() = 'svg']/*[name()='g'][6]/*[name()='g']/*[name()='image']"))).click WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH, "div[contains(@id,'highcharts-')]//**[local-name() = 'div']/*[name()='ul'][6]/*[name()='li'][2]"))).click os.rename("downloaded file path", "new file path") return "Unity Engine apps data successfully downloaded"
页面初始状态示意图:
首次点击下载图标后的页面状态示意图:
原有代码失效原因
- XPath语法错误:开头标签未加匹配前缀、存在多余的
*通配符,且元素层级索引硬编码(固定取第6个g标签、第6个ul标签),Highcharts渲染时元素顺序会随版本、页面布局调整,鲁棒性极差 - 方法调用错误:
.click后未加括号,实际不会触发点击动作;单独写的wait是无效代码,没有实际等待作用 - 定位逻辑冗余:不需要硬编码svg内部层级,Highcharts导出按钮有固定的类名、属性特征,直接匹配特征更稳定
- 未做下载配置:没有提前设置浏览器默认下载路径、关闭下载弹窗,会导致文件下载位置不可控、重命名逻辑找不到目标文件
可行实现方案
提前配置浏览器下载参数,通过Highcharts控件自带的类名、文本特征定位元素,不依赖动态生成的id和固定元素索引:
import os 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 from selenium.webdriver.chrome.options import Options def unityengine_data(save_path="your_target_save_directory"): # 配置浏览器下载规则 chrome_opt = Options() download_prefs = { "download.default_directory": os.path.abspath(save_path), "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True } chrome_opt.add_experimental_option("prefs", download_prefs) driver = webdriver.Chrome(options=chrome_opt) wait = WebDriverWait(driver, 30) driver.get("https://steamdb.info/tech/Engine/Unity/") # 定位导出按钮:匹配Highcharts导出按钮组的固定类名,不依赖动态id export_btn = wait.until(EC.element_to_be_clickable( (By.CSS_SELECTOR, "div[class*='highcharts-'] g.highcharts-exporting-group image") )) export_btn.click() # 定位XLS下载选项:通过菜单文本匹配,避免索引写死失效 xls_download_btn = wait.until(EC.element_to_be_clickable( (By.XPATH, "//div[contains(@class,'highcharts-contextmenu')]//li[contains(text(),'Download XLS')]") )) xls_download_btn.click() # 等待文件下载完成,可根据网速调整等待时长,也可写循环判断目录下临时下载文件是否消失来确认下载完成 time.sleep(5) # 替换为实际默认下载文件名、目标文件名即可执行重命名 # default_download_file = os.path.join(save_path, "chart.xls") # target_file = os.path.join(save_path, "unity_engine_apps_data.xls") # os.rename(default_download_file, target_file) driver.quit() return "Unity Engine apps data successfully downloaded"
补充说明
- 如果页面存在多个Highcharts图表,给选择器加上父容器限定即可,比如要匹配第一个图表可以在CSS选择器里加
:first-of-type限定 - 如果访问时触发Cloudflare人机验证,需要先完成验证逻辑再执行后续下载操作
- 不建议用固定sleep等待下载完成,可以通过监听下载目录的文件变化,判断
.crdownload后缀的临时文件消失后再执行后续文件操作,稳定性更高
内容的提问来源于stack exchange,提问作者ChancellorInSidious
相关产品推荐
相关产品推荐

