【AI实战】Python开发AI天气预报助手全程指南:含完整代码实现
Python版AI天气预报助手开发指南(含完整代码)
一、背景
在当今数字化时代,人工智能(AI)
正以前所未有的速度渗透到各个领域,从智能家居到自动驾驶,从医疗诊断到金融预测,AI 的影响力无处不在。作为一名对技术充满热情的探索者,我深知 AI 的潜力和价值,也意识到掌握 AI 技术对于个人和职业发展的重要性。因此,我决定深入实践 AI,通过实际项目的开发和应用,从最基础的API接入
融入AI科技,提升自己的技术能力和对 AI 的理解。
在这个过程中,我选择了构建一个 AI 实现的天气助手
作为我的实践项目。结合传统冰冷的天气参数和暖心的大预言模型 AI 技术,打造一个能够自动解析城市编码、获取天气数据,并生成自然语言天气报告的智能系统,为用户提供更加贴心、便捷的天气服务。
二、技术选型
作为《穷鬼的回忆录》一书的作者,选型主要考虑的是免费!
免费!
免费!
然后再考虑支持目前大热的deepseek
模型,所以最后选择了和风天气和无问芯穹的deepseek模型作为核心技术支撑,其中和风天气用于查询天气参数信息,无问芯穹用于根据查询的天气结果参数提供专业的报告。
和风天气
拥有丰富而精准的气象数据资源。我们利用其提供的API接口,可以轻松实现城市编码的查询以及获取城市当前的天气参数信息。通过调用和风天气的城市查询API,输入城市名称(支持中英文)或行政区划编码,即可快速获取对应的城市编码。这为后续的天气数据获取奠定了基础。在获取天气数据时,和风天气的实时天气API能够提供详细的气象信息,包括温度、湿度、风速、风向、降水概率等,且支持公制和英制两种单位制,满足不同用户的需求。无问芯穹
的deepseek
模型。该模型具备强大的自然语言处理能力,能够将结构化的天气数据转化为生动、自然的中文天气报告。通过精心设计的提示(Prompt
),我们引导deepseek
模型解析和风天气接口返回的数据,并生成包含穿衣建议和出行提示的个性化天气报告。这种结合AI技术的报告生成方式,不仅提升了用户体验,还为用户提供了更具实用性和参考价值的气象信息。三、AI实践
1. 核心功能设计
2. 环境准备
(1)因和风天气和无问芯穹接口调用都需要使用API密钥
,因此需要分别去其官网注册账户并创建应用KEY:
这两个网站都可以免费注册申请应用密钥,正常测试使用没啥问题的。
获取和风天气 API 密钥
(申请链接) 和无问芯穹 API 密钥
(申请链接),并将其存储在当前目录下的 .env
文件中。
(2)安装Python
环境依赖
pip install openai python-dotenv requests
其中:
.env
文件加载环境变量,简化敏感配置(如API密钥)的管理和隔离。3. 关键代码实现
3.1 系统架构与依赖
(1)依赖库
import os
import json
import requests
from openai import OpenAI
from dotenv import load_dotenv
from requests.exceptions import RequestException
openai
和 dotenv
用于与无问芯穹 API 进行交互及环境变量管理,为 AI 部分提供支持。requests
主要用于和风天气 API 的 HTTP 请求,获取天气数据。json
用于解析和处理 JSON 格式的响应数据,确保数据的正确性和可读性。(2)环境变量初始化:
load_dotenv()
client = OpenAI(
base_url="https://cloud.infini-ai.com/maas/v1",
api_key=os.getenv("INFINI_AI_KEY")
)
使用dotenv
加载.env
配置文件,其中包含无问芯穹 API 的密钥INFINI_AI_KEY
,将敏感信息与代码分离,符合安全规范。
(3)环境变量文件: .env
文件
INFINI_AI_KEY=sk-**
WEATHER_API_KEY=**
3.2 核心函数
(1)城市编码解析:
def get_city_code(city: Union[str, int]) -> str:
"""
智能解析城市编码(支持中英文城市名/行政区划编码)
"""
api_key = os.getenv("WEATHER_API_KEY")
# 判断是否为纯数字编码
if isinstance(city, int) or city.isdigit():
return str(city)
# 调用和风天气城市查询 API
geoapi_url = "https://geoapi.qweather.com/v2/city/lookup"
params = {
"location": city,
"key": api_key,
"range": "cn",
"lang": "zh",
"number": 1
}
try:
response = requests.get(geoapi_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
if data['code'] == '200' and data['location']:
cid = data['location'][0]['id']
return cid
raise ValueError(f"未找到匹配的城市: {city}")
except (RequestException, json.JSONDecodeError) as e:
raise RuntimeError(f"城市查询接口异常: {str(e)}")
response.raise_for_status()
确保 HTTP 请求成功,避免潜在的网络问题。(2)天气数据获取:
def get_weather(city: Union[str, int], unit: str = 'm') -> Dict:
"""
获取和风天气实时数据(自动兼容 gzip 压缩)
"""
api_key = os.getenv("WEATHER_API_KEY")
city_id = get_city_code(city)
url = "https://devapi.qweather.com/v7/weather/now"
headers = {
"Accept-Encoding": "gzip",
"User-Agent": "PythonWeatherSDK/1.0"
}
params = {
"location": city_id,
"key": api_key,
"lang": "zh",
"unit": unit,
"gzip": "true"
}
try:
response = requests.get(url, headers=headers, params=params, timeout=15)
response.raise_for_status()
data = response.json()
if data['code'] != '200':
raise ValueError(f"[{data['code']}] {data.get('message', '未知错误')}")
return data
except RequestException as e:
raise ConnectionError(f"天气接口请求失败: {str(e)}")
except KeyError as e:
raise RuntimeError(f"接口响应格式异常,缺失关键字段: {str(e)}")
gzip
压缩的响应数据,减少网络传输的带宽占用。response.json()
解析 JSON 格式的天气数据,并对关键字段进行校验。(3)AI 天气报告生成:
def generate_weather_report(city: str):
"""生成AI天气报告"""
weather_data = get_weather(city)
try:
prompt = f"""作为专业气象学家,请解析以下和风天气接口查询结果并用中文生成{city}的天气报告:{weather_data}
请包含穿衣建议和出行提示,用自然的口语化表达。"""
print('助手查询:', prompt)
response = client.chat.completions.create(
model="deepseek-r1",
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
stream=True,
)
print('查询结果:\n')
for chunk in response:
if not chunk or not chunk.choices or len(chunk.choices) == 0:
continue
chioce = chunk.choices[0]
if chioce.finish_reason:
break
text = chioce.delta.reasoning_content
if not text:
text = chioce.delta.content
print(text, end='', flush=True)
except requests.exceptions.RequestException as e:
print(f"[API Error] {str(e)}")
except json.JSONDecodeError:
print("[Error] Invalid response format")
(Prompt)
,引导 AI 模型生成包含穿衣建议和出行提示的个性化报告。stream=True
实现流式响应,动态展示 AI 生成的天气报告内容,提升用户体验。(4)亮点说明
- 智能城市编码解析
- 支持多种输入格式(中英文城市名、行政区划编码),提高了系统的灵活性与易用性。
- 利用和风天气的精准城市查询 API,确保城市编码的正确性,为后续天气查询提供基础。
- 高性能天气数据获取
- 自动兼容 gzip 压缩的 HTTP 响应,减少数据传输量,提高网络传输效率。
- 设定合理的超时时间(15秒),防止因网络问题导致的程序卡死,保证系统的稳定性。
- AI 自然语言生成
- 通过无问芯穹的 AI 对话模型,实现了从结构化数据(天气 API 响应)到自然语言报告的自动化转换。
- 提供了个性化的穿衣建议和出行提示,让天气信息更具实用性与参考价值。
- 流式响应的设计让用户能够实时看到 AI 的生成过程,增加了交互的趣味性。
4.完整代码
.env
天气助手.py
天气助手.py
源码#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @ProjectName: Learn
# @Name: 天气助手.py
# @Auth: arbboter
# @Date: 2025/2/21-11:21
# @Desc:
# @Ver : 0.0.0.1
import os
import json
import requests
from openai import OpenAI
from dotenv import load_dotenv
from requests.exceptions import RequestException
from typing import Dict, Union
# 配置无问芯穹API
load_dotenv()
client = OpenAI(
base_url="https://cloud.infini-ai.com/maas/v1",
api_key=os.getenv("INFINI_AI_KEY")
)
def get_city_code(city: Union[str, int]) -> str:
"""智能解析城市编码(支持中英文城市名/行政区划编码)"""
api_key = os.getenv("WEATHER_API_KEY")
# 判断是否为纯数字编码
if isinstance(city, int) or city.isdigit():
return str(city)
# 调用和风天气城市查询API
geoapi_url = "https://geoapi.qweather.com/v2/city/lookup"
params = {
"location": city,
"key": api_key,
"range": "cn",
"lang": "zh",
"number": 1
}
try:
response = requests.get(geoapi_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
if data['code'] == '200' and data['location']:
cid = data['location'][0]['id']
print(f"查询天气编码成功:{city}->{cid}")
return cid
raise ValueError(f"未找到匹配的城市: {city}")
except (RequestException, json.JSONDecodeError) as e:
raise RuntimeError(f"城市查询接口异常: {str(e)}")
def get_weather(city: Union[str, int], unit: str = 'm') -> Dict:
"""
获取和风天气实时数据(自动兼容gzip压缩)
:param city: 支持城市ID/中文名称/英文名称
:param unit: 单位制 m-公制 i-英制
:return: 标准化天气数据字典
"""
api_key = os.getenv("WEATHER_API_KEY")
city_id = get_city_code(city)
url = "https://devapi.qweather.com/v7/weather/now"
headers = {
"Accept-Encoding": "gzip",
"User-Agent": "PythonWeatherSDK/1.0"
}
params = {
"location": city_id,
"key": api_key,
"lang": "zh",
"unit": unit,
"gzip": "true"
}
try:
# 处理响应
response = requests.get(url, headers=headers, params=params, timeout=15)
response.raise_for_status()
data = response.json()
# 处理API错误码
if data['code'] != '200':
raise ValueError(f"[{data['code']}] {data.get('message', '未知错误')}")
print(f"查询{city}天气参数成功:{data}")
# 标准化输出结构
return data
except RequestException as e:
raise ConnectionError(f"天气接口请求失败: {str(e)}")
except KeyError as e:
raise RuntimeError(f"接口响应格式异常,缺失关键字段: {str(e)}")
def generate_weather_report(city: str):
"""生成AI天气报告"""
weather_data = get_weather(city)
try:
prompt = f"""作为专业气象学家,请解析以下和风天气接口查询结果并用中文生成{city}的天气报告:{weather_data}
请包含穿衣建议和出行提示,用自然的口语化表达。"""
print('助手查询:', prompt)
response = client.chat.completions.create(
model="deepseek-r1",
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
stream=True,
)
print('查询结果:\n')
for chunk in response:
if not chunk or not chunk.choices or len(chunk.choices) == 0:
continue
chioce = chunk.choices[0]
if chioce.finish_reason:
break
text = chioce.delta.reasoning_content
if not text:
text = chioce.delta.content
print(text, end='', flush=True)
except requests.exceptions.RequestException as e:
print(f"[API Error] {str(e)}")
except json.JSONDecodeError:
print("[Error] Invalid response format")
# 交互示例
if __name__ == "__main__":
city = input("作为您的AI天气助手,请输入您关心的城市名称:")
# city = '深圳'
generate_weather_report(city)
.env
配置内容INFINI_AI_KEY=您的无问芯穹API密钥
WEATHER_API_KEY=您的天气API密钥
5.运行结果
作为您的AI天气助手,请输入您关心的城市名称:广州
查询天气编码成功:广州->101280101
查询广州天气参数成功:{'code': '200', 'updateTime': '2025-02-21T16:36+08:00', 'fxLink': 'https://www.qweather.com/weather/guangzhou-101280101.html', 'now': {'obsTime': '2025-02-21T16:30+08:00', 'temp': '18', 'feelsLike': '16', 'icon': '104', 'text': '阴', 'wind360': '315', 'windDir': '西北风', 'windScale': '3', 'windSpeed': '13', 'humidity': '58', 'precip': '0.0', 'pressure': '1013', 'vis': '30', 'cloud': '96', 'dew': '11'}, 'refer': {'sources': ['QWeather'], 'license': ['CC BY-SA 4.0']}}
助手查询: 作为专业气象学家,请解析以下和风天气接口查询结果并用中文生成广州的天气报告:{'code': '200', 'updateTime': '2025-02-21T16:36+08:00', 'fxLink': 'https://www.qweather.com/weather/guangzhou-101280101.html', 'now': {'obsTime': '2025-02-21T16:30+08:00', 'temp': '18', 'feelsLike': '16', 'icon': '104', 'text': '阴', 'wind360': '315', 'windDir': '西北风', 'windScale': '3', 'windSpeed': '13', 'humidity': '58', 'precip': '0.0', 'pressure': '1013', 'vis': '30', 'cloud': '96', 'dew': '11'}, 'refer': {'sources': ['QWeather'], 'license': ['CC BY-SA 4.0']}}
请包含穿衣建议和出行提示,用自然的口语化表达。
查询结果:【动态显示,思考过程及最终报告】
[好的,我现在需要帮用户解析这个和风天气的接口查询结果,并生成广州的天气报告。首先,我得仔细看看用户提供的JSON数据,确保没有遗漏任何关键信息。数据里的code是200,说明请求成功,没问题。接下来要注意更新时间是2025年2月21日下午4点36分,但实际观测时间是下午4点30分,这可能对实时性有影响吗?不过用户没特别提到,可能暂时不用处理这个时间差。
接下来是天气数据部分,现在温度是18度,体感温度16,阴天。图标]
因为使用流式模式,生成报告时的交互比较友好,可以即时显示服务信息。
作者:arbboter