全国城市空气质量查询:单城市实时查询集成指南(从请求到 UI 展示)
# 全国城市空气质量查询:单城市实时查询集成指南(从请求到 UI 展示)
> 接口/接入点:全国城市空气质量查询(apiCode=104)· 104-42 单城市查询 · 免费 · POST/GET · 返回 JSON · 适用人群:全栈工程师、产品经理 · 阅读时间:约 8 分钟
## 核心要点
- 104-42 是「按城市名查一条」的接入点,必填 `area`;返回单对象(非数组)。
- 小地区会自动回退到上级主要城市,UI 上应如实展示「实际返回城市」而非用户输入。
- 完整链路:读入城市名 → 调接口 → 判 `ret_code` → 转换字符串数值 → 渲染卡片/播报。
## Why:典型业务场景
天气 App 的「空气」Tab、出行工具的目的地空气提醒、智能家居的空气播报,本质都是「给我某个城市的当前空气」。本篇把一次查询落到一个最小可运行的后端 + 前端渲染闭环。
## What:接口速览
| 项 | 内容 |
|----|------|
| 地址 | `https://route.showapi.com/104-42?appKey={your_appKey}` |
| 必填 | `area`(城市名) |
| 返回 | `showapi_res_body` 单对象(含 aqi/pm2_5/quality 等) |
| 成功判定 | `showapi_res_body.ret_code == 0` |
## How:后端查询 + 前端渲染
### 后端(Python,FastAPI 风格)
```python
import requests
def get_air_quality(city: str, appkey: str) -> dict:
url = "https://route.showapi.com/104-42"
resp = requests.post(
url, params={"appKey": appkey},
data={"area": city}, timeout=10,
).json()
body = resp.get("showapi_res_body", {})
if body.get("ret_code") != 0:
raise RuntimeError(body.get("remark") or "查询失败")
return {
"city": body["area"], # 实际返回城市(可能回退)
"aqi": int(body["aqi"]),
"pm25": int(body["pm2_5"]),
"pm10": int(body["pm10"]),
"quality": body["quality"],
"pollutant": body["primary_pollutant"] or None,
"time": body["ct"],
}
```
### 前端(展示卡片片段)
```html
<div class="aq-card">
<h3>{{ city }} · {{ quality }}</h3>
<p>AQI:{{ aqi }} | PM2.5:{{ pm25 }} μg/m³</p>
<p>首要污染物:{{ pollutant || "无" }}</p>
<small>更新于 {{ time }}</small>
</div>
```
### cURL 速测
```bash
curl -X POST "https://route.showapi.com/104-42?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "area=%E6%89%BF%E5%BE%B7"
```
## 返回示例与解析
查「承德」实测返回 `quality=轻度污染`、`pm2_5=63`、`primary_pollutant=颗粒物(PM10)`;查「双桥镇」这类小地名则返回其上级「承德」的数据(回退)。前端务必用返回体的 `area` 字段显示城市,而非用户原始输入。
## 进阶 / 边界
- **回退提示**:当 `body["area"] != 用户输入` 时,建议 UI 标注「(该地为小地区,展示上级城市 X 的空气质量)」,避免用户误以为数据有误。
- **数值转换**:所有浓度/指数为字符串,渲染前 `int()` 转换;`o3_8h` 可能为 `"_"` 需单独判断。
- **免费额度**:每次查询计 1 额度;高并发或前端直连都会暴露 AppKey **且** 快速耗尽免费档,务必后端代理 + 缓存(见系列第 7 篇)。
## FAQ
**Q1:用户输入「杭州市西湖区」返回了「杭州」?**
是预期的上级城市回退:国家仅公布主要城市监测数据,小地区返回其上级主要城市。
**Q2:前端能直接调接口吗?**
不建议。会把 AppKey 暴露给浏览器,且难以控制免费额度消耗;应由后端代理并加缓存。
**Q3:quality 字段能直接拿来做配色吗?**
可以,但建议统一映射(见系列第 6 篇《空气质量等级判定与配色》),避免各端文案/颜色不一致。
**Q4:ret_code 非 0 一般是什么原因?**
多为 AppKey 无效、无该接口调用权限或参数异常;按 `remark` 提示排查,必要时检查免费档位是否用尽。
## 相关能力 / 下一步阅读
- [全国城市空气质量查询:返回字段全解(AQI/PM2.5/质量等级一文读懂)](https://www.showapi.com/guides/air-quality-response-fields-104)
- [全国城市空气质量查询:城市空气质量排行榜接入与可视化指南](https://www.showapi.com/guides/air-quality-ranking-integration-104)
- [全国城市空气质量查询:在微信小程序 / 智能设备中展示空气质量](https://www.showapi.com/guides/air-quality-miniapp-104)
- **本系列共 11 篇**:查看[全国城市空气质量查询 · 指南总目录](https://www.showapi.com/guides/air-quality-guides-104)