使用Python Requests和Selenium下载CSV文件失败求助
解决Requests获取CSV链接返回HTML的问题
问题原因
你遇到的核心问题是会话不共享或获取的不是真实下载链接:
- 网站需要验证会话(比如登录状态、Cookie),Selenium的浏览器会话和Requests的无状态请求不互通,直接用Requests访问链接会被重定向到登录页或返回HTML内容。
- 部分网站的CSV按钮href只是触发JavaScript的占位符,点击后由JS动态生成真实下载链接或发起带参数的请求,直接提取原始href无法拿到有效下载地址。
解决方案
方案1:直接用Selenium完成下载(最简单)
配置浏览器自动下载到指定路径,跳过Requests,完全复用Selenium的会话:
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By import time # 配置Chrome自动下载设置 chrome_options = Options() download_dir = "/Users/me/Documents/" chrome_options.add_experimental_option("prefs", { "download.default_directory": download_dir, "download.prompt_for_download": False, # 不弹出下载提示 "download.directory_upgrade": True, "safebrowsing.enabled": True }) # 初始化浏览器并访问目标网站 driver = webdriver.Chrome(options=chrome_options) driver.get("你的目标网站URL") # 先完成必要操作(比如登录、筛选数据) # ... # 点击CSV按钮触发下载 csv_button = driver.find_element(By.CLASS_NAME, "csv") csv_button.click() # 等待下载完成(根据文件大小调整等待时间) time.sleep(5) driver.quit()
方案2:共享Selenium的Cookie给Requests
提取Selenium浏览器中的会话Cookie,让Requests模拟已验证的会话:
from selenium import webdriver from selenium.webdriver.common.by import By import requests driver = webdriver.Chrome() driver.get("你的目标网站URL") # 完成登录或数据筛选等前置操作 # ... csv_button = driver.find_element(By.CLASS_NAME, "csv") target_url = csv_button.get_attribute("href") # 提取Selenium的Cookie,转换为Requests可用格式 session_cookies = {cookie["name"]: cookie["value"] for cookie in driver.get_cookies()} # 用带Cookie的会话请求链接 session = requests.Session() session.cookies.update(session_cookies) response = session.get(target_url) if response.status_code == 200: # 验证返回内容是否为CSV if "text/csv" in response.headers.get("Content-Type", ""): with open("/Users/me/Documents/meteo-test.csv", "wb") as f: f.write(response.content) else: print("返回内容非CSV,请检查链接或会话状态") driver.quit()
方案3:捕捉真实下载请求(处理动态生成的链接)
如果按钮的href是JS触发的占位符,用Selenium的网络日志捕捉浏览器发起的真实下载请求:
from selenium import webdriver from selenium.webdriver.common.by import By import requests import json # 开启Chrome网络日志记录 chrome_options = webdriver.ChromeOptions() chrome_options.set_capability("goog:loggingPrefs", {"performance": "ALL"}) driver = webdriver.Chrome(options=chrome_options) driver.get("你的目标网站URL") # 完成前置操作 # ... csv_button = driver.find_element(By.CLASS_NAME, "csv") csv_button.click() # 从网络日志中筛选CSV下载链接 download_url = None logs = driver.get_log("performance") for log in logs: log_data = json.loads(log["message"])["message"] if "Network.responseReceived" in log_data["method"]: resp_info = log_data["params"]["response"] # 通过URL后缀或Content-Type判断是否为CSV请求 if ".csv" in resp_info["url"] or "text/csv" in resp_info["headers"].get("Content-Type", ""): download_url = resp_info["url"] break if download_url: # 带上Cookie请求真实下载链接 cookies = {cookie["name"]: cookie["value"] for cookie in driver.get_cookies()} response = requests.get(download_url, cookies=cookies) if response.status_code == 200: with open("/Users/me/Documents/meteo-test.csv", "wb") as f: f.write(response.content) else: print("未捕捉到真实CSV下载链接") driver.quit()
注意事项
- 必须确保在点击CSV按钮前完成网站要求的验证步骤(如登录、人机验证),否则即使拿到链接也会被拦截。
- 若返回的HTML是登录页,说明会话Cookie未正确传递,需检查Cookie提取是否完整。
- 可以通过打印
response.headers查看返回内容的类型,确认是否为text/csv或application/csv。
内容的提问来源于stack exchange,提问作者Alex Fischer
相关产品推荐
相关产品推荐

