基于Python的中国航空航班数据可视化分析系统
项目概述
这是一个功能完整的航空数据可视化分析系统,采用现代化的Web技术栈,为用户提供直观、交互式的航班数据分析体验。
技术栈
- 后端
- 前端: Bootstrap 5 + ECharts + jQuery
- 数据库
- 认证
- 数据处理
系统架构
前端界面层 ←→ 业务逻辑层 ←→ 数据存储层HTML+CSS+JS FastAPI+Python SQLite+CSV
核心功能
1. 用户管理系统
2. 数据分析功能
3. 数据可视化
目录结构
航空数据可视化系统/├── main.py # FastAPI主应用├── requirements.txt # Python依赖├── airplane_system.db # SQLite数据库├── data/ # 数据文件│ ├── air_data.csv # 航空数据│ ├── airplane.csv # 航班数据│ └── analyze.ipynb # 数据分析├── static/ # 静态资源│ ├── css/ # 样式文件│ ├── js/ # JavaScript文件│ └── webfonts/ # 字体文件├── templates/ # HTML模板│ ├── base.html # 基础模板│ ├── dashboard.html # 仪表板│ ├── routes.html # 航线分析│ ├── airlines.html # 航空公司│ ├── cities.html # 城市分析│ ├── schedule.html # 班期分析│ ├── price.html # 价格分析│ ├── delay.html # 延误分析│ └── admin_*.html # 管理页面└── README.md # 项目说明
核心代码实现
用户认证系统
# JWT Token实现from fastapi import HTTPException, Dependsfrom fastapi.security import HTTPBearer, HTTPAuthorizationCredentialsimport jwtfrom datetime import datetime, timedeltaSECRET_KEY = "your-secret-key"ALGORITHM = "HS256"ACCESS_TOKEN_EXPIRE_MINUTES = 30def create_access_token(data: dict): to_encode = data.copy() expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwtdef verify_token(credentials: HTTPAuthorizationCredentials = Depends(HTTPBearer())): try: payload = jwt.decode(credentials.credentials, SECRET_KEY, algorithms=[ALGORITHM]) username: str = payload.get("sub") if username is None: raise HTTPException(status_code=401, detail="Invalid token") return username except jwt.ExpiredSignatureError: raise HTTPException(status_code=401, detail="Token expired") except jwt.JWTError: raise HTTPException(status_code=401, detail="Invalid token")
数据库设计
# SQLite数据库初始化import sqlite3import pandas as pddef init_database(): conn = sqlite3.connect('airplane_system.db') cursor = conn.cursor() # 创建用户表 cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, hashed_password TEXT NOT NULL, email TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') # 创建航班数据表 cursor.execute(''' CREATE TABLE IF NOT EXISTS flights ( id INTEGER PRIMARY KEY AUTOINCREMENT, departure_city TEXT NOT NULL, arrival_city TEXT NOT NULL, airline TEXT NOT NULL, flight_number TEXT NOT NULL, departure_airport TEXT NOT NULL, arrival_airport TEXT NOT NULL, departure_airport_lat REAL, departure_airport_lng REAL, arrival_airport_lat REAL, arrival_airport_lng REAL, on_time_rate REAL, avg_delay_time REAL, monday INTEGER DEFAULT 0, tuesday INTEGER DEFAULT 0, wednesday INTEGER DEFAULT 0, thursday INTEGER DEFAULT 0, friday INTEGER DEFAULT 0, saturday INTEGER DEFAULT 0, sunday INTEGER DEFAULT 0, price REAL, passengers INTEGER ) ''') conn.commit() conn.close()
数据分析API
# 航线分析接口@app.get("/api/routes/analysis")async def get_routes_analysis(): conn = sqlite3.connect('airplane_system.db') cursor = conn.cursor() cursor.execute(''' SELECT departure_city, arrival_city, COUNT(*) as flight_count, AVG(price) as avg_price, AVG(on_time_rate) as avg_on_time_rate FROM flights GROUP BY departure_city, arrival_city ORDER BY flight_count DESC LIMIT 50 ''') routes_data = cursor.fetchall() conn.close() return { "routes": [ { "departure": route[0], "arrival": route[1], "flight_count": route[2], "avg_price": round(route[3], 2) if route[3] else 0, "avg_on_time_rate": round(route[4], 2) if route[4] else 0 } for route in routes_data ] }# 航空公司分析接口@app.get("/api/airlines/analysis")async def get_airlines_analysis(): conn = sqlite3.connect('airplane_system.db') cursor = conn.cursor() cursor.execute(''' SELECT airline, COUNT(*) as flight_count, AVG(price) as avg_price, AVG(on_time_rate) as avg_on_time_rate, AVG(avg_delay_time) as avg_delay_time FROM flights GROUP BY airline ORDER BY flight_count DESC ''') airlines_data = cursor.fetchall() conn.close() return { "airlines": [ { "name": airline[0], "flight_count": airline[1], "avg_price": round(airline[2], 2) if airline[2] else 0, "avg_on_time_rate": round(airline[3], 2) if airline[3] else 0, "avg_delay_time": round(airline[4], 2) if airline[4] else 0 } for airline in airlines_data ] }
前端界面实现
<!-- 响应式导航栏 --><navclass="navbar navbar-expand-lg navbar-light bg-light"> <divclass="container"> <aclass="navbar-brand"href="/"> <iclass="fas fa-plane"></i> 航空数据分析系统 </a> <buttonclass="navbar-toggler"type="button"data-bs-toggle="collapse"data-bs-target="#navbarNav"> <spanclass="navbar-toggler-icon"></span> </button> <divclass="collapse navbar-collapse"id="navbarNav"> <ulclass="navbar-nav me-auto"> <liclass="nav-item"> <aclass="nav-link"href="/dashboard"> <iclass="fas fa-chart-line"></i> 仪表板 </a> </li> <liclass="nav-item"> <aclass="nav-link"href="/routes"> <iclass="fas fa-route"></i> 航线分析 </a> </li> <liclass="nav-item"> <aclass="nav-link"href="/airlines"> <iclass="fas fa-building"></i> 航空公司 </a> </li> <liclass="nav-item"> <aclass="nav-link"href="/cities"> <iclass="fas fa-city"></i> 城市分析 </a> </li> </ul> <ulclass="navbar-nav"> <liclass="nav-item dropdown"> <aclass="nav-link dropdown-toggle"href="#"id="userDropdown"role="button"data-bs-toggle="dropdown"> <iclass="fas fa-user"></i> {{ current_user }} </a> <ulclass="dropdown-menu"> <li><aclass="dropdown-item"href="/profile">个人中心</a></li> <li><hrclass="dropdown-divider"></li> <li><aclass="dropdown-item"href="/logout">退出登录</a></li> </ul> </li> </ul> </div> </div></nav>
数据可视化图表
// 初始化仪表板图表function initDashboardCharts() { const flightStatsChart = echarts.init(document.getElementById('flightStatsChart')); const flightStatsOption = { title: { text: '航班数据概览', left: 'center' }, tooltip: { trigger: 'axis' }, legend: { data: ['航班数量', '平均价格', '准点率'], top: 30 }, xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] }, yAxis: [ { type: 'value', name: '航班数量', position: 'left' }, { type: 'value', name: '价格/准点率', position: 'right' } ], series: [ { name: '航班数量', type: 'bar', data: [1200, 1320, 1010, 1340, 900, 2300, 2100] }, { name: '平均价格', type: 'line', yAxisIndex: 1, data: [820, 932, 901, 934, 1290, 1330, 1320] }, { name: '准点率', type: 'line', yAxisIndex: 1, data: [95.2, 94.8, 96.1, 93.5, 94.2, 95.8, 96.3] } ] }; flightStatsChart.setOption(flightStatsOption);}// 初始化中国地图function initChinaMap() { const mapChart = echarts.init(document.getElementById('chinaMap')); fetch('/static/js/china.json') .then(response => response.json()) .then(chinaJson => { echarts.registerMap('China', chinaJson); const mapOption = { title: { text: '中国航线分布图', left: 'center' }, tooltip: { trigger: 'item', formatter: '{b}: {c} (航班数量)' }, visualMap: { min: 0, max: 1000, left: 'left', top: 'bottom', text: ['高', '低'], calculable: true }, series: [ { name: '航班数量', type: 'map', map: 'China', roam: true, emphasis: { label: { show: true } }, data: [ {name: '北京', value: 850}, {name: '上海', value: 720}, {name: '广州', value: 680}, {name: '深圳', value: 520}, {name: '成都', value: 480} ] } ] }; mapChart.setOption(mapOption); });}
数据可视化展示
项目展示
🐼 项目源码获取,码界筑梦坊各平台同名,博客底部含联系方式卡片,欢迎咨询!

























