广告位 · 页头(后台-模块管理-新建模块后替换此区域)

如何通过城市名称调用OpenWeatherMap API获取实时天气数据?

OpenWeatherMap 的 Current Weather Data 接口是获取实时天气最常用的入口,它支持按城市名称、城市 ID、坐标和邮政编码查询。按城市名称查询时,服务端会先借助地理编码把传入的 q 参数解析为经纬度,再返回该位置的天气实况。换句话说,你不需要自己维护一张城市坐标表,只要拼对请求参数,就能把天气数据取回来。本文会先说明接口参数和返回结构,再给出可运行的调用代码。

如何通过城市名称调用OpenWeatherMap API获取实时天气数据?

一、请求地址与参数组合

实时天气接口的地址固定为 https://api.openweathermap.org/data/2.5/weather。该接口要求至少携带 q 和 appid 两个参数,其中 q 表示城市名称,appid 是你在 OpenWeatherMap 后台创建应用后获得的 API 密钥。免费账号通常可以满足个人项目和小型脚本调用,但存在每分钟请求次数限制,开发时要做好错误重试和缓存。

城市名称参数可以直接写英文城市名,例如 q=Beijing 或 q=London。如果担心重名,可以追加国家代码,写成 q=Beijing,CN 或 q=London,UK。OpenWeatherMap 也支持中文城市名,但英文名和拼音的返回稳定性更高,建议优先使用后两者。

除了 q 和 appid,还有两个参数会直接影响展示结果。units 控制温度单位,可选 standard、metric、imperial,分别对应开尔文、摄氏度和华氏度。lang 控制天气描述语言,传入 zh_cn 可以返回中文描述,传入 en 或留空则使用英文。一个完整的请求地址如下:

https://api.openweathermap.org/data/2.5/weather?q=Beijing&appid=YOUR_API_KEY&units=metric&lang=zh_cn

这里 YOUR_API_KEY 需要替换成自己的密钥。免费版不支持将所有参数写死在前端页面,因为密钥一旦暴露很容易被他人盗用,更稳妥的方式是让后端服务器转发请求,或把密钥放在环境变量里。

二、响应结构与字段含义

请求成功时,接口会返回一个 JSON 对象,字段覆盖天气现象、温度、湿度、气压、风、云量以及城市信息。下面是一个按北京查询并设置 units=metric、lang=zh_cn 后的简化响应:

{
  "coord": { "lon": 116.3972, "lat": 39.9075 },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "晴",
      "icon": "01d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 28.15,
    "feels_like": 27.32,
    "temp_min": 26.89,
    "temp_max": 30.12,
    "pressure": 1006,
    "humidity": 35
  },
  "visibility": 10000,
  "wind": { "speed": 4.63, "deg": 150 },
  "clouds": { "all": 0 },
  "dt": 1716000000,
  "sys": { "country": "CN", "sunrise": 1715980000, "sunset": 1716030000 },
  "timezone": 28800,
  "id": 1816670,
  "name": "Beijing",
  "cod": 200
}

最常用的字段集中在 weather 和 main 两个对象。weather 是一个数组,通常取第一项即可,其中 description 是经过 lang 参数处理后的天气描述,main 则是固定的天气类别,如 Clear、Clouds、Rain、Snow。主温度数据在 main.temp,而 feels_like 表示体感温度,temp_min 和 temp_max 是短时最低和最高温度。

其他字段也有明确用途。main.humidity 是相对湿度百分比,main.pressure 是海平面气压,单位是 hPa。wind.speed 在 metric 单位下为米每秒,clouds.all 表示云量百分比。dt 是 Unix 时间戳,配合 timezone 的秒偏移可以换算成当地时间。sys.sunrise 和 sys.sunset 也使用时间戳表示日出日落,城市基础信息则放在 name 和 sys.country 中。

如果启用了中文语言,天气描述会直接返回中文,但 main 字段仍然保持英文。因此如果页面上要展示图标或按类别做逻辑判断,建议使用 weather[0].main,不要依赖中文描述来做 if 判断,避免语言切换后逻辑失效。

三、Python 与 JavaScript 调用示例

Python 环境推荐使用 requests 库。它的参数字典可以自动处理 URL 编码,不需要手动拼接查询字符串,代码可读性也更好。下面示例会在请求成功后打印天气描述、温度、湿度和风速,失败时输出状态码和返回信息。

import requests
API_KEY = "YOUR_API_KEY"
CITY = "Beijing"
BASE_URL = "https://api.openweathermap.org/data/2.5/weather"
params = {
    "q": CITY,
    "appid": API_KEY,
    "units": "metric",
    "lang": "zh_cn"
}
response = requests.get(BASE_URL, params=params)
if response.status_code == 200:
    data = response.json()
    weather_desc = data["weather"][0]["description"]
    temp = data["main"]["temp"]
    humidity = data["main"]["humidity"]
    wind_speed = data["wind"]["speed"]
    print(f"{CITY}天气:{weather_desc}")
    print(f"温度:{temp}°C,湿度:{humidity}%,风速:{wind_speed}m/s")
else:
    print(f"请求失败,状态码:{response.status_code}")
    print(response.json())

浏览器或 Node.js 环境可以使用 fetch。与 Python 示例不同,fetch 默认不会在 HTTP 错误状态码时抛异常,所以需要检查 response.ok,再决定是否解析 JSON。以下代码将城市名和密钥放在模板字符串中,实际项目中密钥不要硬编码在前端。

const apiKey = "YOUR_API_KEY";
const city = "Beijing";
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=zh_cn`;
fetch(url)
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    const weatherDesc = data.weather[0].description;
    const temp = data.main.temp;
    const humidity = data.main.humidity;
    const windSpeed = data.wind.speed;
    console.log(`${city}天气:${weatherDesc}`);
    console.log(`温度:${temp}°C,湿度:${humidity}%,风速:${windSpeed}m/s`);
  })
  .catch(error => console.error("请求出错:", error));

常见错误状态码比较固定。401 表示 API 密钥无效或未激活,404 表示城市名称无法匹配,429 表示请求频率超过当前套餐限制。遇到 404 时可以先尝试加上国家代码,例如把 q=Paris 改为 q=Paris,FR,减少重名干扰。遇到 429 则应降低轮询频率或增加缓存。

四、城市名称歧义与接口使用建议

城市名称不像坐标那样唯一,很多国家都有同名城市。如果请求时只写 q=Springfield,服务端只能根据内部优先级返回一个结果,可能会与你预期不符。更可靠的做法是使用组合查询:q=Springfield,US、q=Springfield,IL,US,或者直接用坐标查询。城市名与坐标结合后,地理编码的歧义会大幅降低。

API 密钥安全也值得单独强调。免费密钥如果直接写在前端代码里,任何人打开浏览器开发者工具都能看到,可能导致额度被恶意消耗。推荐做法是后端代理:前端请求自己的服务器,服务器再携带环境变量中的密钥请求 OpenWeatherMap,并把结果返回前端。这样密钥不会出现在客户端,还能在服务端统一做缓存和限流。

最后要注意数据的时效性和调用成本。实时天气接口返回的是观测站或模型计算数据,并不一定等同于你所在街道的精确情况。对于展示型应用,建议至少缓存 10 到 30 分钟再重新请求,既可以提升页面响应速度,也能减少 API 调用量。若需要分钟级降水预报或空气质量,应改用 OpenWeatherMap 提供的其他接口,而不是频繁轮询当前天气接口。

广告位 · 文章底部(后台-模块管理替换此区域)