https://cds.climate.copernicus.eu/#!/home
1 注册或登录CDS平台

2 登录后进入User guide


点击API service


在这个Setup the CDS Api key下面找到你的url和key,后面配置时需要。
3 配置API
在“C:\Users\用户名” 下创建一个“.cdsapirc” 文件,创建方法:
先创建一个 “.cdsapirc.txt” 文件,输入下方格式的url和key信息,然后再把 “.txt” 删掉。
url: https://cds.climate.copernicus.eu/api
key: your key
ctrl+R打开cmd,安装cdsapi第三方库,输入:pip install cdsapi
4 下载安装IDM软件
IDM下载官网:https://www.internetdownloadmanager.com
支持付费下载正版,或于CSDN/B站等平台获取安装包。
要记住IDMan.exe的安装路径,后续代码批量下载时需要。
5 批量下载Python脚本
支持多线程,同时加载多个ERA5数据。
如果下载失败,注意检查API配置文件输入的url和key是否正确。
import cdsapiimport osfrom subprocess import callfrom concurrent.futures import ThreadPoolExecutor # 添加线程池支持def idmDownloader(task_url, folder_path, file_name): """ IDM下载器:param task_url: 下载任务地址:param folder_path: 存放文件夹:param file_name: 文件名:return: """# IDM安装目录idm_engine = "D:/IDM/Internet Download Manager/IDMan.exe"# 将任务添加至队列call([idm_engine, '/d', task_url, '/p', folder_path, '/f', file_name, '/a'])# 开始任务队列call([idm_engine, '/s'])# ConfigurationyearStart = 2000yearEnd = 2025grid = 0.25 # 0.25 degree resolution# variable = 'q' # specific humidity# variable = 'sp' # surface pressure# variable = 'e' # evaporation# variable = 'tp' # total precipitation# variable = 'hgt'# variable = 'uwnd'# variable = 'vwnd'# variable = 'wwnd'# variable = 'air'# variable = 'slp'# variable = 'air2m'variable = 'u10m'base_path = r'\data\ERA5'path = os.path.join(base_path, variable) # 存放文件夹# Create output directory if it doesn't existos.makedirs(path, exist_ok=True)# Prepare year and month listsyears = range(yearStart, yearEnd + 1)yr = [str(i) for i in years]months = range(1, 13)mo = [str(j).zfill(2) for j in months]# Pressure levels to downloadpressure_levels = ["1", "3", "5", "7", "10", "30", "50", "70", "100","150", "200", "250", "300", "400", "500", "600","700", "850", "925", "975", "1000"]times = ["00:00", "01:00", "02:00","03:00", "04:00", "05:00","06:00", "07:00", "08:00","09:00", "10:00", "11:00","12:00", "13:00", "14:00","15:00", "16:00", "17:00","18:00", "19:00", "20:00","21:00", "22:00", "23:00"]def download_month(iyr, imo):""" 下载单个月份数据的函数 """year_path = os.path.join(path, str(yr[iyr])) os.makedirs(year_path, exist_ok=True) filename = variable + f'.6h.global.{grid}deg.{yr[iyr]}.{mo[imo]}.nc'#filename = variable + f'.1h.global.{grid}deg.{yr[iyr]}.{mo[imo]}.nc'output_file_path = os.path.join(year_path, filename)if os.path.exists(output_file_path):print(f'File {output_file_path} already exists. Skipping download.')returnprint(f'======= Downloading: {variable} | date: ' + yr[iyr] + '.' + mo[imo] + ' =======')try: c = cdsapi.Client() # 每个线程创建独立的客户端r = c.retrieve('reanalysis-era5-single-levels',# "reanalysis-era5-pressure-levels",{'product_type': 'reanalysis',# "variable": ["geopotential"], # "variable": ["specific_humidity"], # "variable": ["evaporation"], # "variable": ["total_precipitation"], # "variable": ["surface_pressure"], # "variable": ["u_component_of_wind"], # "variable": ["v_component_of_wind"], # "variable": ["temperature"], # "variable": ["vertical_velocity"], # "variable": ["2m_temperature"], #"variable": ["mean_sea_level_pressure"],"variable": ["10m_u_component_of_wind"],'year': yr[iyr],'month': mo[imo],'day': ['01', '02', '03', '04', '05', '06','07', '08', '09', '10', '11', '12','13', '14', '15', '16', '17', '18','19', '20', '21', '22', '23', '24','25', '26', '27', '28', '29', '30','31'],"time": ["00:00", "06:00", "12:00", "18:00"],#"time": times, # "pressure_level": pressure_levels,'format': 'netcdf',"download_format": "unarchived",'grid': [grid, grid], # 0.25° resolution}) url = r.location # 获取文件下载地址idmDownloader(url, year_path, filename) # 添加进IDM中下载except Exception as e:print(f"Error downloading {variable} for {yr[iyr]}-{mo[imo]}: {str(e)}")# 将错误信息写入日志文件with open(os.path.join(path, "download_errors.log"), 'a') as f: f.write(f"{variable}_{yr[iyr]}-{mo[imo]}: {str(e)}\n")return# 创建线程池控制并发数max_workers = 2 # 设置最大并发线程数tasks = [(i, j) for i in range(len(yr)) for j in range(len(mo))] # 生成所有任务参数with ThreadPoolExecutor(max_workers=max_workers) as executor:# 使用lambda解包参数元组executor.map(lambda params: download_month(*params), tasks)print("所有下载任务已添加到IDM队列!请检查IDM开始下载。")