Python天气预测与可视化:构建完整数据管道与工程实践
简介面向Python方向毕业设计或课程设计的学生这套完整项目围绕天气预测与可视化系统展开涵盖数据获取、处理分析、前端展示与简单预测算法等核心环节。包内共155个文件既有Python后端源码py/pyc也有前端页面html/css/js、SQL数据库与项目配置文件同时包含视频演示和文档说明压缩包整体约88.36MB前端采用layui、Font Awesome等样式组件界面可直接使用。项目演示了调用天气API获取实时数据、使用Pandas处理历史记录、借助Matplotlib等库绘制趋势图表等典型技术并实现了简单的天气预测算法能帮助读者快速搭建一个支持输入地点查询、天气展示和结果预测的完整系统。当前已有330人学习适合需要答辩参考、代码复现或提升简历项目的Python学习者。1. 天气预测与可视化一套能跑通全链路的数据工程样本天气预测看起来是气象台的事但用 Python 自己动手做一个小型预测与可视化系统门槛远比想象中低。这个毕业设计项目本质上是一条完整的数据管道采集、存储、预测、可视化外加一套文档与演示素材。它能在 4 到 6 周内打磨成型覆盖数据分析、算法选型、工程封装和展示答辩也因此成为 Python 进阶者最常上手的方向之一。对于正在选毕业设计题目、或想用最短路径体验数据工程全流程的人这套拆解法可以少走半年弯路。新人在过程中补齐 Python 语法和数据库操作熟手也能看到预测模型调参、接口异常处理和可视化边界条件的细节。文档说明和视频演示只是交付物真正值得吃透的是数据从采集到呈现的分层设计。2. 预测算法与可视化方案先定技术边界再动手写代码2.1 天气预测不是玄学从统计基线到机器学习天气预测的核心问题是对时间序列做外推也就是根据过去一段时间的观测值推断未来若干个时刻的状态。毕业生容易一上来就选 LSTM 这类深度学习模型但训练数据只有几千条时LSTM 的效果反而不如简单模型。常见做法是先跑通统计学模型再决定要不要上机器学习。线性回归是入门的基线把历史时刻的温度、湿度、气压作为特征预测下一时刻的目标值。它的假设是特征和目标之间存在线性关系代码少、解释性强答辩时容易讲清楚。ARIMA差分自回归移动平均模型则是处理带趋势和季节性的时间序列更规范的工具按需对序列做差分再对残差拟合 AR 和 MA 项。它的缺点是要求数据平稳天气数据通常要去趋势和季节项后才能建模。如果数据量大且包含多站点多维特征可以考虑 LightGBM 或 XGBoost它们对特征工程的要求更高但训练快、可解释性也好。深度学习不是不能用而是需要足够的历史数据、GPU 资源和调参时间。毕业设计的时间窗口内更稳妥的组合是“统计模型做基线 树模型做提升”实在要展示深度学习可以在一个子任务里用 LSTM 对比其它模型的效果。2.2 可视化方案的技术选型为什么是 Matplotlib 和 Plotly天气可视化的目的是让数据规律一目了然不是画得越花哨越好。Matplotlib 是 Python 生态里最成熟的基础绘图库稳定、可控、文档全适合生成论文和文档插入的静态图。Plotly 的优势在交互性和 Web 展示鼠标悬停看数值、拖拽缩放时间轴、下拉筛选城市这些能力让项目在答辩现场更有冲击力。选型时按使用场景分流。预测结果的趋势对比图用 Matplotlib 画折线图多城市温度热力图用 Matplotlib 的 imshow 或 seaborn需要在浏览器里交互展示的页面用 Plotly 生成 HTML 文件嵌入 Flask 或 FastAPI。地理分布图可以选 folium 或 pyecharts但如果只做一两个城市的预测用普通图表就足够了不必引入太重的地图组件。建议的依赖组合是pandas 做数据处理、scikit-learn 跑基线模型、statsmodels 做 ARIMA、matplotlib 和 plotly 做可视化。这套组合在 PyPI 上都能直接安装不涉及编译问题适合快速验证方案。2.3 数据从哪来公开 API 与本地数据库的分工天气预测的数据来源通常是公开气象 API免费额度对学习项目足够用。每个 API 返回的数据结构不同但都包含气温、湿度、风力、天气现象等字段接口调用方式也类似。关键是设计一个数据采集层把 API 响应规范化为统一的数据结构这样后续预测模块不依赖具体数据源。数据库的角色是积累历史数据并支持增删改查。SQLite 对毕业设计来说是够用的选择一个文件就是一个库不需要单独安装数据库服务方便打包交付MySQL 适合展示数据库课程设计要求的场景但前提是团队熟悉服务部署。数据库里存原始观测数据和预测结果两张表原始数据表用于模型训练预测结果表用于可视化展示和准确率回溯。采集、存储、预测、可视化四层分离是这套项目的核心架构后文的环境搭建、代码实现和参数调优都围绕这条链路展开。3. 从零跑通最小系统环境搭建、数据采集与预测实现3.1 环境准备用 venv 和 pip 搭一个干净的 Python 运行环境Python 版本建议选择 3.9 或 3.10兼容性最好。安装完成后验证环境再创建项目目录和虚拟环境。mkdir weather_project cd weather_project python -m venv venv venv\Scripts\activate # Linux/macOS 用 source venv/bin/activate pip install requests pandas numpy matplotlib scikit-learn statsmodels plotly flask pip list # 确认已安装的包及版本这个流程避免直接往全局环境装包因为项目依赖的版本可能与系统其它程序冲突。虚拟环境把依赖隔离在项目目录下生成 requirements.txt 后换一台机器也能快速复现。写一份依赖清单是文档说明的一部分答辩时会被问到环境迁移问题。pip 安装时需要注意Windows 用户尽量在 PowerShell 里操作路径不要包含中文和空格否则部分包编译或读取文件会报错。若公司或校园网络限制 PyPI 访问可以考虑配置国内镜像源但毕业设计源码里不应包含这些配置信息。3.2 数据采集用 requests 获取天气数据并落库以 OpenWeatherMap 的免费 API 为例调用接口的代码如下import requests import sqlite3 import datetime API_KEY your_api_key CITY Beijing def fetch_weather(city, api_key): url https://api.openweathermap.org/data/2.5/forecast params { q: city, appid: api_key, units: metric, lang: zh_cn } resp requests.get(url, paramsparams, timeout10) resp.raise_for_status() return resp.json() def save_to_db(data, db_pathweather.db): conn sqlite3.connect(db_path) cursor conn.cursor() cursor.execute( CREATE TABLE IF NOT EXISTS daily_weather ( time TEXT PRIMARY KEY, temp REAL, humidity INTEGER, pressure INTEGER, wind_speed REAL, description TEXT ) ) for item in data[list]: ts datetime.datetime.utcfromtimestamp(item[dt]).strftime(%Y-%m-%d %H:%M:%S) cursor.execute( INSERT OR REPLACE INTO daily_weather VALUES (?, ?, ?, ?, ?, ?), ( ts, item[main][temp], item[main][humidity], item[main][pressure], item[wind][speed], item[weather][0][description] ) ) conn.commit() conn.close() # 调用 raw fetch_weather(CITY, API_KEY) save_to_db(raw)逻辑说明fetch_weather 用 requests 的 get 方法发送 HTTP GET 请求params 里的 unitsmetric 让温度返回摄氏度langzh_cn 让天气现象描述显示中文。timeout 参数控制请求等待时间避免网络卡死导致程序挂在那。save_to_db 用 CREATE TABLE IF NOT EXISTS 保证表结构存在INSERT OR REPLACE 以时间为主键重复数据不会覆盖报错。这段代码里有几个值得注意的点。API 密钥不能硬编码在源码里实践中应通过环境变量或配置文件读取源码包中应提供 config.example.py 而不是真实密钥。requests 库只负责拿到数据不负责重试和缓存批量采集时需要考虑接口频率限制建议每次请求间隔 1 到 2 秒。3.3 预测模型用线性回归和 ARIMA 做两步预测拿到历史数据后先做特征切分和模型训练。下面以最近 7 天小时级数据预测未来 3 小时为例给出线性回归的实现import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error def load_history(db_pathweather.db): conn sqlite3.connect(db_path) df pd.read_sql_query( SELECT time, temp, humidity, pressure, wind_speed FROM daily_weather ORDER BY time LIMIT 168, conn ) conn.close() return df def create_features(df): df df.copy() df[hour] pd.to_datetime(df[time]).dt.hour df[lag_1] df[temp].shift(1) df[lag_3] df[temp].shift(3) df df.dropna() return df df load_history() feature_df create_features(df) X feature_df[[humidity, pressure, wind_speed, hour, lag_1, lag_3]].values y feature_df[temp].values split int(len(X) * 0.8) X_train, X_test, y_train, y_test X[:split], X[split:], y[:split], y[split:] model LinearRegression() model.fit(X_train, y_train) pred model.predict(X_test) print(MAE:, mean_absolute_error(y_test, pred))参数说明lag_1 和 lag_3 是滞后特征表示前 1 小时和前 3 小时的温度这可以让模型捕捉短时趋势。split 是训练集比例80% 用于训练、20% 用于验证是时间序列拆分的常见做法。注意不能随机打乱样本时间序列的时序性一旦破坏模型会学到未来信息。如果数据存在明显趋势或季节性线性回归的残差会带有自相关水平不够高。建议此时改用 ARIMAfrom statsmodels.tsa.arima.model import ARIMA ts df.set_index(pd.to_datetime(df[time]))[temp].resample(3H).mean().dropna() model_arima ARIMA(ts, order(2, 1, 2)) model_fit model_arima.fit() forecast model_fit.forecast(steps4) print(forecast)order(2, 1, 2) 中三个数字分别代表 AR 阶数、差分阶数和 MA 阶数。选定参数时可以用 AIC赤池信息准则做网格搜索依次对 (p, q) 组合计算 AIC 值选最小的组合。ARIMA 模型要求输入序列等间隔先做 resample 避免时间索引不对齐导致建模失败。statsmodels 的新版本 ARIMA 类支持 stepwise 自动搜索参数但在小数据集上手动尝试几个组合更快。3.4 可视化把预测结果画成趋势对比图预测是对未来做推断可视化就要让人一下看出“真实值”和“预测值”的差异。用两个库分别画静态图和交互图。静态图用途是文档和论文插图用 Matplotlibimport matplotlib.pyplot as plt def plot_forecast(dates, actual, predicted, city): plt.figure(figsize(12, 5)) plt.plot(dates[:len(actual)], actual, label实际温度, markero, linewidth2) plt.plot(dates[len(actual)-1:], predicted, label预测温度, markerx, linestyle--) plt.title(f{city} 未来时次温度预测) plt.xlabel(时间) plt.ylabel(温度 (°C)) plt.legend() plt.grid(alpha0.3) plt.tight_layout() plt.savefig(forecast.png, dpi150)交互展示用 Plotly 一页 HTML 承载所有图表。Plotly 图形与其它工具不同构造 figure 时 data 和 layout 是核心结构import plotly.graph_objects as go def build_interactive_plot(dates, actual, predicted): fig go.Figure() fig.add_trace(go.Scatter( xdates, yactual, name实际, modelinesmarkers )) fig.add_trace(go.Scatter( xdates, ypredicted, name预测, modelinesmarkers, linedict(dashdash) )) fig.update_layout( title天气预测对比, xaxis_title时间, yaxis_title温度 (°C), hovermodex unified ) fig.write_html(forecast_interactive.html)Matplotlib 的 savefig 要设置 dpi默认值在论文里不够清晰。Plotly 的 hovermode 设置为 x unified 后鼠标滑过时统一显示所有曲线的数值比一个点一个点地悬停更直观。两个库的字体默认不支持中文Windows 要指定中文字体否则标题和标签会显示成方框。4. 数据库设计、参数调优与项目结构从能跑到能答辩4.1 用 SQLite 做本地数据仓库的建表与查询天气数据规模小、写入不频繁SQLite 的表结构设计遵循第三范式即可。核心是两张表历史数据和预测结果。CREATE TABLE historical_weather ( id INTEGER PRIMARY KEY AUTOINCREMENT, city TEXT NOT NULL, obs_time TEXT NOT NULL, temp REAL NOT NULL, humidity INTEGER, pressure INTEGER, wind_speed REAL, weather_desc TEXT, UNIQUE(city, obs_time) ); CREATE TABLE forecast_result ( id INTEGER PRIMARY KEY AUTOINCREMENT, city TEXT NOT NULL, model TEXT NOT NULL, forecast_time TEXT NOT NULL, target_time TEXT NOT NULL, pred_temp REAL, actual_temp REAL, mae REAL, UNIQUE(city, model, target_time) );UNIQUE 约束保证同城同时刻的数据不会重复写入这是增量采集的基础。历史数据表用于模型训练forecast_result 中的 actual_temp 字段用于回填真实观测值计算模型误差。查询时按时间区间和城市条件筛选SELECT city, obs_time, temp FROM historical_weather WHERE city Beijing AND obs_time datetime(now, -7 day) ORDER BY obs_time;Python 侧用 SQLAlchemy 连接会让项目结构更清晰但毕业设计没必要引入 ORM。直接使用 sqlite3 标准库或 pandas 的 read_sql_query 就能满足数据读取需求。源码包里附带的 .db 文件是已经采集好的样例数据便于评审老师直接运行演示。4.2 预测任务的关键参数窗口、比例、滞后阶数预测系统里有几个参数直接影响效果这些参数在答辩时是必问点参数建议值调参依据训练窗口7-14 天覆盖至少一个自然周包含工作日/周末差异训练/测试比例8:2 或 9:1数据量大取 9:1数据少取 8:2滞后阶数1, 3, 6 小时依据数据采样频率高频用低阶预测步长6-24 小时步长越长误差越大ARIMA order网格搜索 AIC同时观察残差是否白噪声窗口太短模型学不到规律太长则引入过时数据天气系统本身就在变化。训练比例是经典约束测试集必须放在时间序列末尾否则会造成数据泄漏。滞后阶数考察目标值与前几个时刻的相关性可以用自相关图 ACF 观察衰减速度来确定上下界。4.3 源码模块划分数据、模型、视图三层分离一个能过审的毕业设计源码结构应当是模块化的评审老师打开文件夹就能找到对应文件。常见做法是把采集、建模、可视化、Web 服务拆分weather_project/ ├── app.py # Flask 入口路由映射 ├── config.py # 配置项API Key、数据库路径、默认城市 ├── requirements.txt # 项目依赖清单 ├── weather.db # SQLite 数据库 ├── data_collector.py # API 数据采集模块 ├── model_trainer.py # 训练模型并输出指标 ├── model_predictor.py # 调用模型产出预测结果 ├── visualizer.py # 可视化图表生成模块 ├── templates/ │ └── index.html # Web 展示页面 ├── static/ │ └── charts/ # 存放生成的静态图表 ├── docs/ │ └── 设计说明书.md # 文档说明 └── video_demo/ # 演示录屏存放目录app.py 的 Flask 路由把各模块串起来。例如浏览器访问根路径拉起 visualizer 生成图表并嵌入模板然后返回渲染后的页面。config.py 集中管理所有可变参数源码包里千万不能出现实际密钥。模块划分合理时替换 API 或换模型只需要改对应文件不需要把整个项目推倒重来。这也是评审老师会追问的扩展性问题。4.4 Web 展示与数据库交互让项目看起来完整Flask 应用里读取预测结果并渲染到页面的实现from flask import Flask, render_template import sqlite3 import pandas as pd app Flask(__name__) app.route(/) def index(): conn sqlite3.connect(weather.db) df pd.read_sql_query( SELECT * FROM forecast_result WHERE cityBeijing ORDER BY target_time LIMIT 20, conn ) conn.close() return render_template(index.html, tablesdf.to_html(classesdata)) if __name__ __main__: app.run(debugTrue, port5000)render_template 接收 DataFrame 转成的 HTML 表格前端不需要额外引入前端框架。debugTrue 只用于开发调试部署时要关闭否则会暴露栈信息。此处的目标是把后端数据库查询和前端展示打通形成隔一段时间重新预测并刷新页面的闭环。5. 模型评估的进阶技巧用误差回测验证预测可信度模型不是训练完就结束了预测结果必须与真实观测值回填对比。forecast_result 表中有 actual_temp 字段每过一个预测周期就会写入实际温度。这时用一个回测脚本计算多个周期误差就能看出模型在哪些时段效果差、哪些参数需要调整。def backtest_mae(db_pathweather.db): conn sqlite3.connect(db_path) df pd.read_sql_query( SELECT city, model, target_time, pred_temp, actual_temp FROM forecast_result WHERE actual_temp IS NOT NULL ORDER BY target_time DESC LIMIT 100 , conn) conn.close() df[error] abs(df[pred_temp] - df[actual_temp]) result df.groupby([city, model])[error].mean().reset_index() print(result) return result结果按城市和模型聚合平均绝对误差 MAE 如果持续超过 2 摄氏度说明预测结果的参考价值受限。误差会随预测时长增长24 小时以上的预测允许更高容忍度。可视化阶段可以加一个散点图横轴为实际温度纵轴为预测温度对角线附近分布越密集模型越好。回测是任何数据类项目展示可信度的关键一步与其把 API 返回的预测原样展示不如在界面上补一句“历史 48 小时平均误差 1.2°C”更能体现工程能力。顺带可以把图表的配色统一把 Matplotlib 默认的蓝色折线替换为更清晰的对比色把中文标点统一为全角这些细节会降低评审偏差。这套项目的进阶方向很多把线性回归替换成多站点空间插值在 Flask 里加上历史天气对比页或接入实时天气预警信息。不论朝哪个方向走熟悉从 API 到数据库再到前端图表的完整链路本身就是比代码更值钱的收获。本文还有配套的精品资源点击获取