查看: 322|回复: 0

Python天气查询脚本开发:wttr.in接口调用与命令行解析

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
这是一篇基于实际项目经验的Python脚本编程记录。很多初学者在学完基础语法后,往往卡在“能写什么”这一步。天气查询是一个覆盖面很合适的练手场景:它要用到网络请求、JSON解析、参数传递、异常处理,以及简单的函数封装。下面从项目设计、代码实现到运行调试完整拆解。

一、项目形态与接口选型

首先要明确,Python写的天气小程序不等同于微信小程序。常见的形态有两种:一种是命令行/桌面小工具,输入城市名打印天气;另一种是给微信小程序做后端接口,Python通过Flask或FastAPI提供数据。两种形态的核心逻辑一致,都是“给定城市名,返回结构化天气数据”。建议先做命令行版本,把请求、解析、异常处理练熟,再考虑包HTTP接口。

天气数据不能自己造,需要借助第三方接口。对比了几种免费方案:wttr.in不需要注册Key,返回格式支持JSON/文本/PNG,可通过lang=zh输出中文,适合个人工具和快速演示;和风天气和需要Key且配额有限,更适合真实小程序后端;OpenWeatherMap也有每分钟次数限制。个人练手首选wttr.in。

wttr.in背后的数据源覆盖全球,城市名可以直接用中文。关键请求参数是format=j1(返回完整JSON)和lang=zh(中文天气描述)。例如:https://wttr.in/北京?format=j1&lang=zh。

本项目依赖很简单:Python 3.8+、requests库。整个程序一个文件即可。目录结构建议:weather_cli/ 下放weather.py主程序,requirements.txt内容为requests。

二、核心代码实现

先准备好环境,检查Python与pip版本,然后安装requests库:
  1. python --version
  2. pip --version
  3. pip install requests
复制代码

核心代码包括城市名URL编码、天气请求、当前天气格式化、未来三天预报格式化、主入口。以下是完整实现:
  1. import requests
  2. import sys
  3. from urllib.parse import quote
  4. def get_weather(city: str) -> dict:
  5.     """请求天气接口,返回解析后的JSON字典"""
  6.     url = f"https://wttr.in/{quote(city)}?format=j1&lang=zh"
  7.     try:
  8.         resp = requests.get(url, timeout=10)
  9.         resp.raise_for_status()
  10.         return resp.json()
  11.     except requests.Timeout:
  12.         print("[错误] 请求超时,请检查网络后重试")
  13.     except requests.RequestException as e:
  14.         print(f"[错误] 请求失败: {e}")
  15.     return {}
  16. def format_current(current: dict) -> str:
  17.     """格式化当前天气信息"""
  18.     temp = current["temp_C"]
  19.     feels = current["FeelsLikeC"]
  20.     humidity = current["humidity"]
  21.     wind = current["windspeedKmph"]
  22.     desc = current["lang_zh"][0]["value"] if "lang_zh" in current else current["weatherDesc"][0]["value"]
  23.     return (
  24.         f"当前温度: {temp}°C\n"
  25.         f"体感温度: {feels}°C\n"
  26.         f"天气状况: {desc}\n"
  27.         f"相对湿度: {humidity}%\n"
  28.         f"风速: {wind} km/h"
  29.     )
  30. def format_forecast(weather: list) -> str:
  31.     """格式化未来三天预报"""
  32.     lines = ["\n未来三天预报:"]
  33.     for day in weather[:3]:
  34.         date = day["date"]
  35.         mintemp = day["mintempC"]
  36.         maxtemp = day["maxtempC"]
  37.         hourly = day["hourly"][0]
  38.         desc = hourly["lang_zh"][0]["value"] if "lang_zh" in hourly else hourly["weatherDesc"][0]["value"]
  39.         lines.append(f"{date}: {desc}, {mintemp}°C ~ {maxtemp}°C")
  40.     return "\n".join(lines)
  41. def main():
  42.     if len(sys.argv) > 1:
  43.         city = " ".join(sys.argv[1:])
  44.     else:
  45.         city = input("请输入城市名: ").strip()
  46.     if not city:
  47.         print("城市名不能为空")
  48.         return
  49.     data = get_weather(city)
  50.     if not data:
  51.         return
  52.     current = data["current_condition"][0]
  53.     print(f"\n{city} 实时天气:")
  54.     print(format_current(current))
  55.     print(format_forecast(data["weather"]))
  56. if __name__ == "__main__":
  57.     main()
复制代码

这里有几个关键细节值得说明。

timeout=10不是随便写的。接口正常响应通常在1到2秒,10秒超时能应对慢网络,又不会让用户长时间等待。

raise_for_status()会在HTTP状态码为4xx或5xx时抛出异常,防止拿到错误页面后继续解析出奇怪的错误。

城市名用urllib.parse.quote做URL编码非常必要。直接把“北京”放进URL可能产生编码问题,编码后接口才能正确识别。

