资讯详情

基于Python与Vue的天气可视化分析系统:从数据采集到图表展示全解析

📅 2026/9/19 23:59:56 | 华诺云谱 👁 阅读
基于Python与Vue的天气可视化分析系统:从数据采集到图表展示全解析
每年一到课程设计季就有不少同学向我打听天气类的题目到底怎么做才出彩这个选题看似普通但想拿高分、想真正学到东西关键在于把“数据采集—数据存储—后端接口—前端可视化”这条路完整跑通。我今天就把自己打磨过的一套天气可视化分析系统完整拆开来讲整套基于 Python Vue 实现自带源码、数据库脚本和配套文档。这套系统解决的问题很直接把分散在气象接口里的天气数据抓下来存进 MySQL 数据库再用 Vue 写一个可视化大屏把温度趋势、湿度分布、城市对比、历史统计等内容用图表直观呈现出来。你拿到手之后既能当课设、毕设的完整项目也能当作自己学习 Python 后端和 Vue 前端的最佳练手素材。我会从系统设计思路讲起逐层拆开数据库表设计、后端接口实现、前端图表渲染、项目本地启动这几个核心环节最后把我在开发过程中踩过的坑和排查思路一并整理出来。无论你是刚入门 Python、第一次接触 Vue还是准备把项目部署上线这篇文章都能给你能直接抄作业的路径。1. 系统设计与技术选型为什么偏偏是 Python Vue1.1 技术选型背后的真实考量很多同学问我做一个天气系统直接写个网页调接口不就行了为什么非要拆成前后端分离这里面的逻辑很简单纯后端模板渲染比如 Flask Jinja2开发快但图表交互、异步加载、页面转场这些体验很吃力而纯前端方案没法解决数据持久化和定时采集的问题。Python Vue 的组合恰恰在开发效率和展示效果之间取了一个平衡点。Python 生态里做数据采集和处理太方便了。requests 拉接口、pandas 做清洗聚合十几行代码就能搞定一套完整的数据流水线。后端我用的是轻量级框架 Flask配合 Flask-SQLAlchemy 做 ORM比 Django 更轻、更容易让初学者看懂每一行代码的用途。Vue 这边我选的是 Vue 3 Vite 组合配合 Element Plus 做后台布局、ECharts 做图表渲染。Vue 的响应式机制非常适合这种多城市切换、时间范围筛选的交互场景——你选一个城市页面上的所有图表同时联动更新这个体验用传统 jQuery 写会相当痛苦。1.2 系统功能模块拆解整套系统我从需求角度拆成了 6 个核心模块数据采集模块定时从公开天气 API 拉取实时天气、逐日预报和历史天气数据同时做好异常重试和数据去重。数据存储模块MySQL 数据库存储城市信息、实时天气数据、历史天气记录、用户信息四类核心数据。后端接口模块提供城市列表、当前天气、历史趋势、统计数据等 RESTful API全部返回 JSON 格式。前端展示模块Vue 大屏页面包含城市切换、时间范围选择、多图表联动、表格数据展示等功能。数据分析模块对温度、湿度、风力等维度做月均值、极值、变化趋势计算并在前端以图表呈现。用户管理模块简单的注册登录、会话保持功能便于系统扩展成完整的前后端分离项目。这 6 个模块也可以看作你现在简历上能写的 6 个技术点。面试官问起来你能从采集到展示把整个链路的细节讲清楚这比背十个八股文都管用。1.3 整体架构的分层设计系统的整体架构分成四层每一层有自己的职责边界第一层是数据采集层跑在后端服务里的定时任务。如果 API 调用失败会用备用数据源重试确保天气数据不出现大段空白。第二层是数据服务层也就是 Flask 后端。它既要接收前端的 HTTP 请求返回对应 JSON 数据也负责对原始天气数据做清洗加工比如把字符串格式的温度转为数值、按城市和时间维度聚合统计。第三层是数据存储层MySQL 负责持久化所有数据。为了保证开发和调试方便SQLAlchemy 的建表语句会在首次启动时自动执行也提供了手动导入的 SQL 脚本。第四层是前端展示层Vue 负责页面渲染和交互。前端通过 Axios 调用后端接口拿到 JSON 后驱动 ECharts 更新。各层之间通过标准 HTTP 接口通信互不干扰。这样即便以后要把后端换成 Java、Go前端代码也几乎不用改动这就是前后端分离架构的价值所在。2. 数据库设计与数据流转从接口到表的完整链路2.1 数据源选择与备选方案天气数据是整个系统的血液。我基于稳定性和易用性优先选择了免费且无需复杂鉴权的公开天气 API例如 OpenWeatherMap 的免费接口或和风天气的免费开发版。这类接口通常只需注册获取一个 API Key就能按城市名或经纬度拉取实时天气。这里我补一句重要的很多项目教程里用爬虫直接抓网页数据我其实不太推荐作为主方案。因为天气类网站的页面结构经常变动一旦网站改版你的采集器就废了。接口的方式虽然也有频率限制但字段结构稳定更适合做长期运行的系统。我自己的实现方式是双数据源策略主数据源用免费 API每天定时采集一次当天实时数据追加写入历史表如果主数据源连续失败 3 次就触发备用数据源比如另一个免费接口做补偿采集。这个容错机制写起来不到 50 行代码但能在演示答辩时避免“打开系统发现没有数据”的尴尬。2.2 数据库表结构设计的核心思路整个系统的核心数据表一共 4 张我把字段设计和设计思路说明如下。第一张是城市表存储城市的基本信息和经纬度坐标。经纬度字段非常重要因为后续做地图展示、计算日出日落时间、按坐标拉取天气都需要用到。CREATE TABLE city ( id int NOT NULL AUTO_INCREMENT, city_name varchar(50) NOT NULL COMMENT 城市名称, province varchar(50) DEFAULT NULL COMMENT 所属省份, longitude decimal(10, 6) DEFAULT NULL COMMENT 经度, latitude decimal(10, 6) DEFAULT NULL COMMENT 纬度, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_city_name (city_name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT城市信息表;第二张是实时天气表存储某个城市某一时刻的瞬时天气数据。这张表是 append-only 模式只增不改每条数据都记录采集时间。CREATE TABLE weather_realtime ( id bigint NOT NULL AUTO_INCREMENT, city_id int NOT NULL COMMENT 城市ID, temperature decimal(5, 1) DEFAULT NULL COMMENT 当前温度, feels_like decimal(5, 1) DEFAULT NULL COMMENT 体感温度, humidity int DEFAULT NULL COMMENT 相对湿度, pressure int DEFAULT NULL COMMENT 气压, wind_direction varchar(20) DEFAULT NULL COMMENT 风向, wind_scale varchar(20) DEFAULT NULL COMMENT 风力等级, weather_desc varchar(50) DEFAULT NULL COMMENT 天气现象描述, collect_time datetime DEFAULT NULL COMMENT 采集时间, PRIMARY KEY (id), KEY idx_city_time (city_id, collect_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT实时天气数据表;第三张是历史天气表。虽然实时表积累的数据也能查询历史趋势但历史表存的是按天聚合的结果最高温、最低温、平均温、降水量等查询起来更快做趋势分析也更方便。第四张是用户表字段相对常规id、用户名、密码我用 Werkzeug 的加密算法做了哈希处理、创建时间。初次学习也可以先不做用户功能把登录模块去掉系统完全不影响运行。2.3 数据入池清洗与去重怎么处理从 API 拉回来的数据不能直接入库必须先清洗。我这里分享三个关键处理点。第一个是温度字段。接口往往返回字符串或者保留多位小数入库前我会统一转成float并用round保留一位小数。第二个是缺失值。有些接口在极端天气下可能不返回某些字段我的做法是缺失的数值字段填 NULL而不是填 0——因为颗粒物、气压字段填 0 会在图表上形成错误的极值。第三个是去重。采集任务可能因为网络回调重复触发插入前我会先查一下同一城市同一分钟是否已有记录有就跳过。这部分的核心代码逻辑并不复杂核心就是一个采集函数加一个批量入库函数。数据量级并不大即使每 30 分钟采集一次、持续跑一个月数据量也就是几万条级别MySQL 完全可以轻松应对。3. 后端核心实现Flask 接口从零到一3.1 后端项目结构与依赖清单后端项目我保持了极简又清晰的目录结构方便初学者理解app.py应用入口初始化 Flask、注册蓝图、启动定时任务。models.pySQLAlchemy 模型定义与数据库表一一对应。api/蓝图目录按模块拆分接口。scheduler.py定时采集任务使用APScheduler实现。utils.py公共工具函数比如接口请求、数据清洗、响应包装。requirements.txt依赖清单。requirements.txt是我在所有项目里都会维护的文件直接pip install -r requirements.txt就能装齐环境。本项目的核心依赖有flask2.3.3 flask-sqlalchemy3.1.1 flask-cors4.0.0 requests2.31.0 apscheduler3.10.4 pandas2.1.4 werkzeug2.3.83.2 核心接口设计与实现逻辑后端接口我采用了 RESTful 风格并用统一响应结构包装前端解析非常方便。统一的响应格式是{ code: 200, message: success, data: {} }核心接口我整理成了下面这几个GET /api/cities获取城市列表用于前端下拉选择。GET /api/weather/current?city_id1获取指定城市最新一条实时天气。GET /api/weather/history?city_id1days7获取近 N 天历史天气用于折线图。GET /api/weather/statistics?city_id1month2024-01获取某月的温度统计、湿度均值、极端天气天数。POST /api/auth/register和POST /api/auth/login用户注册和登录接口。以历史天气接口为例它的实现思路是先接收参数再查询数据库然后用 JSON 返回。为了让前端画图方便我返回的数据结构设计为同时包含 temperature 数组、humidity 数组和对应的 date 数组而不是返回原始表记录让前端自己处理。3.3 天气统计与聚合逻辑让数据“开口说话”一个只会展示原始数据的系统撑不起“分析”二字。我在后端特意加了一个聚合统计模块用来计算每月平均气温、最高温极值、高温天数、降雨天数等指标。具体算法逻辑是先按城市和时间范围筛选数据然后按月份分组用 SQLAlchemy 的func.avg、func.max、func.min做聚合。对于月份-温度这类简单指标一条 SQL 聚合语句就搞定对于“高温天数”则需要用 Python 遍历每日记录统计最高温度超过 30 度的天数。这些统计结果回传到前端之后会渲染成“月度温度变化曲线”和“极端天气统计卡片”。这个功能是整个系统最出彩的部分答辩时老师最喜欢问的就是均值怎么算的、极值怎么取的你能把逻辑讲清楚印象分会提升不少。4. Vue 前端可视化从数据到图表的最后一公里4.1 前端初始化和必备依赖前端部分用 Vue 3 Vite 构建组件库选了 Element Plus图表库选 EChartsHTTP 请求库用 Axios。项目创建和依赖安装命令如下npm create vitelatest weather-frontend -- --template vue cd weather-frontend npm install npm install element-plus axios echarts element-plus/icons-vue装依赖这一步是很多新手卡壳的地方。如果你在安装过程中遇到权限报错通常是因为之前用管理员权限装过全局包。我建议直接把整个node_modules文件夹删掉再重新执行npm install。如果下载速度慢可以设置镜像源npm config set registry https://registry.npmmirror.com。4.2 页面组件设计大屏布局如何划分前端页面我采用了经典的可视化大屏布局顶部是标题和用户信息左侧是城市选择卡片中间区域是温度趋势折线图和湿度柱状图右侧是天气分布饼图和统计卡片底部是近 7 天天气表格。组件拆分的思路是按卡片来拆CitySelector.vue城市下拉选择器。WeatherCard.vue当前天气信息卡片。TempTrendChart.vue温度趋势折线图。HumidityBarChart.vue湿度柱状图。WeatherPieChart.vue天气现象分布饼图。StatisticPanel.vue统计分析面板。WeatherTable.vue历史天气数据表格。每个组件内部维护自己的 ECharts 实例接收父组件传入的cityId和timeRange作为 props。当父组件中选中的城市改变时通过watch监听 props 变化重新请求接口并刷新图表。这种“数据驱动更新”的方式正是 Vue 响应式设计的精髓。4.3 ECharts 图表配置实战以温度趋势折线图为例ECharts 的核心配置包括 xAxis、yAxis、series 三个部分。这里我强调几个实操时容易踩坑的细节。第一点是 yAxis 的刻度范围。温度数据如果直接交给 ECharts 自动计算可能由于个别离群点导致整体曲线被压扁。我会手动设置min和max适当留出余量保证曲线展示更集中清晰。第二点是用tooltip的trigger: axis这样鼠标悬停时可以同时显示同一天的温度、湿度数据对比分析很方便。第三点是dataZoom组件。当展示 30 天以上数据时折线图会变得很拥挤加上dataZoom后用户可以拖动查看局部体验会好很多。const option { tooltip: { trigger: axis }, legend: { data: [最高气温, 最低气温] }, grid: { left: 3%, right: 4%, bottom: 3%, containLabel: true }, xAxis: { type: category, data: dates, axisLabel: { rotate: 30 } }, yAxis: { type: value, name: 温度(℃), min: Math.floor(minTemp - 2), max: Math.ceil(maxTemp 2) }, dataZoom: [ { type: inside, start: 0, end: 100 }, { type: slider, height: 20 } ], series: [ { name: 最高气温, type: line, smooth: true, data: highTemps, areaStyle: { opacity: 0.15 } }, { name: 最低气温, type: line, smooth: true, data: lowTemps } ] };这段配置里最有价值的其实是axisLabel的rotate属性和dataZoom。没有前者日期标签会重叠成一团黑没有后者数据一多图表就没法看。这两个细节是很多网上教程里不会跟你讲的。4.4 前后端接口对接与跨域处理前端通过 Axios 请求后端接口最头疼的问题就是跨域。开发环境下我推荐在 Vite 配置中设置代理而不是在后端直接开启 CORS 放行。在vite.config.js中加入以下配置server: { proxy: { /api: { target: http://127.0.0.1:5000, changeOrigin: true } } }它的原理是Vite 开发服务器把前端请求中带/api前缀的地址转发到后端地址浏览器看到的始终是同源请求自然不会触发跨域限制。我也在后端加了 Flask-CORS 作为兜底这样即便前端不走代理直接访问后端接口也不会报跨域错误。双重保障在联调和演示时能省不少事。这里提醒一句线上部署时不要全开 CORS应该配置白名单否则任意网站都能调用你的接口容易产生安全风险。4.5 城市切换和图表的联动更新机制页面左侧有一个城市下拉框。当用户选择新城市后所有图表和当前天气卡片必须同步更新。我这里的实现方案是在父组件中定义currentCityId这个响应式变量把它传递给所有子组件。子组件通过watch监听currentCityId的变化变化后重新调用对应接口并用setOption更新 ECharts 实例。这个机制很容易踩一个坑ECharts 实例在setOption时会和上一次配置做 diff 合并如果前后数据结构不一致会导致图表残留旧数据。我的处理方式是每次更新前先调用myChart.clear()然后再setOption。这样虽然损失了一点性能但保证了展示结果的正确性。数据量级很小性能差异完全感知不到。5. 本地部署与完整复现让系统在你电脑上跑起来5.1 环境准备清单我按从零开始的标准把环境准备步骤列一遍方便第一次接触这些工具的同学对照操作。第一步是安装 Python 3.9 及以上版本。去 Python 官网下载安装包安装时记得勾选“Add Python to PATH”。这一步不勾选的话后续在命令行里执行python会提示找不到命令。安装完成后打开终端输入python --version验证。第二步是安装 Node.js 16 或以上版本。同样去官网下载 LTS 版本安装后执行node -v和npm -v验证。第三步是安装 MySQL 5.7 或 8.0。安装时记住 root 密码后续连接数据库要用。第四步是准备一个代码编辑器个人推荐 VS Code装上 Python 和 Vue 相关插件后开发体验很好。5.2 初始化数据库与启动后端第一步是创建数据库。我通常用命令行操作也可以使用 Navicat 等图形化工具CREATE DATABASE weather_system CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;第二步是导入初始化数据。项目里附带了一份weather_system.sql文件里面包含了建表语句和测试城市数据。在命令行中执行mysql -u root -p weather_system weather_system.sql第三步是修改后端数据库配置。打开config.py文件把数据库连接地址改成你自己本地环境对应的地址SQLALCHEMY_DATABASE_URI mysqlpymysql://root:yourpassword127.0.0.1:3306/weather_system第四步是安装依赖并启动 Flask 服务启动后终端会显示接口服务地址。5.3 启动前端与整体联调依赖安装后执行npm run dev启动前端开发服务。Vite 默认端口是 5173浏览器访问http://localhost:5173就能看到系统页面。联调时我习惯先用后端的接口测试工具Apifox 或 Postman直接调一下接口确认数据正常后再打开前端页面。如果发现前端某个图表没有数据先看浏览器 F12 控制台里的网络请求判断是接口报错还是数据格式不对再逐层定位。前后端都启动成功后系统的运行流程是前端页面加载后请求城市列表默认选中第一个城市并请求当前天气和历史趋势所有图表自动渲染出来。切换城市后全部图表联动更新整个系统就算完整跑通了。5.4 项目目录结构与文档阅读指南拿到手之后建议先花十分钟浏览项目根目录的 README 和文档目录。我习惯把文档分成三份一份是部署文档讲环境配置和启动步骤一份是设计文档讲系统架构和数据库设计还有一份是使用说明讲页面功能和操作流程。部署文档是你看项目时应该最先阅读的文件它能保证你把系统跑起来。跑通之后再对照设计文档理解每个模块为什么要这样实现。理解完设计再回到源码里精读关键部分这样学习效率是最高的。6. 常见问题与排查技巧实录6.1 数据库相关连接失败与中文乱码后端启动时报Cant connect to MySQL server九成是连接配置写错了。检查config.py里的密码是否正确、MySQL 服务是否启动。Windows 下打开“服务”管理器找到 MySQL 服务确认状态是“正在运行”。建表后插入的中文数据显示乱码这是字符集配置不一致导致的。解决方法是确认数据库、数据表、连接串都使用 utf8mb4 字符集在SQLALCHEMY_DATABASE_URI后面拼接?charsetutf8mb4参数。6.2 跨域与接口访问异常前端报跨域错误如果走的是 Vite 代理先确认代理配置有没有生效修改vite.config.js后有没有重启 dev server。Vite 的配置文件改动需要重启才能生效这个点经常被忽略。如果接口返回 404看一下后端是否注册了对应蓝图以及 Flask 的app.route路径是否和前端请求地址完全一致。注意斜杠的有无也会导致 404/api/cities和/api/cities/在 Flask 中可能指向不同的路由。6.3 ECharts 图表问题不显示、报错、旧数据残留图表完全不显示优先检查容器高度。ECharts 初始化时需要容器有明确高度如果外层 div 没有设置高度图表就会显示成空白。解决办法是给图表容器设置固定高度比如height: 400px。当切换城市后图表里出现旧城市的数据残留原因是图表更新时没有清空旧配置。我在前面讲过setOption前先调用clear()能解决绝大多数残留问题。如果用的是 Vue 的v-if控制图表组件显隐还需要注意组件销毁时主动调用dispose()释放实例否则会报“容器已被销毁”的警告。6.4 定时任务与数据采集异常使用 APScheduler 时如果发现定时任务没有执行先检查调度器有没有启动。最简单的测试方式是把采集间隔临时改成 10 秒再观察数据库里有没有新数据写入。正常情况下定时任务会打印日志方便你观察每次采集的执行结果和耗时。接口数据拉取超时建议在requests.get中显式设置timeout参数比如 10 秒。如果不设置请求可能长时间挂起导致定时任务越积越多最终拖垮服务。6.5 新手踩坑汇总速查表我把初学阶段最容易出现问题的地方整理成一张速查表方便你对照排查。现象最常见原因解决思路Python 命令找不到安装时未勾选 Add to PATH重装 Python 或手动配置环境变量npm 安装依赖超时默认源下载慢设置镜像源后重装后端启动报模块不存在未安装 requirements.txt执行 pip install -r requirements.txt前端 npm run dev 报错Node 版本过低或依赖冲突升级 Node 版本并删除 node_modules 重装接口返回数据为空数据库没数据或接口参数错误先手动调用接口测试再检查采集任务图表显示空白容器高度为 0给图表容器设置固定高度滚动条或页面布局错乱Element Plus 未完整引入检查 main.js 是否正确注册组件库修改配置不生效服务没有重启改配置后必须重启相关服务7. 这套系统还能怎么扩展如果你想把项目做出差异化这里有几个我实际验证过可行的方向。第一个方向是接入实时预测。用 LSTM 或 Prophet 对历史温度数据做时序预测前端用 ECharts 同时展示历史曲线和未来预测曲线系统的分析属性会大幅增强。第二个方向是增加地图可视化。用 ECharts 的地图组件在省份地图上打点颜色深浅代表温度高低视觉冲击力很强。数据库里预留的经纬度字段就是为这个功能准备的。第三个方向是增加用户偏好设置。让不同用户保存自己关注的城市列表登录后自动加载各自的关注城市。这个小功能不复杂但能让系统从一个“演示品”变成“可用的产品”。第四个方向是容器化部署。写一份 Dockerfile把前后端分别打包成镜像再用 docker-compose 一起编排启动。这件事能提前帮你在简历上加一行“熟悉 Docker 部署流程”性价比很高。这套天气可视化分析系统最大的价值不在于代码本身而在于它把数据采集、关系型数据库设计、后端接口开发、前端组件化、可视化图表、接口联调这一整套项目流程串了起来。我从需求拆解到编码实现走通了全链路才真正理解书上那些概念在工程里是怎么衔接的。如果你也打算拿它来学习或做课设建议不要直接跑起来就算完而是亲手把每一个模块的代码读一遍再删掉重写一遍收获会远超想象。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。