寻求优于Selenium的Python指定网站文件下载方案
问题描述
我尝试从以下网站下载文件:
https://www.coordinador.cl/operacion/documentos/registro-de-instrucciones-de-operacion-rio-sscc-energia/
目前用Selenium选择日期并点击下载按钮,但直接用wget访问下载链接会返回403错误,看起来下载链接会重定向到AWS S3,没法直接用wget。有没有更优的实现方式?(我没有AWS相关经验,不知道怎么处理)
我的代码如下:
from selenium import webdriver from selenium.webdriver.common.by import By import time driver = webdriver.Chrome() driver.get('https://www.coordinador.cl/operacion/documentos/registro-de-instrucciones-de-operacion-rio-sscc-energia/') fini=driver.find_element(by='id',value='energia-inicio') fini.click() cal_ini=driver.find_element(By.CSS_SELECTOR,value='a.ui-state-default.ui-state-highlight') cal_ini.click() fini=driver.find_element(by='id',value='energia-termino') fini.click() cal_fin=driver.find_element(By.CSS_SELECTOR,value='a.ui-state-default.ui-state-highlight') cal_fin.click() downloadcsv=driver.find_element(By.CSS_SELECTOR,value='a.cen_btn.cen_btn-primary.download-energia') downloadcsv.click() time.sleep(30) driver.close()
更优实现方式
不需要AWS权限,问题出在S3的预签名链接需要和请求时的Cookie、请求头匹配,直接wget不带这些信息会被拒绝。以下是两种可行方案:
方案一:从Selenium中获取真实下载链接,用requests带Cookie请求
保留Selenium的日期选择逻辑,但跳过浏览器下载步骤,直接提取下载链接后用requests库带上浏览器会话信息请求,大幅减少等待开销:
from selenium import webdriver from selenium.webdriver.common.by import By import requests driver = webdriver.Chrome() driver.get('https://www.coordinador.cl/operacion/documentos/registro-de-instrucciones-de-operacion-rio-sscc-energia/') # 执行日期选择逻辑 fini = driver.find_element(by='id', value='energia-inicio') fini.click() cal_ini = driver.find_element(By.CSS_SELECTOR, value='a.ui-state-default.ui-state-highlight') cal_ini.click() fini = driver.find_element(by='id', value='energia-termino') fini.click() cal_fin = driver.find_element(By.CSS_SELECTOR, value='a.ui-state-default.ui-state-highlight') cal_fin.click() # 获取下载链接与浏览器会话Cookie download_btn = driver.find_element(By.CSS_SELECTOR, value='a.cen_btn.cen_btn-primary.download-energia') download_url = download_btn.get_attribute('href') cookies = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()} # 关闭浏览器 driver.quit() # 用requests发起下载请求,带上Cookie和模拟浏览器的请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' } response = requests.get(download_url, cookies=cookies, headers=headers, stream=True) with open('energia_data.csv', 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk)
方案二:直接模拟接口请求,完全绕过Selenium
通过浏览器开发者工具分析网站的下载接口,直接用requests构造请求,无需启动浏览器:
- 打开浏览器F12,切换到「Network」标签,点击下载按钮,找到触发的接口请求(通常是GET或POST类型)
- 复制请求的URL、请求头(Headers)和参数(Params/Form Data)
- 用requests构造相同请求,带上必要的Cookie和参数直接下载文件
示例代码(需替换为实际分析出的接口信息):
import requests headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Referer': 'https://www.coordinador.cl/operacion/documentos/registro-de-instrucciones-de-operacion-rio-sscc-energia/' } # 从浏览器会话中复制必要的Cookie字段(如会话ID) cookies = { 'session_id': 'xxx', 'csrf_token': 'xxx' } # 替换为实际需要的日期参数 params = { 'start_date': '2024-01-01', 'end_date': '2024-01-31' } response = requests.get('https://www.coordinador.cl/api/energia/download', params=params, cookies=cookies, headers=headers, stream=True) with open('energia_data.csv', 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk)
注意事项
- S3预签名链接有有效期(一般几分钟),需获取后立即使用
- 网站Cookie可能会过期,需定期更新或保持会话有效性
- 方案一比原Selenium代码更高效,方案二是资源消耗最低的实现方式,但需要一定的接口分析能力
内容的提问来源于stack exchange,提问作者XaniloM
相关产品推荐
相关产品推荐