接口返回的数据中,current_condition是当前天气数组,weather是多天预报数组。实际返回字段很多,这里只取了温度、体感、描述、湿度、风速五个维度。天气描述字段默认返回英文,只有加lang=zh才会返回lang_zh数组,代码中做了兼容,找不到中文描述时回退英文。

三、运行与输出效果

运行方式有两种。第一种是交互式:
  1. python weather.py
复制代码

程序提示“请输入城市名”,输入北京或上海后回车。第二种是带命令行参数直接查:
  1. python weather.py 北京
  2. python weather.py "New York"
复制代码

输出效果类似:
  1. 北京 实时天气:
  2. 当前温度: 18°C
  3. 体感温度: 18°C
  4. 天气状况: 晴
  5. 相对湿度: 23%
  6. 风速: 11 km/h
  7. 未来三天预报:
  8. 2025-01-05: 晴, -4°C ~ 6°C
  9. 2025-01-06: 多云, -3°C ~ 7°C
  10. 2025-01-07: 阴, -2°C ~ 5°C
复制代码

这里需要注意:如果城市名中有空格,比如“New York”,命令行传参时必须加引号,否则会被拆成两个参数。

如果希望在Linux/macOS终端直接输入别名调用,可以在shell配置中加:
  1. alias tq='python3 ~/weather_cli/weather.py'
复制代码

之后直接输入“tq 北京”即可查询。

四、功能扩展实践

扩展一:多城市连续查询。把命令行参数视为城市列表,逐个遍历即可实现。使用sys.argv切片后,如果没有参数就交互式输入。若城市名带空格,仍需引号包裹。

扩展二:做成HTTP接口给小程序或前端用。用Flask包一层即可:
  1. from flask import Flask, jsonify, request
  2. from weather import get_weather, format_current, format_forecast
  3. app = Flask(__name__)
  4. @app.route("/weather")
  5. def weather():
  6.     city = request.args.get("city", "")
  7.     if not city:
  8.         return jsonify({"error": "city parameter is required"}), 400
  9.     data = get_weather(city)
  10.     if not data:
  11.         return jsonify({"error": "failed to fetch weather"}), 502
  12.     current = data["current_condition"][0]
  13.     return jsonify({
  14.         "city": city,
  15.         "current": format_current(current),
  16.         "forecast": format_forecast(data["weather"])
  17.     })
  18. if __name__ == "__main__":
  19.     app.run(host="0.0.0.0", port=5000)
复制代码

这样前端请求/weather?city=北京就能拿到格式化结果。不过生产环境更合理的做法是直接返回temp_C、humidity等原始JSON字段,让前端自己渲染,而不是返回带换行的纯文本。

需要提醒的是,微信小程序前端使用WXML、WXSS和JavaScript,Python只适合做后端API和数据处理。支付等功能与Python脚本无关,需要单独申请商户资质。

五、常见问题排查

实践中有几个容易踩的坑。

第一,Windows控制台中文乱码。这不是代码问题,而是控制台编码不一致。可先执行chcp 65001切换到UTF-8代码页,或运行Python时加-X utf8参数:
  1. python -X utf8 weather.py 北京
复制代码

第二,城市名不存在时接口可能返回空数据或默认城市。建议解析前判断current_condition数组是否为空,为空时提示“城市不存在或无法解析”。

第三,频繁请求被限流。免费接口也需要合理请求频率,批量查询时每隔1秒请求一次,避免连续大量访问。

第四,内网SSL证书报错。公司网络拦截证书时,requests.get会抛SSLError。个人学习可临时加verify=False跳过校验,但要注意安全风险,生产环境禁止这么做。

第五,接口地址硬编码过多。建议把请求URL定义为文件顶部的常量,后续切换数据源或变更域名时只改一行。

排查网络相关问题时,建议先用curl直接请求接口验证:
  1. curl "https://wttr.in/北京?format=j1&lang=zh"
复制代码

如果curl能返回JSON说明接口与网络正常,问题在Python代码;如果curl也超时,需要先解决网络环境。这个方法能快速定位很多“代码没问题但跑不通”的诡异场景。

参考速查表:中文城市名报错或返回空,是URL未编码,用quote处理;中文乱码,是控制台编码问题,用chcp 65001或-X utf8;请求超时,是网络或限流,加timeout参数并控制请求间隔;城市查不到,是拼写或用词不标准,改用拼音、英文名或大城市试试;ModuleNotFoundError,是没有安装requests库,用pip install requests。

六、总结

这类项目对初学者的价值在于:字符串、字典、列表、函数、异常处理、第三方库和API调用全都能覆盖,而且正反馈非常明显。写完代码就能查到真实天气数据,比刷练习题更有成就感。wttr.in返回的数据还包括气压、能见度、云量、降雨概率等几十个字段,可以按需求继续扩展。比如在格式化函数中加入紫外线强度提示,或者把结果按城市保存到本地文件,都是不错的二次实践方向。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-7 12:23 , Processed in 0.026814 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部