1. 航线分布地图
2. 航线飞线图
3. 数据分析图表
4. 实时数据更新
部署与运行
环境要求
- 现代浏览器(Chrome、Firefox、Safari、Edge)
安装步骤
- 克隆项目
git clone <项目地址>cd 航空数据可视化系统
- 创建虚拟环境
python -m venv venvsource venv/bin/activate # Linux/Mac# 或venv\Scripts\activate # Windows
- 安装依赖
pip install -r requirements.txt
准备数据文件 确保 data/airplane.csv 文件存在,包含必要的航班数据字段
启动系统
- 访问系统 打开浏览器访问
http://localhost:8000
生产环境部署
使用Gunicorn部署
pip install gunicorngunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
使用Docker部署
FROM python:3.9-slimWORKDIR /appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY . .EXPOSE 8000CMD ["python", "main.py"]
开发心得与总结
技术选型思考
- FastAPI vs Flask: 选择FastAPI是因为其现代化的异步支持、自动API文档生成和更好的性能表现
- SQLite vs PostgreSQL: 对于原型开发和中小型应用,SQLite提供了简单性和零配置的优势
- ECharts vs D3.js: ECharts提供了更丰富的开箱即用图表,特别适合地图可视化
架构设计亮点
- 前后端分离
- 模块化设计
- 响应式设计
性能优化策略
- 数据库索引
- 数据缓存
- 异步处理
安全性考虑
- 密码加密
- JWT认证
- 输入验证
可扩展性设计
- 插件化架构
- 多数据源支持
- API版本控制
未来发展方向
短期目标
中期目标
长期目标
联系方式
码界筑梦坊 - 专注于技术分享与创新 各平台同名 页面底部含联系卡片
参考资料
许可证
本项目采用 MIT 许可证。
最后更新时间: 2025年8月
如果这篇文章对您有帮助,请给个⭐️支持一下!