chrome下载需配置绝对路径的download.default_directory并禁用prompt_for_download,linux/macos需确保写权限;下载完成须轮询校验文件大小稳定,超时设60秒防死锁。

设置Chrome选项启用下载并指定默认目录
直接调用 driver.get() 触发下载时,Chrome 默认会把文件存到系统默认下载目录(如 ~/Downloads),且无法在下载过程中干预文件名。必须提前通过 ChromeOptions 配置 download.default_directory 和禁用下载栏弹窗,否则 Selenium 会卡住或下载失败。
关键点:路径必须是绝对路径;需手动创建目录;download.prompt_for_download 必须设为 False,否则 Chrome 会弹确认框阻塞自动化。
options.add_experimental_option("prefs", {"download.default_directory": "/absolute/path/to/download_dir", "download.prompt_for_download": False, "download.directory_upgrade": True})- Windows 用户注意路径分隔符:用
r"C:path odir"或双反斜杠"C:\path\to\dir" - Linux/macOS 下确保目录有写权限,否则下载会静默失败(无报错但文件不出现)
等待下载完成并校验文件是否真实写入
Selenium 不提供“下载完成”事件监听,driver.execute_script("return window.performance.getEntries();") 也拿不到下载请求状态。可靠做法是轮询目标目录,检查文件是否存在、大小是否稳定(防止只写了一半就去重命名)。
常见错误:用 os.path.exists() 刚检测到文件就立刻重命名 —— 此时文件可能还在写入中,导致 OSError: [Errno 13] Permission denied(Windows)或内容截断(Linux/macOS)。
- 推荐逻辑:每 0.5 秒检查一次,直到文件存在且连续两次
os.path.getsize()相同(说明写入结束) - 超时建议设为 60 秒,避免无限等待;配合
try/except捕获FileNotFoundError - 示例片段:
while time.time() - start
用 shutil.move() 安全重命名已下载文件
不能用 os.rename() 跨文件系统重命名(比如从 /tmp 重命名到 /home 可能失败),也不能在 Windows 上对正在被浏览器写入的文件直接操作。必须等上一步确认写入完成后再执行移动。
更稳妥的做法是:先生成带完整路径的目标文件名,再用 shutil.move(src, dst) —— 它自动处理跨分区、覆盖等边界情况,且比 os.replace() 兼容性更好(Python 3.3+)。
- 源路径是下载目录下的原始文件名(通常由服务器 Content-Disposition 决定,可能含时间戳或随机串)
- 目标路径应包含完整目录 + 你想要的新文件名,例如
os.path.join(download_dir, "report_20240515.xlsx") - 如果目标文件已存在,
shutil.move()会直接覆盖,无需额外判断(除非业务要求跳过)
绕过前端 JS 触发下载的隐藏限制
有些页面用 fetch() + Blob + URL.createObjectURL() 实现下载,不发 HTTP 请求,Selenium 无法捕获网络流。此时 driver.find_element().click() 可能无效,因为按钮绑定的是 JS 函数而非标准 <a href></a>。
解决思路不是“拦截响应”,而是模拟 JS 执行环境,让 Blob 下载走通:
- 确保 Chrome 启动时未加
--disable-web-security(它反而会破坏 Blob URL 解析) - 改用
driver.execute_script()注入并触发目标函数,例如:driver.execute_script("document.querySelector('#export-btn').click()") - 若仍失败,可尝试先用
driver.execute_script("return window.URL.createObjectURL(...);")提前生成 URL,再用driver.get(url)强制触发下载(需配合前面的 Chrome 下载配置)
文件名不可控、下载路径不明确、JS 下载拦截 —— 这三类问题往往交织出现。最易被忽略的是“写入未完成就重命名”,它不抛异常,只导致后续读取失败或数据损坏,调试时容易误判为网络或权限问题。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











