尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Python疫情信息发布平台:从数据采集到可视化看板的全链路实战

发布时间:2026/9/28 15:39:49

资讯中心
01
ARTICLE

Python疫情信息发布平台:从数据采集到可视化看板的全链路实战

Python疫情信息发布平台:从数据采集到可视化看板的全链路实战
简介面向计算机相关专业学生与开发者的完整全栈项目——基于Python大数据分析与可视化的疫情信息发布平台源码涵盖前端、后端与数据库三大部分适用于毕业设计、课程设计或期末大作业场景。项目后端基于Python编写数据处理与分析逻辑前端采用Vue框架构建可视化交互界面并配套SQL数据库脚本可支撑疫情数据的采集存储、统计分析与可视化展示。压缩包共72个文件包含vue、js、css等前端页面文件py后端逻辑代码、sql数据库脚本、json数据文件以及png图片素材和项目使用说明文档整体大小约7.74MB。目前已有217人学习下载。源码目录结构清晰、前后端模块划分合理便于理解全栈项目开发流程也支持在此基础上二次开发与功能拓展可帮助使用者快速掌握Python大数据分析与可视化项目的完整落地方法。1. 疫情信息发布平台源码缺的不是图表而是让数据「自己开口说话」的完整链路你拿到的这套基于Python大数据分析与可视化的疫情信息发布平台源码如果只把它当一堆图表模板来看大概率会用完就扔。真正值钱的是它演示了一条从数据采集、清洗、落库、接口封装再到前端可视化的完整链路原始数据进来清洗成表后端按需聚合前端在浏览器里变成管理者能一眼看懂的折线、地图和热力图。适合谁适合刚学完Python基础、想找一个能写进简历的全栈练手项目的在校生也适合需要给单位或学校搭一套内部数据看板的运维和开发。它能解决的核心问题是把「零散的数字」变成「能支撑判断的信息」。2. 技术选型先想清楚Python分析链路怎么和可视化前端接上2.1 数据链路拆解采集、清洗、聚合、展示四层各管什么拿到这种项目第一件事不是写代码而是把数据流画出来。疫情信息发布平台的数据链路常见做法是拆成四层采集层、清洗层、存储层、展示层。采集层负责从公开数据源拿原始数据比如卫健委公布的确诊数、无症状数、密接数也可能是爬虫抓到的公告页或第三方整理的CSV。清洗层用Pandas做标准化统一日期格式、补全缺失值、把地区名对齐到行政区划编码。存储层是这个平台的承重墙。疫情数据的特点是时间维度强、地区维度强、指标维度多。用MySQL这类关系型数据库存明细查询时再按天/按地区聚合比直接读CSV靠谱得多。展示层就是浏览器里的前端页面通过后端暴露的JSON接口拿到聚合后的数据交给ECharts渲染。这样拆的好处是每一层都能单独替换今天用CSV喂数据明天换成爬虫后天接别的系统只要清洗层输出格式不变上层完全不用动。2.2 后端框架怎么选Flask和Django不是越重越好常见做法是用Flask因为这种数据发布平台后端逻辑不复杂几个聚合查询接口、一个登录鉴权、一个上传入口。Flask轻路由清晰写一个疫情趋势接口只需要几十行代码新手看代码不会迷路。Django自带Admin后台和ORM适合业务模块多、要管用户权限和审核流程的系统但对这个项目来说杀鸡用牛刀。我一般会强调一个点选Flask之后项目结构也要按模块拆不要全塞进一个app.py。至少分出routes、models、utils三层。routes放接口路由models放数据库表映射和查询逻辑utils放数据清洗和格式转换。这样等到你要加一个「按周同比」的新接口不用在一坨代码里翻半天。2.3 可视化选型ECharts是主力Plotly做辅助分析浏览器端图表首选ECharts。原因很实际地图支持好中国省级、市级GeoJSON配好就能渲染折线图、柱状图、热力图对疫情场景全覆盖配置项社区资料多搜「ECharts 地图 疫情」能出来一大把现成配置。Plotly更适合在Jupyter里做交互探索导出HTML倒是方便但作为发布平台的嵌入式图标风格和性能都不如ECharts灵活。前后端数据交互格式统一用JSON。后端返回的结构我习惯固定成{code: 0, msg: success, data: {...}}。code做业务状态msg给前端提示data放实际数据。这个约定一旦定下来前端写axios的时候就不用到处判断异常情况。Python后端用Flask自带的jsonify序列化DataFrame转换出来的dict注意numpy的int64和float64要转成Python原生类型否则jsonify会报TypeError这条在联调时几乎是必踩的坑。3. 后端与数据库骨架接口设计、连接池与权限控制怎么做3.1 数据库表设计把疫情信息拆成可以分析的结构疫情信息发布平台的核心表至少要有三张地区维度表、每日统计表、病例明细表。地区维度表存地区编码、名称、上级编码用于地图下钻每日统计表存日期、地区编码、新增确诊、累计确诊、治愈、死亡等指标这是趋势图和地图的主要数据源病例明细表可选存每条病例的性别、年龄、确诊日期、来源用于做人群分布分析。建表SQL我一般这么写CREATE TABLE region_daily ( id INT AUTO_INCREMENT PRIMARY KEY, stat_date DATE NOT NULL, region_code VARCHAR(12) NOT NULL, region_name VARCHAR(64) NOT NULL, new_confirmed INT DEFAULT 0, total_confirmed INT DEFAULT 0, cured INT DEFAULT 0, dead INT DEFAULT 0, risk_level VARCHAR(16) DEFAULT low, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_date_region (stat_date, region_code), KEY idx_region (region_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有两个参数说明唯一索引uk_date_region的作用是防止同一地区同一天的数据重复插入做增量更新时用INSERT ... ON DUPLICATE KEY UPDATE直接覆盖region_code用VARCHAR(12)而不是INT是因为地区编码有前导零比如北京是“110000”转成INT就丢了。字符集utf8mb4是必须的疫情数据里的生僻字和标点符号用utf8会报错。3.2 后端接口提供趋势、分布、预警三类核心数据接口设计围绕使用场景来定首页看板要趋势和区域汇总地图页要区域分布预警模块要变化率。我习惯提供三个接口/api/trend、/api/map、/api/alert。趋势接口返回指定日期范围和地区列表的每日聚合指标地图接口返回最新一天各省份的累计值预警接口返回近期新增连续上升的地区。from flask import Blueprint, request, jsonify from sqlalchemy import text api Blueprint(api, __name__) api.route(/trend, methods[GET]) def trend(): start request.args.get(start, 2023-01-01) end request.args.get(end, 2023-12-31) region request.args.get(region, ) sql text( SELECT stat_date, region_name, SUM(new_confirmed) AS new_confirmed, SUM(total_confirmed) AS total_confirmed, SUM(cured) AS cured FROM region_daily WHERE stat_date BETWEEN :start AND :end AND (:region OR region_name :region) GROUP BY stat_date, region_name ORDER BY stat_date ) rows db.session.execute(sql, {start: start, end: end, region: region}).mappings().all() data [dict(row) for row in rows] for item in data: for k, v in item.items(): if isinstance(v, int): item[k] int(v) return jsonify({code: 0, msg: success, data: data})这段代码的关键在GROUP BY按日期加地区分组这样前端既能画全国总趋势也能选中某个省画单省曲线不用另写接口。mappings().all()返回的是字典列表方便jsonify直接序列化。参数里的start、end一定要做白名单校验否则SQL注入风险就藏在这类拼接查询里这是上传漏洞之外后端最容易翻车的位置。3.3 数据库连接池高并发下别让MySQL成为黑匣子开发环境一条连接够用上线后几十个用户同时打开看板如果每个请求都新建数据库连接MySQL很快会报Too many connections。解决方案是连接池用SQLAlchemy自带配置就行。from sqlalchemy import create_engine engine create_engine( mysqlpymysql://user:password127.0.0.1:3306/covid_db, pool_size10, max_overflow5, pool_recycle3600, pool_pre_pingTrue, echoFalse )参数经验值pool_size配10max_overflow配5意思是池子里保底10个连接极限15个超过15个的请求排队等待。pool_recycle3600让连接每3600秒重建一次目的是规避MySQL服务端的wait_timeout默认8小时杀空闲连接你这边还拿着死连接不放导致重启服务才恢复。pool_pre_pingTrue是在每次从池里取连接前先发一个轻量探测连接断了就换一条这一项是解决「连接池耗尽后服务半天缓不过来」的关键。开发和部署环境用的是同一个MySQL实例时连接池参数不能照抄。云数据库和小机器上pool_size建议调到5以内否则应用一启动就占掉几十个连接其他系统容易连不上数据库。另外本地临时调试用SQLite跑通逻辑是可以的SQLAlchemy只需要改连接串但发布平台一定别用SQLite并发写锁问题会让你在联调阶段就怀疑人生。4. 前端可视化落地过程从接口数据到ECharts图表4.1 前后端联调跨域与接口约定是第一个坎前后端分离项目实战中最常见的翻车现场是后端接口用浏览器直接打开有数据前端页面一请求就报错。原因几乎都是跨域。Flask后端如果跑在5000端口前端页面跑在8080端口浏览器的同源策略会拦截请求。解决方式是在Flask应用里加上CORS配置让后端明确允许指定来源访问。from flask_cors import CORS app Flask(__name__) CORS(app, resources{r/api/*: {origins: [http://localhost:8080]}})这段配置的含义是只对/api/前缀的接口开放跨域并且只允许来自http://localhost:8080的请求。比CORS(app)无脑全开要安全因为生产环境的前端域名是固定的别图省事把origins设成*否则任何第三方网页都能通过浏览器调用你的接口拿数据这在发布平台里等于裸奔。联调阶段还要统一传参方式。我习惯GET请求的参数从request.args取POST的JSON从request.json取前端axios传参数时注意用params传GET参数用data传POST的JSON体。前端传参写反了后端起到的常常是None排查半天发现是GET用了data这类低级错误占了联调日志的一半。4.2 ECharts配置折线、地图、热力图的核心项疫情看板最常用的图表是折线图和地图。折线图代码大概长这样const trendChart echarts.init(document.getElementById(trendChart)); fetch(/api/trend?start2023-01-01end2023-12-31) .then(res res.json()) .then(res { const data res.data; const dates [...new Set(data.map(d d.stat_date))]; const names [...new Set(data.map(d d.region_name))]; const series names.map(name ({ name: name, type: line, smooth: true, data: dates.map(date { const item data.find(d d.stat_date date d.region_name name); return item ? item.new_confirmed : 0; }) })); trendChart.setOption({ tooltip: { trigger: axis }, legend: { type: scroll }, xAxis: { type: category, data: dates }, yAxis: { type: value }, series: series }); });这里有个性能细节如果地区很多series太多会让图例挤成一团所以legend要配type: scroll后端返回全量地区数据前端用find逐条匹配数据量在几千条以内没问题一旦超过几万条这种find写法的性能会明显下降应该在后端就按地区分组返回嵌套结构而不是前端再做一次find。地图配置要把GeoJSON的注册放在图表绘制之前fetch(/static/china.geojson).then(r r.json()).then(geoJson { echarts.registerMap(china, geoJson); mapChart.setOption({ visualMap: { min: 0, max: 10000, inRange: { color: [#e0f3f8, #ffffcc, #feb24c, #f03b20] }, text: [高, 低], calculable: true }, series: [{ type: map, map: china, roam: true, data: mapData }] }); });visualMap的max必须根据数据动态计算在拿到接口数据后取最大值再往上取整。写死max: 10000会导致颜色映射失真当天累计值只有500的地区因为全图最大值太大全部显示浅蓝色看不出地区差异。roam: true允许缩放拖拽但看板投屏在展厅大屏上时建议关掉大屏交互不适合让用户拖地图。4.3 页面结构用Vue还是原生JavaScript这种单页看板我建议用Vue 3 Vite加上原生ECharts不用Element UI全家桶。原因一是数据展示型页面交互少组件库提供的表格、弹窗你不是都用得上原因二是Vue的响应式数据和ECharts实例的结合方式更可控。组件库这类东西是给后台管理系统用的疫情发布平台的核心是看板不是一堆按钮。不熟悉Vue的同学纯HTML JavaScript ECharts也能跑只是维护性差点。因为看板通常有筛选条件开始时间、结束时间、地区、指标类型。这些筛选条件变了图表要联动刷新。用Vue的话筛选条件放ref里监听变化后重新调接口再setOption逻辑干净。这里我给你一个最小实现const filters ref({ start: 2023-01-01, end: 2023-12-31, region: }); function refreshAllCharts() { fetchTrend(filters.value); fetchMap(filters.value); fetchAlert(filters.value); } watch(filters, refreshAllCharts, { deep: true });注意deep: true不能省。filters是一个对象直接watch(filters, ...)只能检测到引用变化修改filters.value.start不会触发回调。加上deep: true后对象内部字段变化也能被监听。这个细节会在你加了自定义日期选择器之后立刻暴露出来。5. 上线避坑指南部署、定时更新与高频故障排查5.1 部署结构Nginx Gunicorn MySQL的经典组合本地跑通之后上线部署的常见做法是Nginx做反向代理Gunicorn跑Flask应用MySQL独立在云数据库或者Docker里。Flask自带的werkzeug开发服务器只能单进程并发一上来就卡死不能直接暴露到公网。Gunicorn启动命令大概是gunicorn -w 4 -b 127.0.0.1:5000 app:app-w 4表示起4个worker进程-b绑定本地5000端口不让外部直接访问。Nginx配置里把/api和静态资源反向代理到5000端口同时处理前端页面的托管。部署环节有一个安全坑必须提上传模块。如果平台要支持管理员上传Excel批量导入数据后端一定要校验文件后缀和内容不能只检查filename.endswith(.xlsx)。因为文件名可以被伪造data.xlsx.php这种后缀形式在部分Apache配置下会被当成脚本执行导致整台服务器被上传漏洞打穿。安全的做法是读文件头判断真实类型Python里可以用python-magic库识别MIME类型白名单只允许application/vnd.openxmlformats-officedocument.spreadsheetml.sheet。5.2 定时更新增量入库不能停机疫情数据的特性决定它每天要更新。人工登录后台导入Excel迟早会忘常见做法是写一个独立的Python更新脚本cron定时跑。脚本读最新数据后执行增量INSERT。0 6 * * * cd /opt/covid_platform /usr/bin/python3 scripts/daily_update.py logs/update.log 210 6 * * *表示每天早晨6点跑一次避开业务高峰。21把标准错误也写进日志排查问题的时候不看日志等于闭眼开车。daily_update.py内部用INSERT ... ON DUPLICATE KEY UPDATE来处理重复日期地区的数据这样即使同一批数据抓了两次也不会造成统计翻倍。增量更新的日志要留够至少30天并且每天检查update.log的行数。行数突然变成0多半是脚本报错或者数据源结构变了。我见过最隐蔽的问题是数据源把日期字段从2023-01-01改成了2023/01/01pandas解析成字符串后直接插库导致数据库里同一天出现两条记录唯一索引没拦住查趋势图时出现断层。5.3 高频故障排查5个必踩坑的现象、原因、解决坑一前端页面全是问号图表标题和地区名乱码。现象接口数据看起来正常页面渲染后中文变???。原因三层都可能出错。数据库表不是utf8mb4或者MySQL连接串没加charsetutf8mb4HTTP响应头没带Content-Type: application/json; charsetutf-8前端HTML没声明meta charsetUTF-8。解决从数据库连接串查起依次改HTTP响应头和HTML声明。排查时先用curl -s 接口地址 | head -c 200看返回的原始字节如果curl显示正常而浏览器乱码问题在前端HTML如果curl就乱码问题在后端或数据库。坑二接口单独访问正常前端页面却请求失败。现象浏览器地址栏输接口地址能看到JSON前端页面控制台报CORS policy错误。原因同源策略拦截前后端端口不同后端没开CORS。解决后端加flask-cors并且origins必须严格填前端域名。如果你用了Nginx做同域反向代理让前端页面和/api走同一个域名和端口跨域问题直接消失这是生产环境最推荐的方案。坑三系统跑了两天后所有接口卡死MySQL报Too many connections。现象SSH进服务器看show processlist;大量连接处于Sleep状态。原因连接池配置了但没生效或者SQLAlchemy的session没有在请求结束时关闭。解决检查Flask的teardown_appcontext里有没有执行db.session.remove()并且连接池打开pool_pre_pingTrue。另外连接池参数调好之后必须重启Gunicorn-w 4的每个worker会各自维护一个连接池你改了配置只重启MySQL没用。坑四地图页面渲染卡顿拖拽缩放掉帧。现象数据量几百条时正常几千条时浏览器明显变卡。原因地图的data数组太大且GeoJSON里的边界坐标点过多前端每次渲染都要处理一遍。解决后端在返回地图接口时只返回地图上实际标记的省份不要全量返回GeoJSON可以去掉不用的精度字段并下采样掉某些极短的边界线段。如果数据本身是逐日的前端只请求最新一天不要一次拉全年的地图数据。坑五数据库里明明是早上8点的数据查询结果却是0点。现象stat_date字段存的是2023-01-01 00:00但业务上统计的是当天8点发布的数据。原因MySQL的时区设置和服务器的系统时区不一致Python写入时用了本地时间读取时MySQL按UTC处理再转换回来差8小时。解决统一时区。MySQL配置default-time-zone 08:00Python连接串加上init_commandSET time_zone 08:00前端展示时再不做时区转换。这条最玄学排查起来最费时间建议部署时就把时区写进安装文档别等出了问题再查。6. 把发布平台升级成研判工具自动日报、异常检测与压测验证当数据更新稳定之后可以通过一些方法验证平台是否可靠并把它从「发布」升级成「研判」。第一步是压测验证接口性能Gunicorn起了4个worker后用ApacheBench测一下趋势接口的吞吐量ab -n 1000 -c 50 http://127.0.0.1:5000/api/trend?start2023-01-01end2023-12-31-n 1000发1000个请求-c 50模拟50个并发。如果每秒请求数低于50优先检查SQL有没有走索引其次看是不是每个请求都触发了全表扫描。第二步是加自动日报。每周一早晨把上周的数据汇总成一份Word或PDF报告发给决策群。Python的python-docx库可以按模板生成带图表的Word文档后端只需要新增一个/api/report/weekly接口返回上周各地区的汇总数据再写一个独立的report脚本把这些数据填进模板cron定时跑。这个功能看起来小但能把平台的用户粘性提升一个档次——因为管理者每周不需要打开系统就能拿到结论。第三步是对新增异常做简单检测。用3-sigma规则把当天新增值和过去7天均值做比较超过均值加3倍标准差就标记为异常。代码量很小但不做这个检测前面的可视化就只是「看个大概」做了平台才算有预警能力。我自己的教训是上线第一周不要急着加功能先把定时更新、备份和日志这三件事跑稳。备份用mysqldump每晚全量一次保留最近7天这个后悔药必须备着。平台稳定运行两周后再考虑自动日报和异常检测否则故障排查和新功能开发挤在一起你会陷入两边都做不好的循环。希望这个方向的落地思路帮到你照着这套链路把一个项目从开发到上线完整跑一遍比刷一百道前端面试题更能理解什么是真正能用的系统。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。