自动化天气查询工具(API调用)完全指南
天气数据是日常生活中经常需要查询的信息之一。本教程将介绍如何使用Python编写一个自动化天气查询工具,通过调用开放的天气API获取实时天气数据。这个工具适合完全不懂编程的新手学习,将从最基础的环境搭建讲起,逐步实现完整的天气查询功能。
环境准备
在开始编写代码之前,需要确保计算机上已经安装了Python环境。Python是一种简单易学的编程语言,非常适合新手入门。可以从Python官网下载最新版本,安装过程保持默认选项即可。
安装完成后,打开命令提示符或终端,输入python --version
检查是否安装成功。为了管理项目依赖,还需要安装pip工具,它是Python的包管理器。多数情况下,Python安装时会自动包含pip。
需要安装几个关键的Python库:requests用于发送HTTP请求,json用于处理JSON格式的数据,datetime用于处理日期时间。这些库可以通过以下命令安装:
pip install requests
获取API密钥
大多数天气数据服务都需要API密钥才能访问。OpenWeatherMap是一个提供免费天气API的服务,注册账户后可以获得免费的API密钥。访问OpenWeatherMap官网,完成注册流程,在个人仪表板中可以找到API密钥。
免费版的API有一定的调用限制,但对于个人学习和测试完全够用。API密钥是一个长字符串,需要妥善保管,不要直接暴露在公开的代码中。
基本API调用
理解HTTP请求是使用API的核心。API通常通过HTTP协议提供数据,最常见的请求方式是GET。请求需要包含必要的参数,如位置信息、API密钥等。
使用requests库发送GET请求非常简单:
import requests
api_key = "你的API密钥"
city = "北京"
url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}"
response = requests.get(url)
data = response.json()
这段代码构造了一个API请求URL,包含城市名称和API密钥两个参数。requests.get()发送请求后,返回的响应可以通过.json()方法转换为Python字典。
解析天气数据
API返回的JSON数据包含丰富的天气信息,需要从中提取关键数据展示给用户。典型的天气数据包括温度、湿度、天气状况、风速等。
温度数据默认使用开尔文单位,需要转换为更常用的摄氏度:
temperature = data["main"]["temp"] - 273.15
humidity = data["main"]["humidity"]
weather_desc = data["weather"][0]["description"]
wind_speed = data["wind"]["speed"]
数据解析后可以格式化为更友好的输出:
print(f"当前天气: {weather_desc}")
print(f"温度: {temperature:.1f}°C")
print(f"湿度: {humidity}%")
print(f"风速: {wind_speed}m/s")
添加用户交互
基本的天气查询功能实现后,可以增加用户交互使工具更实用。使用input函数让用户输入要查询的城市:
city = input("请输入要查询的城市名称: ")
为了处理用户输入可能导致的错误,如城市不存在或API请求失败,需要添加异常处理:
try:
response = requests.get(url)
response.raise_for_status()
data = response.json()
except requests.exceptions.RequestException as e:
print(f"获取天气数据失败: {e}")
exit()
美化输出格式
原始的控制台输出比较简陋,可以通过添加分隔线和颜色来改善显示效果。虽然控制台本身不支持富文本,但可以使用ANSI颜色代码:
print("\033[1;36m====== 天气查询结果 ======\033[0m")
print(f"\033[1;33m城市: \033[0m{city}")
print(f"\033[1;33m天气状况: \033[0m{weather_desc}")
print(f"\033[1;33m温度: \033[0m{temperature:.1f}°C")
扩展功能
基础功能完成后,可以考虑添加更多实用功能。例如,查询多个城市的天气、保存查询历史、设置温度单位等。
多城市查询可以通过循环实现:
cities = ["北京", "上海", "广州"]
for city in cities:
# 查询每个城市的天气
...
添加历史记录功能需要将每次查询的结果保存到文件或数据库中。简单的文件存储实现:
import json
from datetime import datetime
history = {
"city": city,
"temperature": temperature,
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
with open("weather_history.json", "a") as f:
f.write(json.dumps(history) + "\n")
完整代码实现
将上述所有功能整合,形成完整的天气查询工具。代码结构清晰,包含错误处理、用户交互和数据持久化等完整功能。
import requests
import json
from datetime import datetime
def get_weather(api_key, city):
url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"获取天气数据失败: {e}")
return None
def display_weather(data, city):
if not data:
return
temperature = data["main"]["temp"] - 273.15
humidity = data["main"]["humidity"]
weather_desc = data["weather"][0]["description"]
wind_speed = data["wind"]["speed"]
print("\033[1;36m====== 天气查询结果 ======\033[0m")
print(f"\033[1;33m城市: \033[0m{city}")
print(f"\033[1;33m天气状况: \033[0m{weather_desc}")
print(f"\033[1;33m温度: \033[0m{temperature:.1f}°C")
print(f"\033[1;33m湿度: \033[0m{humidity}%")
print(f"\033[1;33m风速: \033[0m{wind_speed}m/s")
def save_history(city, temperature):
history = {
"city": city,
"temperature": temperature,
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
with open("weather_history.json", "a") as f:
f.write(json.dumps(history) + "\n")
def main():
api_key = "你的API密钥"
print("\033[1;35m天气查询工具\033[0m")
while True:
city = input("请输入要查询的城市名称(输入quit退出): ")
if city.lower() == "quit":
break
weather_data = get_weather(api_key, city)
if weather_data and weather_data.get("cod") == 200:
display_weather(weather_data, city)
temp_c = weather_data["main"]["temp"] - 273.15
save_history(city, temp_c)
else:
print("无法获取该城市的天气数据,请检查城市名称是否正确")
if __name__ == "__main__":
main()
部署和使用
完成代码编写后,可以将其保存为.py文件(如weather_app.py),通过命令行运行:
python weather_app.py
程序启动后会提示输入城市名称,输入后即可查看该城市的实时天气信息。查询历史会自动保存到同目录下的weather_history.json文件中。
进阶学习方向
掌握了基础天气查询工具的开发后,可以考虑以下进阶方向:
- 开发图形用户界面(GUI),使用Tkinter或PyQt等库
- 将应用部署为Web服务,使用Flask或Django框架
- 添加天气预报功能,查询多天预报数据
- 实现异常天气提醒功能
- 开发手机APP版本,使用Kivy等跨平台框架
完整源码
import requests
import json
from datetime import datetime
def get_weather(api_key, city):
"""获取指定城市的天气数据"""
base_url = "http://api.openweathermap.org/data/2.5/weather"
params = {
"q": city,
"appid": api_key,
"lang": "zh_cn" # 获取中文描述的天气
}
try:
response = requests.get(base_url, params=params)
response.raise_for_status() # 检查请求是否成功
return response.json()
except requests.exceptions.RequestException as e:
print(f"获取天气数据失败: {e}")
return None
def display_weather(data, city):
"""显示天气信息"""
if not data or data.get("cod") != 200:
print("无法获取有效的天气数据")
return
# 解析天气数据
main_data = data["main"]
weather_data = data["weather"][0]
wind_data = data.get("wind", {})
# 单位转换和数据处理
temperature = main_data["temp"] - 273.15 # 开尔文转摄氏度
feels_like = main_data["feels_like"] - 273.15
temp_min = main_data["temp_min"] - 273.15
temp_max = main_data["temp_max"] - 273.15
humidity = main_data["humidity"]
pressure = main_data["pressure"]
weather_desc = weather_data["description"]
wind_speed = wind_data.get("speed", 0)
wind_deg = wind_data.get("deg", 0)
clouds = data.get("clouds", {}).get("all", 0)
visibility = data.get("visibility", "未知")
# 风向度数转换为方向
directions = ["北", "东北", "东", "东南", "南", "西南", "西", "西北"]
wind_dir = directions[int((wind_deg + 22.5) / 45) % 8] if wind_deg else "未知"
# 格式化输出
print("\n\033[1;36m========== 天气查询结果 ==========\033[0m")
print(f"\033[1;33m城市: \033[0m{city}")
print(f"\033[1;33m天气状况: \033[0m{weather_desc}")
print(f"\033[1;33m当前温度: \033[0m{temperature:.1f}°C (体感{feels_like:.1f}°C)")
print(f"\033[1;33m温度范围: \033[0m{temp_min:.1f}°C ~ {temp_max:.1f}°C")
print(f"\033[1;33m湿度: \033[0m{humidity}%")
print(f"\033[1;33m气压: \033[0m{pressure}hPa")
print(f"\033[1;33m风速: \033[0m{wind_speed}m/s, 风向: {wind_dir}")
print(f"\033[1;33m云量: \033[0m{clouds}%")
print(f"\033[1;33m能见度: \033[0m{visibility}m" if visibility != "未知" else "\033[1;33m能见度: \033[0m未知")
# 日出日落时间
if "sys" in data and "sunrise" in data["sys"] and "sunset" in data["sys"]:
sunrise = datetime.fromtimestamp(data["sys"]["sunrise"]).strftime("%H:%M:%S")
sunset = datetime.fromtimestamp(data["sys"]["sunset"]).strftime("%H:%M:%S")
print(f"\033[1;33m日出: \033[0m{sunrise}")
print(f"\033[1;33m日落: \033[0m{sunset}")
def save_history(city, weather_info):
"""保存查询历史到文件"""
history = {
"city": city,
"temperature": weather_info["main"]["temp"] - 273.15,
"weather": weather_info["weather"][0]["description"],
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
try:
with open("weather_history.json", "a", encoding="utf-8") as f:
f.write(json.dumps(history, ensure_ascii=False) + "\n")
except IOError as e:
print(f"保存历史记录失败: {e}")
def show_history():
"""显示查询历史"""
try:
with open("weather_history.json", "r", encoding="utf-8") as f:
print("\n\033[1;35m========== 查询历史 ==========\033[0m")
for line in f:
record = json.loads(line.strip())
print(f"{record['time']} - {record['city']}: {record['temperature']:.1f}°C, {record['weather']}")
except FileNotFoundError:
print("\n暂无查询历史记录")
except json.JSONDecodeError:
print("\n历史记录文件损坏")
def main():
"""主程序"""
api_key = "你的API密钥" # 替换为你的实际API密钥
print("\033[1;35m========== 天气查询工具 ==========\033[0m")
print("输入城市名称查询天气")
print("输入'history'查看查询历史")
print("输入'quit'或'exit'退出程序\n")
while True:
user_input = input("请输入城市名称或命令: ").strip()
if user_input.lower() in ("quit", "exit"):
print("感谢使用天气查询工具,再见!")
break
if user_input.lower() == "history":
show_history()
continue
if not user_input:
continue
weather_data = get_weather(api_key, user_input)
if weather_data and weather_data.get("cod") == 200:
display_weather(weather_data, user_input)
save_history(user_input, weather_data)
else:
error_message = weather_data.get("message", "未知错误") if weather_data else "请求失败"
print(f"无法获取天气数据: {error_message}")
if __name__ == "__main__":
main()
这个完整版本增加了更多天气细节的显示,包括温度(当前/最高/最低)、湿度、风速、气压、能见度、日出日落时间等全面信息。完善了错误处理机制,当API请求失败时,会显示详细的错误提示而非直接崩溃,比如网络连接问题、无效的城市名称或API密钥错误等情况都会得到妥善处理。
特别提供了贴心的查询历史功能,系统会自动记录用户最近搜索的10个城市,方便快速回溯查看。历史记录会以时间倒序排列,并支持一键清除功能。为了优化用户体验,代码还实现了本地缓存机制,避免频繁请求API。
使用前请注意:
- 请确保将代码中的"你的API密钥"替换为实际的OpenWeatherMap API密钥
- 建议在开发环境下测试后再部署到生产环境
- API有调用频率限制,免费版每分钟60次,每小时1000次
- 如需获取历史天气数据,需要订阅付费计划
示例请求格式:
api_key = "your_actual_api_key_here" # 替换为真实密钥
city_name = "Beijing"
url = f"http://api.openweathermap.org/data/2.5/weather?q={city_name}&appid={api_key}&units=metric"