Python结合Headless Chrome下载文件时出现停滞问题
解决Headless Chrome(Canary)在Mac上停滞无法下载CSV的问题
我之前也碰到过类似的情况——用Headless Chrome爬老旧网站触发CSV下载时卡住,尤其是在Mac搭配Jupyter的环境里。结合你已经配置过相关设置但仍失效的情况,大概率是Headless模式的兼容性、老旧网站的JS逻辑或者Jupyter环境的特殊性导致的,给你几个针对性的解决方案:
1. 切换到新版Headless模式(关键!)
旧版的Headless Chrome和正常Chrome的行为差异很大,很多下载相关的API支持不完善,而Canary版本已经支持新版Headless模式,完全模拟正常Chrome的运行逻辑。
修改你的ChromeOptions配置,把旧的--headless替换成:
chrome_options.add_argument("--headless=new")
同时记得指定Canary的二进制文件路径(避免和普通Chrome混淆):
chrome_options.binary_location = "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
2. 完善下载偏好配置(针对Mac权限和老旧网站)
Mac上的文件系统权限、老旧网站的安全标记都可能阻止下载,更新你的prefs配置:
import os download_dir = "/Users/你的用户名/Documents/scraped_csv" # 用绝对路径,避免Jupyter路径混乱 os.makedirs(download_dir, exist_ok=True) # 确保目录存在 prefs = { "download.default_directory": download_dir, "download.prompt_for_download": False, "download.directory_upgrade": True, "profile.default_content_setting_values.automatic_downloads": 1, # 允许自动下载 "safebrowsing.enabled": True # 跳过老旧网站的安全警告拦截 } chrome_options.add_experimental_option("prefs", prefs)
另外加上两个解决Mac权限问题的参数:
chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-dev-shm-usage")
3. 修复老旧网站的点击触发逻辑
很多老旧网站用的是老式的onclick事件或者自定义JS绑定,Selenium默认的click()方法可能无法正确触发下载。改用JS模拟点击:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By # 等待元素可点击后,用JS触发点击 download_btn = WebDriverWait(driver, 15).until( EC.element_to_be_clickable((By.ID, "download-button-id")) # 替换成你实际的元素定位 ) driver.execute_script("arguments[0].click();", download_btn)
这里一定要用WebDriverWait代替time.sleep(),确保元素完全加载后再操作。
4. Jupyter环境的额外检查
Jupyter的运行环境可能和你本地终端的环境不一致,要确保:
- Selenium安装的版本和Canary版本兼容(可以用
pip install --upgrade selenium更新到最新版) - 下载目录有写入权限:避免用相对路径,直接指定绝对路径,比如上面的
/Users/你的用户名/Documents/scraped_csv - 如果Jupyter是用conda环境运行的,要确认Selenium是安装在当前conda环境里的
完整示例代码
把上面的配置整合起来,完整的脚本大概是这样:
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By import os import time # 配置Chrome Options chrome_options = Options() chrome_options.binary_location = "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary" chrome_options.add_argument("--headless=new") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-dev-shm-usage") # 设置下载目录和偏好 download_dir = "/Users/你的用户名/Documents/scraped_csv" os.makedirs(download_dir, exist_ok=True) prefs = { "download.default_directory": download_dir, "download.prompt_for_download": False, "download.directory_upgrade": True, "profile.default_content_setting_values.automatic_downloads": 1, "safebrowsing.enabled": True } chrome_options.add_experimental_option("prefs", prefs) # 初始化Driver driver = webdriver.Chrome(options=chrome_options) try: # 打开目标网站 driver.get("https://你的老旧网站地址") # 第一步点击操作(替换成你实际的元素定位) step1_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, "step1-btn")) ) driver.execute_script("arguments[0].click();", step1_btn) # 第二步点击操作 step2_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CLASS_NAME, "step2-btn")) ) driver.execute_script("arguments[0].click();", step2_btn) # 等待下载完成:检查目标文件是否出现在下载目录 target_filename = "data.csv" # 替换成网站实际的下载文件名 file_path = os.path.join(download_dir, target_filename) timeout = 30 start_time = time.time() while not os.path.exists(file_path): if time.time() - start_time > timeout: raise TimeoutError("下载超时,请检查网站逻辑或延长超时时间") time.sleep(1) print(f"CSV文件已成功下载到:{file_path}") finally: # 确保Driver关闭 driver.quit()
排查技巧
如果还是不行,可以试试这些方法定位问题:
- 临时关闭Headless模式,用正常的Canary浏览器运行脚本,看看能不能成功下载——如果可以,说明是Headless模式的配置问题;如果不行,就是网站本身的逻辑需要调整
- 添加日志参数
chrome_options.add_argument("--enable-logging --v=1"),运行后查看Chrome的日志,找下载相关的报错信息 - 检查老旧网站的网络请求,看看下载链接是不是需要额外的Cookie或者请求头,Selenium是否正确携带了这些信息
内容的提问来源于stack exchange,提问作者Gideon
相关产品推荐
相关产品推荐

