You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Selenium使用Pool多进程下载时如何获取各进程对应文件路径

多进程池Chromium下载冲突解决方案

现有逻辑只适用于单进程独占下载目录的场景,多进程共用目录时会出现两个核心问题:一是全局扫描.crdownload后缀无法区分归属进程,二是按创建时间取最新文件的逻辑在并发完成时会匹配错误。可以通过以下两种方案解决:

方案1:为每个进程分配独立下载目录(最推荐)

该方案实现成本最低,无任何冲突概率,适配headless Chromium的配置逻辑:

  • 每个子进程启动后,生成唯一的临时下载目录,可通过进程ID、UUID拼接目录名,示例:tmp_download_dir = f"./tmp_download_{os.getpid()}",创建目录后即可使用
  • 初始化当前进程的Chromium实例时,单独配置prefs中的download.default_directory为上述专属临时目录
  • 原有download_wait、last_downloaded_file逻辑无需修改,因为目录为当前进程独占,不会出现其他进程的文件干扰
  • 下载完成后将目标文件移动到全局存储目录,再删除临时目录释放空间即可

方案2:共用全局下载目录的适配方案

如果业务要求必须使用同一个下载目录,可从下载任务绑定层面改造逻辑:

优化思路

放弃全局扫描后缀+匹配最新创建时间的模糊逻辑,直接将下载任务和对应的文件绑定,可通过两种方式实现:

  • 对接Chromium DevTools协议监听下载事件:开启Chromium的远程调试能力,触发下载前注册监听回调,可直接获取当前下载任务的文件名、进度、完成状态,无需扫描目录。如果使用上层封装工具,可直接调用对应接口:
    • Selenium4+ 支持直接获取下载任务对象
    • Playwright可通过expect_download接口直接等待当前触发的下载完成,示例:
      with page.expect_download() as download_info:
          page.locator("#download_btn").click()
      download = download_info.value
      # 直接获取当前下载的文件路径,完全不会和其他进程的任务冲突
      file_path = download.path()
      
  • 改造原有轮询逻辑:如果暂时不想对接DevTools,可修改原有函数,先捕获当前进程触发的专属临时下载文件,再等待其下载完成,改造后代码示例:
import os
import time

def download_wait(path_to_downloads):
    # 记录触发下载前已有的临时文件,过滤不属于当前任务的下载
    pre_exist_cr = set(f for f in os.listdir(path_to_downloads) if f.endswith('.crdownload'))
    wait_seconds = 0
    target_cr = None
    # 先等待当前任务的临时下载文件出现
    while not target_cr and wait_seconds < 30:
        time.sleep(0.5)
        cur_cr = set(f for f in os.listdir(path_to_downloads) if f.endswith('.crdownload'))
        new_cr = cur_cr - pre_exist_cr
        if len(new_cr) == 1:
            target_cr = new_cr.pop()
        wait_seconds += 0.5
    if not target_cr:
        raise TimeoutError("未检测到下载任务启动")
    # 仅等待当前任务的临时文件消失,代表下载完成
    wait_seconds = 0
    while wait_seconds < 270:
        time.sleep(1)
        if target_cr not in os.listdir(path_to_downloads):
            break
        wait_seconds += 1
    else:
        raise TimeoutError("下载超时")
    # 直接返回对应目标文件名,无需匹配创建时间
    target_file = target_cr.rsplit('.crdownload', 1)[0]
    print(f'文件 {target_file} 下载完成,耗时 {wait_seconds + 30} 秒')
    return target_file

注意:如果业务本身会返回同名文件,可在下载完成后给文件名拼接进程ID、任务ID等唯一标识,避免文件覆盖。

内容的提问来源于stack exchange,提问作者Razilator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:54:06