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

Python Selenium批量下载文件后driver.quit()失效挂起问题

问题根因

驱动无法退出挂死的核心原因有两个:

  • 下载触发逻辑是异步的:Selenium执行点击下载链接的动作后,Firefox会在后台独立进程中完成文件传输和写入,循环结束时大部分文件并未下载完成。此时调用driver.quit()会等待所有浏览器关联进程(包括正在执行IO的下载进程)退出才会返回,直接进入无限等待状态。
  • 下载配置不全:现有配置仅放行application/force-download类型的自动下载,未覆盖目标站点返回的实际文件MIME类型,可能触发浏览器后台隐藏的下载确认弹窗,阻塞进程退出。
  • 配置写法错误:原代码将service_log_path作为Firefox偏好设置传入,该参数实际是WebDriver初始化参数,传入后不生效,可能导致日志进程异常挂起。
修复方案
  • 补全Firefox下载相关配置,将站点常见的压缩包、数据文件MIME类型加入自动保存列表,避免隐式弹窗阻塞。
  • 新增下载完成检测逻辑:轮询下载目录,通过Firefox下载临时文件(.part后缀)是否全部消失判定下载状态,确认所有文件写入完成后再执行退出操作。
  • 增加进程终止兜底逻辑,退出时先调用常规quit()方法,再强制停止geckodriver服务,避免残留进程挂起。
  • 下载路径必须使用绝对路径,避免相对路径导致的文件检测、下载位置异常。

修正后可正常退出的完整代码如下:

import os
import time
import requests
from bs4 import BeautifulSoup as bs
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By

#step-1: 获取文件列表
# 注意:verify=False仅用于测试,正式环境建议配置站点证书信任
data_url_page = requests.get("https://mft.rrc.texas.gov/link/0e33071d-9891-4009-970c-5aa26da5e31a", verify=False)
files_list = []
soup = bs(data_url_page.content, "lxml")
for table_div in soup.find_all('div', class_='ui-datatable-tablewrapper'):
    files_td = table_div.find_all('td', class_='NameColumn')
    for file_name in files_td:
        if file_name:
            files_list.append(file_name.get_text().strip())

# 替换为本地下载目录的绝对路径
DOWNLOAD_DIR = "/absolute/path/to/your/download/dir/"
os.makedirs(DOWNLOAD_DIR, exist_ok=True)

def wait_all_download_complete(timeout=1800):
    """等待所有文件下载完成,默认超时30分钟兜底"""
    start_time = time.time()
    while time.time() - start_time < timeout:
        # Firefox下载中的文件会以.part为临时后缀
        downloading_files = [f for f in os.listdir(DOWNLOAD_DIR) if f.endswith('.part')]
        if not downloading_files:
            # 二次校验:等待2秒后确认无临时文件,避免小文件写入尾期误判
            time.sleep(2)
            recheck = [f for f in os.listdir(DOWNLOAD_DIR) if f.endswith('.part')]
            if not recheck:
                return True
        time.sleep(3)
    return False

#step-2: 批量下载文件
def http_file_downloader(data_url_files, files_list):
    options = Options()
    options.add_argument("--headless")
    options.set_preference("browser.download.folderList", 2)
    options.set_preference("browser.download.manager.showWhenStarting", False)
    options.set_preference("browser.download.dir", DOWNLOAD_DIR)
    # 补全站点常见文件MIME类型,全部自动保存不弹窗
    auto_save_mime = """
    application/zip,application/x-zip-compressed,application/octet-stream,
    application/x-gzip,text/csv,application/pdf,application/force-download
    """
    options.set_preference("browser.helperApps.neverAsk.saveToDisk", auto_save_mime.replace("\n","").strip())
    driver = webdriver.Firefox(options=options)
    try:
        driver.get(data_url_files)
        # 等待页面列表加载完成
        time.sleep(5)
        for file_name in files_list:
            xpath = f'//a[text()="{file_name}"]'
            elem = driver.find_element(by=By.XPATH, value=xpath)
            elem.click()
            # 点击间隔避免请求过密被站点拦截
            time.sleep(0.5)
        # 等待所有下载完成后再退出
        wait_all_download_complete()
    finally:
        # 双层退出逻辑兜底,避免进程挂起
        try:
            driver.quit()
        except Exception:
            pass
        # 强制停止geckodriver服务,彻底释放所有关联进程
        driver.service.stop()

# 启动下载
http_file_downloader("https://mft.rrc.texas.gov/link/0e33071d-9891-4009-970c-5aa26da5e31a", files_list)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:54:40