基于Python的Selenium Docker环境无法下载文件问题求助
解决Docker中Chrome无头模式下Selenium下载文件丢失的问题
以下是针对问题的具体排查和解决步骤:
1. 补全Dockerfile中Chrome与Chromedriver的安装步骤
你的Dockerfile仅查看了chromium缓存信息,未实际安装Chrome和对应版本的Chromedriver,这会导致Selenium无法正常驱动Chrome完成下载。修改Dockerfile,添加安装命令:
ENV HOME=/home/user \ PATH=/home/user/.local/bin:$PATH WORKDIR $HOME/app # 安装Chrome、Chromedriver及依赖 RUN apt-get update && apt-get install -y --no-install-recommends \ chromium \ chromium-driver \ && rm -rf /var/lib/apt/lists/* # 验证安装版本 RUN chromium --version RUN chromedriver --version RUN python3 --version COPY --chown=user . $HOME/app CMD ["python3","app.py"]
2. 完善Chrome无头模式的下载配置
无头模式下Chrome需要额外配置确保下载正常,补充以下参数和偏好设置:
import os download_path = "/home/user/app/downloads" # 必须使用绝对路径 os.makedirs(download_path, exist_ok=True) prefs = { "download.default_directory": download_path, "download.prompt_for_download": False, # 禁用下载弹窗 "download.directory_upgrade": True, # 自动升级下载目录 "safebrowsing.enabled": True # 避免部分下载被安全策略拦截 } chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--headless=new') # Chrome 112+推荐使用新版无头模式 chrome_options.add_argument('--no-sandbox') chrome_options.add_argument('--disable-dev-shm-usage') chrome_options.add_argument('--disable-gpu') # 无头模式需禁用GPU chrome_options.binary_location = '/usr/bin/chromium' # 指定Chrome二进制文件路径 chrome_options.add_argument('--safebrowsing-disable-download-protection') # 禁用下载保护拦截 chrome_options.add_experimental_option('prefs', prefs) driver = webdriver.Chrome(options=chrome_options)
3. 确保下载目录的权限正确
如果download_path对应的目录不存在或当前用户无读写权限,Chrome会静默失败:
- 在脚本中添加目录创建与权限验证:
print(f"Download directory permissions: {oct(os.stat(download_path).st_mode)[-3:]}") - 或在Dockerfile中提前创建目录并设置权限:
RUN mkdir -p $HOME/app/downloads && chown -R user:user $HOME/app/downloads
4. 验证Chrome实际下载状态与路径
在脚本中添加调试逻辑,确认Chrome是否触发下载及文件保存路径:
# 触发下载操作后,访问Chrome下载页面 driver.get('chrome://downloads/') # 通过JS获取下载记录 downloads = driver.execute_script(""" return document.querySelector('downloads-manager') .shadowRoot.querySelector('#downloadsList') .items.map(e => ({filename: e.filename, state: e.state, path: e.filePath})); """) print("Chrome download records:", downloads)
5. 等待下载完成再关闭Driver
如果脚本在下载未完成时就关闭Driver,.crdownload临时文件会被清理,添加等待逻辑:
import time def wait_for_download(download_path, timeout=60): end_time = time.time() + timeout while time.time() < end_time: crdownload_files = [f for f in os.listdir(download_path) if f.endswith('.crdownload')] if not crdownload_files: finished_files = [f for f in os.listdir(download_path) if not f.startswith('.')] if finished_files: return finished_files[0] time.sleep(1) return None # 触发下载后调用等待函数 finished_file = wait_for_download(download_path) if finished_file: print(f"Downloaded file: {finished_file}") else: print("Download timed out") driver.quit()
内容的提问来源于stack exchange,提问作者BamBurger
相关产品推荐
相关产品推荐

