Files
pbf/tasks/updatedownload.md
2026-03-17 19:48:15 +08:00

264 lines
3.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NavSea Weather Server
Task: WeatherServer_GFS_Subset_Downloader
Architecture: V11
Codex: codex6
Status: TODO
---
# 任务目标
升级现有 gfs_downloader.py
当前问题:
直接下载完整 GFS 文件:
gfs.t00z.pgrb2.0p25.f000
文件大小:
≈ 500MB
下载 72 小时预测需要:
≈ 12GB
这是不可接受的。
解决方案:
使用 NOAA 提供的 GRIB Subset API
filter_gfs_0p25.pl
只下载:
1 指定区域
2 指定变量
3 指定高度层
目标:
将单个 GRIB 文件缩小到:
2MB 10MB
---
# 下载区域
NavSea 天气服务器只需要日本附近区域:
leftlon = 120
rightlon = 150
toplat = 50
bottomlat = 20
覆盖:
日本海
东海
太平洋日本海域
---
# 下载变量
Weather System V1 需要以下变量:
UGRD
VGRD
APCP
PRMSL
TMP
HTSGW
DIRPW
PERPW
说明:
UGRD VGRD → 风
APCP → 降水
PRMSL → 气压
TMP → 温度
HTSGW → 浪高
DIRPW → 浪方向
PERPW → 浪周期
变量参数来自 NOAA GFS 参数列表。 :contentReference[oaicite:0]{index=0}
---
# 下载高度层
需要以下层:
10 m above ground
surface
mean sea level
参数:
lev_10_m_above_ground
lev_surface
lev_mean_sea_level
---
# URL 构造规则
基础地址:
https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl
示例:
https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?
file=gfs.t00z.pgrb2.0p25.f003
&lev_10_m_above_ground=on
&lev_surface=on
&lev_mean_sea_level=on
&var_UGRD=on
&var_VGRD=on
&var_APCP=on
&var_PRMSL=on
&var_TMP=on
&var_HTSGW=on
&var_DIRPW=on
&var_PERPW=on
&leftlon=120
&rightlon=150
&toplat=50
&bottomlat=20
&dir=%2Fgfs.20260312%2F00%2Fatmos
---
# 修改文件
weather_server/downloader/gfs_downloader.py
---
# 新代码
```python
import os
import requests
from datetime import datetime
BASE_URL = "https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl"
OUTPUT_DIR = "data/grib"
FORECAST_HOURS = [
0,3,6,9,12,15,18,21,24,
27,30,33,36,39,42,45,
48,51,54,57,60,63,66,
69,72
]
REGION = {
"leftlon":120,
"rightlon":150,
"toplat":50,
"bottomlat":20
}
VARIABLES = [
"UGRD",
"VGRD",
"APCP",
"PRMSL",
"TMP",
"HTSGW",
"DIRPW",
"PERPW"
]
LEVELS = [
"lev_10_m_above_ground",
"lev_surface",
"lev_mean_sea_level"
]
os.makedirs(OUTPUT_DIR, exist_ok=True)
def get_cycle():
now = datetime.utcnow()
hour = (now.hour // 6) * 6
cycle = f"{hour:02d}"
date = now.strftime("%Y%m%d")
return date, cycle
def build_url(date, cycle, fh):
filename = f"gfs.t{cycle}z.pgrb2.0p25.f{fh}"
params = {
"file": filename,
"leftlon": REGION["leftlon"],
"rightlon": REGION["rightlon"],
"toplat": REGION["toplat"],
"bottomlat": REGION["bottomlat"],
"dir": f"/gfs.{date}/{cycle}/atmos"
}
for v in VARIABLES:
params[f"var_{v}"] = "on"
for l in LEVELS:
params[l] = "on"
return BASE_URL, params
def download_file(url, params, path):
if os.path.exists(path):
print("skip", path)
return
print("downloading", path)
r = requests.get(url, params=params, stream=True)
if r.status_code != 200:
print("failed", r.status_code)
return
with open(path, "wb") as f:
for chunk in r.iter_content(1024*1024):
f.write(chunk)
def main():
date, cycle = get_cycle()
print("cycle:", date, cycle)
for fh in FORECAST_HOURS:
fh_str = f"{fh:03d}"
url, params = build_url(date, cycle, fh_str)
output = os.path.join(
OUTPUT_DIR,
f"{date}_{cycle}_f{fh_str}.grib2"
)
download_file(url, params, output)
if __name__ == "__main__":
main()