天气预报国际版:14 天预报接入实战(行程规划与日出日落、月相字段)
# 天气预报国际版:14 天预报接入实战(行程规划与日出日落、月相字段)
> 接口:天气预报国际版(apiCode=3540)接入点 3 查询14天预报 · 免费接口 · POST/GET · JSON · 适用人群:旅行/户外类应用开发者 · 阅读时间:约 7 分钟
## 核心要点
- 接入点 `3540-3` 返回 `dayList` 逐日预报:温幅、降水、风、紫外线之外,还带**日出日落与月相组字段**(月相/月出/月落/月光亮度),这是做旅行行程页的现成素材。
- 实测避坑:`moonrise` 在"当天月亮不出"时会返回字符串 `Does not rise today` 而非时间,解析必须容错。
- 文档字段表中 `moonset` 描述误写为"日落时间",实际为**月落时间**(与 `moonrise` 月出对应);本文按实测口径说明。
## Why
规划一次两周内的旅行、安排一场户外婚礼、决定哪天去露营——你需要的不只是"晴天还是下雨",还有温幅够不够舒适、日出几点(看日出要赶早)、月相如何(观星/拍月亮)。14 天预报接入点把这些信息一次给齐,日级字段设计明显偏向"行程决策"场景。
本文以实测数据(东京)走一遍完整接入,并重点提示月相字段的容错点。
## What
| 项目 | 说明 |
|------|------|
| 接口地址 | `https://route.showapi.com/3540-3?appKey={your_appKey}` |
| 接入点 | [查询14天预报(3540-3)](https://www.showapi.com/apiGateway/view/3540/3) |
| 请求方式 | POST / GET,返回 JSON |
| 定位参数 | `name` 或 `lon`+`lat`(二选一) |
| 核心返回 | `cityInfo` + `dayList[]`(逐日) |
| 计费 | 免费接口(防滥用档次限制) |
`dayList[]` 单项主要字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `date` | String | 日期(`2026-09-03`) |
| `temperature` | Number | 平均气温 |
| `max_temperature` / `min_temperature` | Number | 最高 / 最低气温(℃) |
| `weather` / `weather_en` | String | 天气现象(中/英) |
| `rain_prop` / `snow_prob` | Number | 降雨概率 / 降雪概率(%) |
| `total_precip` / `total_snow` | Number | 总降水量(mm)/ 总降雪量(cm) |
| `humidity` | Number | 湿度(%) |
| `max_wind_speed` | Number | 最大风速 |
| `visibility` / `uv` | Number | 能见度(km)/ 紫外线指数 |
| `sunrise` / `sunset` | String | 日出 / 日落时间(如 `05:14` / `18:06`) |
| `moon_phase` / `moon_phase_en` | String | 月相(中/英,如"下弦月"/`Last Quarter`) |
| `moonrise` / `moonset` | String | 月出 / 月落时间(**实测可能有非时间值**) |
| `moon_illumination` | Number | 月光亮度 |
## How
### 1. 拉取 14 天预报并挑出"最适合户外的日子"
Python:
```python
# pip install requests
import requests
APPKEY = "YOUR_APPKEY"
def fetch_14d(city=None, lon=None, lat=None) -> dict:
params = {"appKey": APPKEY}
if lon and lat:
params.update({"lon": lon, "lat": lat})
elif city:
params["name"] = city
resp = requests.post("https://route.showapi.com/3540-3",
params=params, timeout=10)
body = resp.json()["showapi_res_body"]
if body.get("ret_code") != 0:
raise RuntimeError(f"业务错误: {body.get('remark')}")
return body["cityInfo"], body["dayList"]
def outdoor_score(d: dict):
"""简单的户外适宜度打分:雨越小、温幅越温和越好(示例规则,按需调整)。"""
rain = d.get("rain_prop") or 0
spread = (d.get("max_temperature") or 0) - (d.get("min_temperature") or 0)
return rain * -1 + (30 - abs(spread - 8)) * -1 # 示例:示例性权重,非官方口径
info, days = fetch_14d(lon="139.69", lat="35.69") # 东京
print(f'{info["city"]}({info["time_zone"]})未来天气:')
for d in days[:5]:
print(f' {d["date"]} {d["min_temperature"]}~{d["max_temperature"]}℃ {d["weather"]} '
f'降雨{d["rain_prop"]}% 日出{d["sunrise"]} 日落{d["sunset"]} 月相{d["moon_phase"]}')
# 实测输出示例(东京 2026-09-03):
# 2026-09-03 25.2~32.4℃ 阴天 降雨67% 日出05:14 日落18:06 月相下弦月
```
cURL:
```bash
curl -X POST "https://route.showapi.com/3540-3?appKey=YOUR_APPKEY&lon=139.69&lat=35.69"
```
Node.js(含 `moonrise` 容错):
```js
const res = await fetch(
`https://route.showapi.com/3540-3?appKey=${process.env.APPKEY}&name=tokyo`,
{ method: "POST" }
);
const body = (await res.json()).showapi_res_body;
if (body.ret_code !== 0) throw new Error(body.remark);
for (const d of body.dayList.slice(0, 5)) {
// 实测:当天月亮不升时 moonrise === "Does not rise today",必须容错
const moonrise = /^\d{2}:\d{2}$/.test(d.moonrise || "") ? d.moonrise : "—";
console.log(`${d.date} ${d.min_temperature}~${d.max_temperature}℃ ${d.weather} 月出:${moonrise}`);
}
```
### 2. 行程页展示建议
- 前 3 天展示逐日卡片(温幅 + 现象 + 降雨概率),第 4 天起可收起为温度曲线;
- 日出日落做成"白天时长"辅助信息:`sunset - sunrise`(东京实测约 13 小时);
- 月相 + `moon_illumination` 组合适用于观星/摄影人群提示(实测"下弦月、亮度 50%")。
## 返回示例与解析
实测(lon=139.69, lat=35.69 东京,3540-3)节选:
```json
{
"showapi_res_body": {
"remark": "查询成功",
"ret_code": 0,
"cityInfo": { "city": "London", "time_zone": "Europe/London" },
"dayList": [
{ "date": "2026-09-03", "max_temperature": 32.4, "min_temperature": 25.2,
"temperature": 28.3, "weather": "阴天", "weather_en": "Overcast",
"rain_prop": 67, "total_precip": 2.13, "humidity": 70,
"max_wind_speed": 6.8, "uv": 8.3, "visibility": 10,
"sunrise": "05:14", "sunset": "18:06",
"moon_phase": "下弦月", "moon_phase_en": "Last Quarter",
"moonrise": "21:05", "moonset": "11:10", "moon_illumination": 50 }
]
}
}
```
> 注:实测经纬度(东京坐标)查询时 `cityInfo` 解析到的城市与预期存在出入(返回 London),这正是[定位参数](https://www.showapi.com/guides/global-weather-location-params-3540)文中强调的"用 `cityInfo` 对账解析结果"的意义——业务上发现解析城市不对,就换城市名方式或核对坐标。
## 进阶与边界
- **`moonrise` 容错(实测)**:东京 2026-09-07 实测 `moonrise="Does not rise today"`(当天月亮不升)。正则校验 `HH:mm` 格式后再当时间用。
- **`moonset` 是月落不是日落**:文档字段表把它误描述为"日落时间",日落是 `sunset`;`moonset` 与 `moonrise` 对应,为月落时间。
- **预报仅供参考**:14 天尺度的预报不确定性随天数增加,建议 UI 上标注"预报仅供参考",远期天数不做强承诺(如不自动按预报取消行程)。
- **远期字段可能缺失**:`total_precip`/`total_snow`/`snow_prob` 等在部分日期可能为空,判空处理。
## FAQ
**Q1:`dayList` 一定有 14 条吗?**
文档定位为 14 天预报。业务代码按数组实际长度渲染,对少于 14 条做降级展示,不做硬断言。
**Q2:`temperature` 和 `max/min_temperature` 什么关系?**
`temperature` 是当日平均气温,`max/min` 是最高最低。做温幅展示用 max/min,做"整体冷暖"参考用平均。
**Q3:月相字段能用来做观星提示吗?**
可以:`moon_phase` + `moon_illumination`(月光亮度)组合是现成素材。实测"下弦月、亮度 50%"。注意 `moonrise` 要容错(可能返回 "Does not rise today")。
**Q4:`total_precip` 单位是毫米吗?**
是,文档标注总降水量单位为 mm(`total_snow` 为 cm)。实测东京 09-04 `total_precip=35.84`,配合 `rain_prop=90%` 使用。
**Q5:日出日落时间是当地时间吗?**
是,与 `cityInfo.time_zone` 对应(东京 `05:14/18:06`)。跨时区展示时注意换算。
## 下一步阅读
- [天气预报国际版:24 小时预报接入实战(逐小时天气卡片与出行提醒)](https://www.showapi.com/guides/global-weather-hourly-forecast-3540)
- [天气预报国际版:定位参数怎么传(城市名 name 与经纬度 lon/lat 的选择)](https://www.showapi.com/guides/global-weather-location-params-3540)
- [天气预报国际版:返回字段全解(cityInfo / now / hourList / dayList 一文读懂)](https://www.showapi.com/guides/global-weather-response-fields-3540)
- **本系列共 12 篇**:查看[天气预报国际版指南总目录](https://www.showapi.com/guides/global-weather-guides-3540)