基于Flask的智能天气助手系统设计
一、系统架构图(Mermaid)
二、系统流程图(Mermaid)
三、技术实现详解
1. 核心架构设计
系统采用典型的三层架构:
- 展示层:基于HTML/CSS/JavaScript的响应式界面
- 业务逻辑层:Flask服务处理路由和业务逻辑
- 数据层:OpenWeatherMap API提供原始天气数据
2. 关键技术点
后端实现(app.py)
class WeatherAssistant:
def get_weather_report(self, city):
# API请求封装
params = {
"q": city,
"appid": API_KEY,
"units": "metric",
"lang": "zh_cn"
}
def _generate_advice(self, main, weather, wind):
# 智能建议生成逻辑
if temp > 30:
advice.append("️☀️ 高温预警")
elif temp < 5:
advice.append("❄️ 低温提醒")
前端关键功能
function updateUI(data) {
// 动态DOM更新
document.getElementById('basicInfo').innerHTML = `
<div><strong>温度:</strong>${data.temp}°C</div>
<div><strong>体感温度:</strong>${data.feels_like}°C</div>
`;
// 建议列表渲染
document.getElementById('aiAdvice').innerHTML = data.advice
.map(item => `<div>• ${item}</div>`)
.join('');
}
3. 特色功能实现
- 多语言支持:通过设置
lang=zh_cn
参数获取中文天气描述 - 单位转换:使用
units=metric
实现摄氏度单位 - 智能建议系统:基于温度、湿度和天气状况生成个性化建议
- 错误处理机制:三级错误提示(网络错误、城市无效、服务异常)
4. 界面设计亮点
/* 响应式布局 */
.weather-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
/* 视觉层次设计 */
.advice-box {
background: #e3f2fd;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
四、性能优化策略
- 缓存机制:可添加Redis缓存高频查询城市数据
- 异步加载:前端实现请求状态提示动画
- 安全加固:HTTPS传输、API密钥保护
- 错误恢复:自动重试机制(最多3次)
五、扩展方向建议
- 增加天气预报历史记录功能
- 实现多城市同时查询对比
- 添加天气数据可视化图表
- 集成空气质量指数(AQI)监测
该设计实现了从数据获取到智能建议生成的完整闭环,通过清晰的架构分层和模块化设计,保证了系统的可维护性和扩展性。前端响应式设计与后端RESTful API的配合,为后续功能扩展奠定了良好基础。
运行界面
源码如下:
from flask import Flask, jsonify, request, render_template
import requests
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
API_KEY = "your_api_key" # 替换为你的API密钥
class WeatherAssistant:
# 保留之前WeatherAssistant类的核心逻辑,稍作修改适配Web版
def __init__(self):
self.base_url = "http://api.openweathermap.org/data/2.5/weather"
def get_weather_report(self, city):
try:
params = {
"q": city,
"appid": API_KEY,
"units": "metric",
"lang": "zh_cn"
}
response = requests.get(self.base_url, params=params)
response.raise_for_status()
data = response.json()
if data['cod'] != 200:
return None
return self._format_response(data)
except Exception as e:
print(f"Error: {str(e)}")
return None
def _format_response(self, data):
main = data['main']
weather = data['weather'][0]
wind = data.get('wind', {})
sys = data.get('sys', {})
return {
"city": data.get('name', '未知'),
"country": sys.get('country', '未知'),
"temp": main.get('temp'),
"feels_like": main.get('feels_like'),
"humidity": main.get('humidity'),
"condition": weather.get('description'),
"wind_speed": wind.get('speed', 0),
"advice": self._generate_advice(main, weather, wind)
}
def _generate_advice(self, main, weather, wind):
advice = []
temp = main.get('temp', 0)
if temp > 30:
advice.append("️☀️ 高温预警:建议避免正午外出,注意防晒补水")
elif temp < 5:
advice.append("❄️ 低温提醒:请注意保暖,预防感冒")
condition = weather.get('description', '')
if '雨' in condition:
advice.append("☔ 记得携带雨具,小心路滑")
if '雪' in condition:
advice.append("⛄ 道路可能结冰,请注意防滑")
if wind.get('speed', 0) > 8:
advice.append("🍃 大风天气:请妥善安置易受风物品")
return advice
@app.route('/')
def index():
return render_template('index.html') # 确保存在templates/index.html
@app.route('/ping')
def ping():
return "pong"
@app.route('/weather')
def weather_api():
city = request.args.get('city')
print(f"正在查询城市:{city}") # 添加调试日志
if not city:
return jsonify({"error": "城市参数不能为空"}), 400
try:
assistant = WeatherAssistant()
result = assistant.get_weather_report(city)
if result:
return jsonify(result)
else:
return jsonify({"error": "城市不存在或服务不可用"}), 404
except Exception as e:
print(f"服务器错误:{str(e)}")
return jsonify({"error": "服务器内部错误"}), 500
if __name__ == '__main__':
app.run(debug=True)