156-基于Flask的北京市商铺数据可视化分析系统
北京市商铺数据可视化分析系统:从数据到洞察的全栈实践指南
这是一篇可直接发布的高质量技术分享,完整覆盖项目背景、功能清单、目录结构、技术栈、落地部署、核心代码讲解与可视化展示预留位,并提供面向实际生产的优化建议。所有示例代码均来自本仓库,读者可复制即用。
- 代码仓库根目录:
F:/code/156-基于Flask的北京市商铺数据可视化分析系统/code
- 应用启动入口:
app.py
- 后端核心:
app/
(Flask + SQLAlchemy + 蓝图模块化) - 前端静态资源:
app/static/
(Bootstrap + ECharts) - 模板:
app/templates/
目录
- 项目概述与功能清单
- 目录结构
- 技术栈
- 快速开始
- 核心代码与模块拆解
- 应用工厂与蓝图注册
- 数据导入脚本:CSV/Excel→数据库
- 分析路由与数据接口
- 前端可视化:ECharts 玫瑰图示例
- 可视化展示
- 生产部署与优化建议
- 联系与交流
项目概述与功能清单
本系统以北京市餐饮商铺与评论数据为核心,提供数据管理、用户交互、统计分析与可视化洞察、智能推荐等能力,覆盖从数据采集处理到可视化呈现的完整链路。
已落地的主要功能(节选):
- 用户体系:注册、登录、退出,权限控制(普通用户/管理员)
- 商铺管理:列表分页、详情、按地区/分类/价格/评分等维度筛选搜索
- 用户交互:收藏、评论(含评分)、评论点赞,个人收藏与评论记录
- 数据分析:分类/地区/价格/评分分布,热门商铺榜单,地理热力分布
- 可视化:ECharts 多图联动(玫瑰图/柱状/折线/散点/仪表/热力/地图)
- 管理后台:用户/商铺/评论管理,系统数据统计面板
目录结构
以下为与开发最相关的骨架(省略与演示无关的文件):
code/app/__init__.py # 应用工厂 & 扩展初始化 & 蓝图注册config.py # 多环境配置(开发/测试/生产)models/ # SQLAlchemy 模型routes/ # 业务蓝图(auth/shop/analytics/...)static/ # Bootstrap/ECharts/自定义样式与脚本templates/ # Jinja2 模板data/ # 原始/处理后数据(CSV/Excel)scripts/import_real_data.py # 数据导入脚本(pandas → MySQL)app.py # 启动入口requirements.txt # 依赖清单README.md
技术栈
- 后端
- Flask 2.3、Flask-SQLAlchemy、Flask-Login、Flask-Migrate、Flask-Mail、Flask-CORS
- SQLAlchemy 2.x、PyMySQL(MySQL 8+)
- Redis(可用于缓存/会话/队列,可按需接入)
- 数据处理/分析
- pandas、numpy、openpyxl、xlrd
- scikit-learn、scipy(推荐/分析可扩展)
- jieba、wordcloud、textblob(文本处理与可视化)
- 可视化与前端
- Bootstrap 5、Bootstrap Icons、AOS(动画)
- ECharts(玫瑰图/柱状图/折线图/散点图/仪表盘/热力/地图)
- 工具与质量
- pytest、pytest-flask、coverage
- python-dotenv、python-dateutil、bcrypt
快速开始
- 环境准备
python -m venv venv
venv\Scripts\activate # Windows
pip install -r requirements.txt
- 数据库配置(MySQL)
在 app/config.py
中调整连接信息,或通过环境变量注入:
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@localhost:3306/design_156_beijing?charset=utf8mb4'
- 初始化数据库
python app.py init_db # 或使用 Flask-Migrate/migrations
- 启动应用
python app.py
# 访问 http://127.0.0.1:5000
- 导入真实数据(可选)
python scripts/import_real_data.py
核心代码与模块拆解
应用工厂与蓝图注册
应用采用工厂模式,扩展(数据库、登录、迁移、邮件)集中初始化,蓝图按业务域拆分并注册:
# app/__init__.py(节选)
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()
mail = Mail()def create_app(config_name=None):app = Flask(__name__)from app.config import configapp.config.from_object(config[config_name or 'development'])db.init_app(app)login_manager.init_app(app)migrate.init_app(app, db)mail.init_app(app)from app.routes.main import bp as main_bpfrom app.routes.auth import bp as auth_bpfrom app.routes.analytics import bp as analytics_bp# ... 其余蓝图app.register_blueprint(main_bp)app.register_blueprint(auth_bp, url_prefix='/auth')app.register_blueprint(analytics_bp, url_prefix='/analytics')return app
数据导入脚本:CSV/Excel→数据库
通过 pandas 读取 CSV,清洗字段并批量入库,按批次 commit
确保性能与稳定性:
# scripts/import_real_data.py(节选)
import pandas as pd
from app import create_app, db
from app.models.shop import Shop, Category, Districtdef import_shops(categories, districts):shops_df = pd.read_csv('data/北京市餐饮商铺数据(4.4w).csv')imported_count = 0for _, row in shops_df.iterrows():name = (row['店铺名称'] or '').strip()if not name:continueshop = Shop(external_id=str(row['店铺id']),name=name,address=row.get('地址') or '',longitude=float(row['经度']) if pd.notna(row['经度']) else None,latitude=float(row['纬度']) if pd.notna(row['纬度']) else None,rating=float(row['评分']) if pd.notna(row['评分']) else None,avg_price=float(row['人均消费']) if pd.notna(row['人均消费']) else None,# ... 分类/地区映射略)db.session.add(shop)imported_count += 1if imported_count % 1000 == 0:db.session.commit()db.session.commit()return imported_count
要点:
- 按 1000 条提交可控内存占用并减少锁持有时间
- 清洗函数独立(如电话、评分、人均消费),出错行跳过并记录日志
分析路由与数据接口
统计接口示例:分类分布,直接由 SQLAlchemy 聚合,前端异步渲染。
# app/routes/analytics.py(节选)
@bp.route('/api/category-distribution')
@login_required
def api_category_distribution():data = db.session.query(Shop.cuisine_type,func.count(Shop.id).label('count')).filter(Shop.is_active == True,Shop.cuisine_type.isnot(None)).group_by(Shop.cuisine_type).order_by(desc('count')).all()result = {'categories': [item[0] for item in data],'counts': [item[1] for item in data]}return jsonify(result)
前端可视化:ECharts 玫瑰图示例
模板中通过后端渲染的 JSON 数据初始化图表,样式统一采用玻璃拟态风格:
<!-- app/templates/analytics/index.html(节选)-->
<script src="{{ url_for('static', filename='js/echarts.min.js') }}"></script>
<script>
var categoryData = {{ category_data | tojson | safe }};
function initCategoryChart() {const chartDom = document.getElementById('categoryChart');const chart = echarts.init(chartDom);const option = {tooltip: { trigger: 'item' },series: [{type: 'pie', roseType: 'area',data: (categoryData || []).map(i => ({ name: i.name, value: i.count }))}]};chart.setOption(option);
}
document.addEventListener('DOMContentLoaded', initCategoryChart);
</script>
可视化展示
*** 🐦🔥 项目源码获取,码界筑梦坊各平台同名,博客底部含联系方式卡片,欢迎咨询!***
生产部署与优化建议
- 配置分层:使用
Development/Testing/Production
多环境配置,敏感信息通过环境变量注入 - 数据库
- 建议开启只读从库用于统计查询,主库承载写入
- 关键字段索引:
cuisine_type
、district
、rating
、avg_price
、created_at
- 缓存
- 重计算接口(统计/榜单)采用 Redis 缓存(Key 带环境/版本),失效时间根据更新频率设置(如 300s)
- 静态资源
- ETags/Cache-Control 结合版本号;CDN 分发 Bootstrap 与 ECharts
- 日志与监控
- 采用
RotatingFileHandler
分片日志,接入 Prometheus/Grafana/ELK 亦可
- 采用
- 模型与推荐
- 推荐逻辑建议以特征向量/相似度为核心抽象,定期离线训练 + 在线召回与重排
联系与交流
如需技术交流、合作或问题反馈:
联系方式:码界筑梦坊各大平台同名
欢迎 Star、Fork 与 Issue 共同完善项目!