天气预报国际版:24 小时预报接入实战(逐小时天气卡片与出行提醒)
# 天气预报国际版:24 小时预报接入实战(逐小时天气卡片与出行提醒)
> 接口:天气预报国际版(apiCode=3540)接入点 2 查询24小时预报 · 免费接口 · POST/GET · JSON · 适用人群:全栈工程师、出行类产品经理 · 阅读时间:约 7 分钟
## 核心要点
- 接入点 `3540-2` 返回 `hourList` 逐小时预报数组,字段与当前天气的 `now` 高度一致,另多一个 `snow`(降雪量),但没有 `air_quality`。
- `hourList[].time` 是**目标城市当地时间**(如曼谷 `2026-09-03 14:00`),做逐时曲线或"未来 N 小时"提醒时必须按当地时间对齐。
- 实测单次返回覆盖从当前小时起的逐时段数据,配合 `rain_prop` 可直接实现"几小时内有雨提醒"。
## Why
"今天下午会不会下雨""傍晚跑步合适吗""接机时需不需要伞"——这类问题的答案都藏在逐小时预报里。日级预报太粗,当前天气又不够看,24 小时颗粒度刚好覆盖"今天剩下的时间"的决策需求。
本文带你把 `hourList` 变成逐时天气组件与降雨提醒逻辑,代码经真实接口实测(曼谷)。
## What
| 项目 | 说明 |
|------|------|
| 接口地址 | `https://route.showapi.com/3540-2?appKey={your_appKey}` |
| 接入点 | [查询24小时预报(3540-2)](https://www.showapi.com/apiGateway/view/3540/2) |
| 请求方式 | POST / GET,返回 JSON |
| 定位参数 | `name` 或 `lon`+`lat`(二选一) |
| 核心返回 | `cityInfo` + `hourList[]`(逐小时) |
| 计费 | 免费接口(防滥用档次限制) |
`hourList[]` 单项主要字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `time` | String | 小时时间(当地时间,如 `2026-09-03 14:00`) |
| `temperature` / `feels_like` | Number | 气温 / 体感(℃) |
| `weather` / `weather_en` | String | 天气现象(中/英) |
| `rain_prop` / `snow_prob` | Number | 降雨概率 / 降雪概率(%) |
| `snow` | Number | 降雪量 |
| `humidity` | Number | 湿度(%) |
| `wind_speed` / `gust_speed` | Number | 持续风速 / 阵风风速(m/s) |
| `wind_direction` / `wind_direction_en` | String | 风向(中/英) |
| `cloud` | Number | 云层覆盖率(%) |
| `visibility` | Number | 能见度(km) |
| `uv` | Number | 紫外线指数 |
| `pressure` / `dew_point` | Number | 大气压 / 露点温度 |
| `windchill` / `heat_index` | Number | 风寒指数 / 热指数 |
| `short_rad` / `diff_rad` / `dni` / `gti` | Number | 辐射类字段(W/m²) |
## How
### 1. 拉取逐时预报并生成"未来 N 小时"提醒
Python:
```python
# pip install requests
import requests
APPKEY = "YOUR_APPKEY"
def fetch_hourly(city: str) -> list:
resp = requests.post(
"https://route.showapi.com/3540-2",
params={"appKey": APPKEY, "name": city},
timeout=10,
)
body = resp.json()["showapi_res_body"]
if body.get("ret_code") != 0:
raise RuntimeError(f"业务错误: {body.get('remark')}")
return body["cityInfo"], body["hourList"]
def rain_alert(hours: list, window: int = 6, threshold: int = 40) -> str:
"""未来 window 小时内降雨概率超阈值则提醒。"""
for h in hours[:window]:
if (h.get("rain_prop") or 0) >= threshold:
return f'{h["time"]} 前后可能下雨({h["weather"]},概率 {h["rain_prop"]}%),记得带伞'
return f"未来 {window} 小时无明显降雨迹象"
info, hours = fetch_hourly("bangkok")
print(f'{info["city"]}({info["time_zone"]})未来逐时:')
for h in hours[:5]:
print(f' {h["time"]} {h["temperature"]}℃ {h["weather"]} 降雨{h["rain_prop"]}%')
# 实测输出示例(曼谷):
# 2026-09-03 14:00 36.5℃ 多云 降雨8%
# 2026-09-03 15:00 34.9℃ 阴天 降雨9%
print(rain_alert(hours))
```
cURL:
```bash
curl -X POST "https://route.showapi.com/3540-2?appKey=YOUR_APPKEY&name=bangkok"
```
Node.js:
```js
const res = await fetch(
`https://route.showapi.com/3540-2?appKey=${process.env.APPKEY}&name=bangkok`,
{ method: "POST" }
);
const body = (await res.json()).showapi_res_body;
if (body.ret_code !== 0) throw new Error(body.remark);
for (const h of body.hourList.slice(0, 5)) {
console.log(`${h.time} ${h.temperature}℃ ${h.weather}`);
}
```
### 2. 渲染逐时天气横条(前端片段)
```html
<div class="hourly-bar">
<div class="hour" v-for="h in hourList" :key="h.time">
<span class="t">{{ h.time.slice(11, 16) }}</span> <!-- 只取 HH:mm,已是当地时间 -->
<span class="icon">{{ h.weather }}</span>
<span class="temp">{{ h.temperature }}℃</span>
<span class="rain" :class="{ warn: h.rain_prop >= 40 }">{{ h.rain_prop }}%</span>
</div>
</div>
```
## 返回示例与解析
实测(name=bangkok,3540-2)节选:
```json
{
"showapi_res_body": {
"remark": "查询成功",
"ret_code": 0,
"cityInfo": { "city": "曼谷", "city_en": "Bangkok", "time_zone": "Asia/Bangkok", "localtime": "2026-09-03 14:46:01" },
"hourList": [
{ "time": "2026-09-03 14:00", "temperature": 36.5, "feels_like": 36.2, "weather": "多云",
"weather_en": "Cloudy", "rain_prop": 8, "humidity": 37, "wind_speed": 5.3,
"cloud": 85, "uv": 9.4, "short_rad": 938.38, "snow": 0 },
{ "time": "2026-09-03 15:00", "temperature": 34.9, "weather": "阴天", "rain_prop": 9 }
]
}
}
```
- `hourList` 按时间升序排列,第一项即为最近整点;
- 逐时 UV 也在(曼谷 14 时 `uv=9.4`),可做"紫外线最强时段"提示;
- 逐时辐射字段同样存在,解读见[辐射与 UV 解读](https://www.showapi.com/guides/global-weather-radiation-uv-3540)。
## 进阶与边界
- **时区陷阱(最重要)**:`time` 是当地时间。如果你的用户在东八区而查询的是伦敦,"14:00"不是北京时间 14 点。需要跨时区对齐时,用 `cityInfo.time_zone`(IANA 时区名)在代码中换算。
- **无空气质量**:`hourList` 不含 `air_quality`,需要 AQI 请另调 3540-1。
- **`dni`/`gti` 实测为 0**:曼谷正午 `short_rad=938.38` 但 `dni=0`、`gti=0`,与当前天气接入点实测现象一致,辐射字段使用前先看[该文实测观察](https://www.showapi.com/guides/global-weather-radiation-uv-3540)。
- **数组长度**:文档定位为 24 小时预报,业务代码对数组长度做防御(少于 24 条也能正常渲染),不要硬断言。
## FAQ
**Q1:`hourList` 第一个元素一定是"下一个整点"吗?**
实测第一项为最近的整点预报(如 14:46 调用,首项 `time=14:00`)。它是预报值,与 3540-1 的当前实况含义不同,"现在"的展示请用 3540-1。
**Q2:怎么把当地时间转成用户本地时间?**
用 `cityInfo.time_zone`(如 `Asia/Bangkok`)做 IANA 时区换算。前端可用 `Intl.DateTimeFormat` 指定 `timeZone` 后展示。
**Q3:降雪量 `snow` 的单位是什么?**
文档未标注 `snow` 的单位(14 天预报中的 `total_snow` 单位标注为 cm),本文不对 24 小时 `snow` 的单位做无依据断言;用前建议抽样观察量级。
**Q4:为什么逐时的 `uv` 白天高、晚上是 0?**
`uv` 是紫外线指数,随太阳高度变化。实测曼谷 14 时 `uv=9.4`、17 时 `uv=0.4`,符合规律,可放心用于防晒提醒。
**Q5:能查"过去 24 小时"吗?**
文档定位是"24 小时天气预报"(未来),未提供历史小时数据能力。
## 下一步阅读
- [天气预报国际版:14 天预报接入实战(行程规划与日出日落、月相字段)](https://www.showapi.com/guides/global-weather-14day-forecast-3540)
- [天气预报国际版:当前天气接入实战(气温、体感、风、降水概率全字段)](https://www.showapi.com/guides/global-weather-current-weather-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)