基于Flask的城市共享单车借还数据分析与预测系统设计与实现
基于Flask的城市共享单车借还数据分析与预测系统设计与实现 毕业论文
毕业设计
一、项目名称:
基于Flask的城市共享单车借还数据分析与预测系统设计与实现
【摘要】
城市共享单车借还具有明显的时段潮汐、站点类型差异与运营商分流特征,仅靠表格浏览难以快速把握站点热度、借还不均衡、骑行时长与天气影响。本文设计并实现基于 Flask 的城市共享单车借还数据分析与预测系统,面向毕业设计与教学演示,将运营区、借还站点与小时级借还时序统一入库后,以交互式图表完成多维可视化,并以随机森林完成一键借还量预测,辅以智谱大模型问答与自研后台维护。
系统采用 B/S 架构,后端入口为 app.py,运行端口 8080;数据库使用 MySQL(库名 bikeshare),经 PyMySQL 访问。前台基于 Bootstrap、本地 static/vendor 中的 ECharts,配合 bike-theme.css 主题,登录背景为 bike-bg.jpg。核心业务表包括 tbl_user、bike_zones、bike_stations、bike_hourly(含 rent_count/return_count/total_trips/avg_duration_min/imbalance),以及 predictions、models、system_logs。可视化聚合在 utils/bike_viz_charts.py 中按城市、运营区、月份输出图表 bundle,并带短时缓存;随机森林预测由 models/random_forest_model.py 实现,页面路径 /bike/rf_predict;AI 助手类为 BikeAIAssistant,调用智谱 OpenAI 兼容接口,默认模型 glm-4-flash。后台为自研 CRUD(utils/admin_blueprint.py),路径 /admin/,独立登录页 /admin/login,覆盖用户、运营区、借还站点、小时借还四类数据。默认账号 admin/admin123。前台登录表单字段为 userName,会话键为 session["userName"]。主数据来自 UCI Bike Sharing Dataset(hour.csv)映射导入,推荐导入后约六万条小时级借还记录。
测试与运行表明,系统可完成登录注册、首页 KPI 总览、六类借还可视化、数据总览、随机森林预测、AI 问答与后台维护等闭环,界面清晰、响应稳定,可为共享单车借还分析课题研究与教学演示提供可用支撑。
【关键词】 Flask;共享单车;借还数据分析;随机森林;ECharts
【Abstract】
Urban bike-sharing rentals and returns show strong tidal patterns by hour, station type and operator, making spreadsheet browsing inefficient. This thesis designs and implements a Flask-based bike-sharing rental–return analysis and prediction system for graduation design and teaching demos. Zone, station and hourly trip data are stored in MySQL and explored through interactive charts, with one-click Random Forest forecasting, Zhipu LLM Q&A and a custom admin backend.
The system follows a B/S architecture. The entry is app.py on port 8080. MySQL database name is bikeshare, accessed via PyMySQL. The frontend uses Bootstrap, local ECharts under static/vendor, and bike-theme.css with login background bike-bg.jpg. Core tables include tbl_user, bike_zones, bike_stations, bike_hourly (rent_count/return_count/total_trips/avg_duration_min/imbalance), plus predictions, models and system_logs. Visualization bundles are built in bike_viz_charts.py with short TTL cache. Random Forest forecasting is implemented in random_forest_model.py at /bike/rf_predict. The AI assistant class BikeAIAssistant uses Zhipu’s OpenAI-compatible API with default model glm-4-flash. Admin CRUD is custom (admin_blueprint.py) at /admin/ with independent login /admin/login. Default account is admin/admin123. Frontend login uses form field userName and session key userName. Primary data are mapped from the UCI Bike Sharing Dataset (hour.csv), yielding about 60,000 hourly records after recommended import.
Results show that authentication, home KPI overview, multi-dimensional rental–return visualization, data overview, Random Forest prediction, AI assistant and admin maintenance work stably for course demos.
【Keywords】 Flask; Bike Sharing; Rental-Return Analysis; Random Forest; ECharts
目 录
- 2.1 Python编程语言
- 2.2 Flask Web框架
- 2.3 MySQL与PyMySQL
- 2.4 pandas与scikit-learn随机森林
- 2.5 ECharts与bike-theme
- 2.6 智谱AI与技术特色
- 4.0 系统整体实现流程
- 4.1 用户认证模块的实现
- 4.2 借还多维可视化模块的实现
- 4.3 数据总览模块的实现
- 4.4 随机森林借还量预测模块的实现
- 4.5 AI智能助手模块的实现
- 4.6 后台数据管理模块的实现
- 4.7 用户界面实现
- 4.8 系统集成与部署
1 绪 论
1.1 课题研究背景
共享单车借还量是城市慢行交通调度与网点运维的重要依据。站点类型(地铁接驳、商圈、校园、景区、居住区、办公区)、运营商分流、时段潮汐、天气与节假日等因素交织,使借车量与还车量呈现显著周期性与空间差异。对教学与课题研究而言,若仅依赖表格逐行浏览,难以从站点热度、潮汐不均衡、骑行时长、运营商对比、借还时序与天气关联等维度形成整体认识。与此同时,毕业设计场景需要一套可本地部署、结构清晰、图表可读的系统,既要能装载可演示的小时级借还数据,也要能给出可解释的短期预测结果。
本课题据此构建「基于Flask的城市共享单车借还数据分析与预测系统设计与实现」:以 Flask 提供页面与 JSON 接口,以 MySQL 库 bikeshare 持久化运营区、站点与小时借还,以 ECharts 完成多页可视化看板,以 scikit-learn 随机森林完成一站式训练与预测,并以智谱 glm-4-flash 提供借还分析问答。系统入口 app.py 监听 8080 端口;侧栏覆盖首页总览、六类借还可视化、数据总览、随机森林预测与 AI 助手;管理端为自研 /admin/ CRUD。主数据采用 UCI Bike Sharing Dataset(Capital Bikeshare,data/raw/hour.csv)映射到中文运营区与站点,借还随时间与天气的变化来自公开真实时序。该背景决定了后续技术选型必须兼顾轻量部署、图表交互与预测可演示性。
1.2 课题研究的目的、意义
1.2.1 研究目的
- 建立统一的共享单车业务数据模型(用户、运营区、借还站点、小时借还),完成
bikeshare.sql建库与 UCI/演示数据初始化。 - 实现前台登录鉴权与侧栏多页面分析,按城市、运营区、月份等条件筛选后输出图表 bundle。
- 实现基于随机森林的借还量预测页面,一次请求完成拉数、训练、指标评估与多步预测展示。
- 提供智谱 AI 助手与自研后台对用户、运营区、站点、小时借还四类业务表的增删改查,保证数据可维护、图表可刷新。
1.2.2 研究意义
理论意义上,课题将 Web 应用分层、聚合查询、机器学习回归与大模型问答结合起来,形成可复用的「页面路由 + bundle API + 预测服务」模式。实践意义上,系统可在课堂或答辩环境中一键演示可视化与预测链路,降低对外部商业平台的依赖。社会与教学意义上,有助于理解共享单车借还的时空潮汐、运营商差异与天气影响,培养数据处理、可视化工程与预测建模能力。
1.3 课题的国内外研究现状和发展动态
1.3.1 国外研究现状
国外在共享单车需求预测、站点再平衡与交互可视化方面积累较早。常见路径是将公开小时聚合或订单明细导入数据仓库,再以 BI 工具或自研 Web 看板呈现站点热度与高峰特征。UCI Bike Sharing Dataset 等公开集被广泛用于教学与方法对比。预测方面,统计模型与机器学习(含随机森林、梯度提升等)被用于短时需求估计;深度学习模型在数据充足时表现突出,但对算力与样本质量要求更高。课题级系统往往在准确率与实现成本之间折中,选用可解释、训练成本低的集成学习即可满足演示需求。
1.3.2 国内研究现状
国内高校毕业设计中,基于 Flask/Django 的共享出行或借还可视化课题较多,常见组合为 MySQL + ECharts,辅以 pandas 做预处理。部分课题引入 ARIMA、LSTM 等时序模型作为对比,但部署与调参成本较高。管理端有的使用 Django Admin / SimpleUI,有的自研轻量 CRUD。本课题选择 Flask + 自研 /admin/,前台交付以随机森林一键预测为主,与 bike-theme 统一视觉,业务语义固定为运营区—站点—小时借还,避免套用其他交通课题菜单。
1.3.3 发展趋势
趋势上,借还分析正向「入库—缓存—交互可视化—在线预测—智能问答」一体化演进;前端强调本地化静态资源与弱网可用;预测服务强调一次请求返回指标与图表。本系统在可视化 bundle TTL、随机森林时间留出评估、UCI 真实时序映射导入与智谱免费模型接入等方面体现了上述工程趋势。
1.4 研究内容
研究内容包括:(1)库表设计与 bikeshare.sql 初始化;(2)Flask 路由、Session 登录与侧栏菜单;(3)bike_viz_charts 各可视化 bundle 与筛选条件;(4)随机森林特征构造、训练评估与滚动多步预测;(5)智谱 AI 助手(BikeAIAssistant)接入;(6)自研后台 CRUD(zones/stations/hourly);(7)功能与性能层面的验证。创新点集中在:首页五 KPI + 潮汐 TOP + 运营商 + 24h 曲线、六维借还可视化(站点热度/潮汐不均衡/骑行时长/运营商对比/借还时序/天气影响)+ 版本缓存、随机森林一站式预测页、与前台统一主题的自研后台,以及智谱 glm-4-flash 借还问答。
1.5 论文结构安排
第1章介绍背景、目的意义、研究现状与研究内容。第2章说明 Python、Flask、MySQL/PyMySQL、pandas/sklearn、ECharts 与智谱 AI 等相关技术。第3章给出架构、数据流、功能结构、六大模块详细设计与数据库设计。第4章按模块阐述实现流程、核心代码、访问路径与界面图题。第5章给出功能测试用例与性能分析。第6章总结量化成果并展望改进方向。文末为参考文献与致谢。
2 相关技术
2.1 Python编程语言
2.1.1 语言特性与项目选型
Python 语法简洁,生态覆盖 Web、数据处理与机器学习。本项目使用 Python 3.11,依赖见 requirements.txt:Flask、PyMySQL、pandas、numpy、scikit-learn、requests、python-dotenv 等。业务脚本与工具模块均以 UTF-8 源码组织,便于在 Windows 环境下维护。
2.1.2 在本系统中的应用位置
app.py 负责路由与会话;utils/db.py 封装连接与查询;utils/bike_viz_charts.py、utils/index_data.py、models/random_forest_model.py、utils/ai_assistant.py、utils/admin_blueprint.py 分别承担图表聚合、首页看板、随机森林预测、AI 问答与后台。启动时通过 utils/data_initializer.py 的 auto_initialize_data 在空库场景下优先调用 UCI 导入,无源文件时再回退规则模拟。
2.2 Flask Web框架
2.2.1 轻量路由与会话
Flask 以装饰器注册路由,适合中小型课题。本系统用 session 保存 userName、avatar_url、is_admin;before_request 对未登录访问重定向 /login,访问 /admin 且未登录则跳转 /admin/login。根路径 / 与 /login 共用登录视图。
2.2.2 Blueprint 扩展后台
后台以 Blueprint admin_bp 挂载于 /admin,与主应用解耦。页面模板与前台共用 bike-theme 资源,权限通过 admin_required 校验管理员会话,未满足则携带 next 跳转独立后台登录页。
2.3 MySQL与PyMySQL
2.3.1 存储选型
业务数据存放于 MySQL 库 bikeshare,字符集 utf8mb4。config.py 中 DB_NAME 默认 bikeshare,可通过 .env 覆盖。表结构由 bikeshare.sql 创建,并预置 admin/admin123 与运营区、站点种子。
2.3.2 访问封装
utils/db.py 使用 PyMySQL 执行参数化 SQL,query(sql, params, mode) 支持查询与写入。图表、预测与后台列表均通过参数绑定访问,降低拼接风险。bike_hourly 对站点、运营区、时间建立外键与常用索引,支撑按城市/运营区/月份筛选。
2.4 pandas与scikit-learn随机森林
2.4.1 数据处理
预测链路用 pandas 将查询结果整理为含 datetime、total_trips(内部映射为 total_flow 目标列)的升序表,清洗异常值并裁剪负值。可视化侧借助聚合 SQL 直接产出图表序列,减少前端计算负担。UCI 导入脚本 scripts/import_uci_bikeshare.py 亦使用 pandas 读取 hour.csv 并展开到各站点。
2.4.2 随机森林回归
RandomForestPredictor 基于 sklearn.ensemble.RandomForestRegressor:以过去 lookback 个借还量点、小时、星期及小时正弦/余弦为特征,按时间顺序留出后 20% 评估 MAE/RMSE/R²,再对未来多步滚动预测。该方案训练快、可解释性较好,适合课题演示。前台交付以随机森林为主,不以 ARIMA/LSTM 作为主推演示路径。
2.5 ECharts与bike-theme
2.5.1 本地化静态资源
模板 base.html 引用 static/vendor 下 Bootstrap、Bootstrap Icons 与 ECharts 等本地资源,避免依赖外网 CDN,保证离线演示可用。主题样式集中在 static/css/bike-theme.css;登录/注册页背景使用 static/img/bike-bg.jpg。
2.5.2 图表交互约定
可视化页通过 static/js/bike_viz_pages.js、bike_chart_helpers.js 拉取 JSON 并渲染柱状图、折线图、饼图等;提示框使用系列名展示,避免出现无意义的 series0 文案。站点热度等 TOP 类图表保证类目名与数值一致。
2.6 智谱AI与技术特色
2.6.1 智谱 glm-4-flash
utils/ai_assistant.py 中 BikeAIAssistant 通过 OpenAI 兼容接口 POST {ZHIPU_BASE_URL}/chat/completions 调用智谱模型,默认 glm-4-flash。密钥写入项目 .env(ZHIPU_API_KEY),不写入论文交付文案。系统提示词约束回答紧扣共享单车借还业务(潮汐、运营商、骑行时长等)。免费档适合一问一答演示。
2.6.2 技术特色与创新点
可视化 bundle + 短缓存:bike_viz_charts 以 _cache["version"] 控制失效,TTL 约 120 秒,后台写操作后调用 invalidate_viz_cache(),并联动清空首页缓存。
首页借还看板:utils/index_data.py 提供五 KPI(总借、总还、平均时长、潮汐预警站点数、运营商数)、今日潮汐 TOP、运营商占比饼图与近 30 日平均 24h 借还曲线。
随机森林一站式预测:/bike/api/rf_predict 一次返回历史曲线、预测曲线与评估指标,降低多页面跳转成本。
自研后台:非 Flask-Admin / SimpleUI,按 admin_registry.MODULES 声明式配置列表列与表单字段(users/zones/stations/hourly)。
前后台登录分离:前台 /login(表单字段 userName),后台 /admin/login,避免管理入口与普通用户入口混淆。
资源本地化与主题统一:vendor 本地化 + bike-theme.css,前后台视觉一致。
UCI 真实时序映射:保留公开数据集的小时曲线与天气关系,映射到杭州/北京/上海中文站点演示配置。
3 系统分析与设计
3.1 系统总体设计
3.1.1 系统架构设计
系统采用表现层、业务逻辑层与数据访问层三层结构。表现层为 Jinja2 模板与可视化/预测前端脚本;业务层包括鉴权、首页看板、图表 bundle、随机森林预测、AI 助手与后台 CRUD;数据层为 MySQL bikeshare。
图3.1 系统架构图
3.1.2 系统数据流设计
外部角色包括前台用户与管理员。系统输出页面 HTML 与图表/预测 JSON,并将后台维护结果写入数据库;AI 问答依赖智谱接口返回文本。
图3.2 顶层数据流图
图3.3 0层数据流图
3.1.3 系统功能模块设计
结合侧栏与后台菜单,功能划分为六大模块:(1)用户认证;(2)借还多维可视化;(3)数据总览;(4)随机森林借还量预测;(5)AI智能助手;(6)后台数据管理。首页看板作为可视化入口的补充,在实现章与界面节说明;六类可视化页面归属模块(2)。
图3.4 系统功能结构图
3.2 系统详细设计
3.2.1 用户认证模块设计
模块提供 /login、/register、/logout。登录校验 tbl_user 表用户名与密码(演示环境明文存储,与课题默认账号一致);成功后写入 session["userName"],并可写入头像与 is_admin。注册校验两次密码一致与用户名唯一。before_request 对未登录访问重定向登录页;若目标为 /admin,则跳转 /admin/login。默认账号 admin/admin123。前台登录表单字段名为 userName。个人中心 /profile 支持改密与头像上传(/upload_avatar)。
3.2.1.1 用户认证流程设计
图3.5 用户认证模块流程图
3.2.2 借还多维可视化模块设计
模块覆盖侧栏六页与首页看板:站点热度 /bike/station_heat、潮汐不均衡 /bike/tide_imbalance、骑行时长 /bike/ride_duration、运营商对比 /bike/operator_compare、借还时序 /bike/flow_trend、天气影响 /bike/weather_flow;首页 /index 由 get_home_dashboard() 直接渲染 KPI 与图表数据。公共筛选项接口 /bike/api/viz/options,各页分别调用对应 bundle API(如 /bike/api/viz/station-heat)。筛选维度为城市、运营区(zone_id,兼容旧参数 line_id)、月份;_where 在已选运营区时以 zone_id 为准、不再叠加城市条件,前端 bike_viz_pages.js 按城市联动运营区并自动对齐城市,避免「城市与运营区不一致」导致空图。聚合逻辑集中在 utils/bike_viz_charts.py,带版本缓存。
3.2.2.1 借还多维可视化流程设计
图3.6 借还多维可视化模块流程图
3.2.3 数据总览模块设计
数据总览页 /data_preview 面向表格化浏览与核对,展示小时借还记录的关键字段(站点、时间、借车、还车、总量、潮汐差、平均时长、小时、周末/节假日等),支持按站点名与日期筛选并分页查看,便于答辩时核对库内样本是否齐全。该页不替代六类图表分析,而是作为“看得见数据”的清单入口。
3.2.3.1 数据总览流程设计
图3.7 数据总览模块流程图
3.2.4 随机森林借还量预测模块设计
预测页 /bike/rf_predict 选择站点、预测步数与 lookback 后,调用 /bike/api/rf_predict。服务端从 bike_hourly 拉取最近最多 2000 条小时序列(目标字段 total_trips),构造滞后特征与日历特征,训练 RandomForestRegressor,用时间留出集计算 MAE/RMSE/R²,再滚动预测未来若干小时,返回历史与预测曲线数据供 ECharts 展示。步数限制约 6–168,lookback 约 12–72。
3.2.4.1 随机森林借还量预测流程设计
图3.8 随机森林借还量预测模块流程图
3.2.5 AI智能助手模块设计
助手页 /bike/ai_assistant,接口 /bike/api/ai_ask。后端 BikeAIAssistant.ask 组装 system/user/assistant 消息,请求智谱 chat/completions,默认模型 glm-4-flash。用于解答潮汐不均衡、调度建议、站点热度、运营商对比、天气与骑行时长、随机森林指标含义等问题。未配置 ZHIPU_API_KEY 时返回明确提示。
3.2.5.1 AI智能助手流程设计
图3.9 AI智能助手模块流程图
3.2.6 后台数据管理模块设计
/admin/login 为独立后台登录;登录成功后进入 /admin/ 概览。子模块覆盖 users、zones、stations、hourly,对应表 tbl_user、bike_zones、bike_stations、bike_hourly,支持列表搜索、创建、编辑、删除。写操作后调用 invalidate_viz_cache()。权限要求会话为管理员(账号 admin 或 is_admin=1)。非 Flask-Admin、非 SimpleUI。菜单定义见 utils/admin_registry.py 的 ADMIN_MENU 与 MODULES。
3.2.6.1 后台数据管理流程设计
图3.10 后台数据管理模块流程图
3.3 数据库设计
3.3.1 数据库关系设计
数据库名为 bikeshare。交付核心业务表:tbl_user(系统账号)、bike_zones(运营区)、bike_stations(借还站点)、bike_hourly(小时借还)。辅助表:models(模型信息)、predictions(预测结果)、system_logs(系统日志)。站点通过 zone_id 关联运营区,小时借还通过 station_id/zone_id 关联站点与运营区。SQL 中建立外键约束,保证演示数据引用完整。建库脚本为 bikeshare.sql;小时时序由 UCI 导入或启动初始化写入。
图3.11 数据库表关系图
表3.1 tbl_user 表结构
| 字段名称 | 字段类型 | 字段说明 | 是否主键 | 是否为空 |
|---|---|---|---|---|
| id | INT | 自增主键 | 是 | 否 |
| user_name | VARCHAR(50) | 用户名(唯一) | 否 | 否 |
| password | VARCHAR(255) | 密码 | 否 | 否 |
| VARCHAR(100) | 邮箱 | 否 | 是 | |
| avatar | VARCHAR(255) | 头像路径 | 否 | 是 |
| is_admin | TINYINT(1) | 是否管理员 | 否 | 是 |
| created_at | DATETIME | 创建时间 | 否 | 是 |
| updated_at | DATETIME | 更新时间 | 否 | 是 |
表3.2 bike_zones 表结构
| 字段名称 | 字段类型 | 字段说明 | 是否主键 | 是否为空 |
|---|---|---|---|---|
| zone_id | VARCHAR(20) | 运营区 ID | 是 | 否 |
| zone_name | VARCHAR(50) | 运营区名称 | 否 | 否 |
| city | VARCHAR(50) | 所属城市 | 否 | 否 |
| station_count | INT | 站点数 | 否 | 是 |
| coverage_km2 | DECIMAL(10,2) | 覆盖面积(平方公里) | 否 | 是 |
| opened_on | DATE | 开通日期 | 否 | 是 |
| created_at | DATETIME | 创建时间 | 否 | 是 |
表3.3 bike_stations 表结构
| 字段名称 | 字段类型 | 字段说明 | 是否主键 | 是否为空 |
|---|---|---|---|---|
| station_id | VARCHAR(20) | 站点 ID | 是 | 否 |
| station_name | VARCHAR(100) | 站点名称 | 否 | 否 |
| zone_id | VARCHAR(20) | 所属运营区 ID | 否 | 否 |
| city | VARCHAR(50) | 所属城市 | 否 | 否 |
| station_type | VARCHAR(20) | 站点类型 | 否 | 否 |
| capacity | INT | 车桩容量 | 否 | 是 |
| operator | VARCHAR(20) | 运营商 | 否 | 否 |
| is_hub | TINYINT(1) | 是否枢纽 | 否 | 是 |
| latitude | DECIMAL(10,6) | 纬度 | 否 | 是 |
| longitude | DECIMAL(10,6) | 经度 | 否 | 是 |
| station_order | INT | 区内顺序 | 否 | 是 |
| created_at | DATETIME | 创建时间 | 否 | 是 |
表3.4 bike_hourly 表结构
| 字段名称 | 字段类型 | 字段说明 | 是否主键 | 是否为空 |
|---|---|---|---|---|
| id | BIGINT | 自增主键 | 是 | 否 |
| datetime | DATETIME | 日期时间 | 否 | 否 |
| station_id | VARCHAR(20) | 站点 ID | 否 | 否 |
| zone_id | VARCHAR(20) | 运营区 ID | 否 | 否 |
| city | VARCHAR(50) | 城市 | 否 | 否 |
| rent_count | INT | 借车量 | 否 | 是 |
| return_count | INT | 还车量 | 否 | 是 |
| total_trips | INT | 借+还总量 | 否 | 是 |
| avg_duration_min | DECIMAL(8,2) | 平均骑行时长(分钟) | 否 | 是 |
| imbalance | INT | 借−还(潮汐差) | 否 | 是 |
| hour | INT | 小时(0-23) | 否 | 是 |
| day_of_week | INT | 星期几 | 否 | 是 |
| is_holiday | TINYINT(1) | 是否节假日 | 否 | 是 |
| is_weekend | TINYINT(1) | 是否周末 | 否 | 是 |
| weather | VARCHAR(20) | 天气状况 | 否 | 是 |
| temperature | DECIMAL(5,2) | 温度(℃) | 否 | 是 |
| created_at | DATETIME | 创建时间 | 否 | 是 |
表3.5 predictions 表结构(摘要)
| 字段名称 | 字段类型 | 字段说明 | 是否主键 | 是否为空 |
|---|---|---|---|---|
| id | BIGINT | 自增主键 | 是 | 否 |
| datetime | DATETIME | 预测时间点 | 否 | 否 |
| station_id | VARCHAR(20) | 站点 ID | 否 | 否 |
| zone_id | VARCHAR(20) | 运营区 ID | 否 | 否 |
| predicted_trips | INT | 预测借还量 | 否 | 是 |
| actual_trips | INT | 实际借还量 | 否 | 是 |
| model_name | VARCHAR(50) | 模型名称 | 否 | 是 |
表3.6 models / system_logs 表结构(摘要)
models 保存模型名称、类型、MAE/RMSE/R²、训练样本量与状态等;system_logs 保存用户名、操作、模块、详情、IP 与时间,用于运维审计扩展。
种子数据方面:bikeshare.sql 预置 8 个运营区、42 个借还站点(杭州西湖/拱墅/上城/余杭及北京海淀/朝阳、上海徐汇/浦东),运营商为哈啰/美团/青桔。小时借还不在 SQL 中硬编码全量,而由 scripts/import_uci_bikeshare.py 或启动自动初始化写入;推荐 python scripts/import_uci_bikeshare.py --days 60 --force 后,按站点展开约六万条小时记录。
4 系统实现
4.0 系统整体实现流程
实现按「环境与库表 → 鉴权与壳页 → 首页看板与可视化 bundle → 随机森林预测 → AI 助手 → 自研后台 → 联调」推进。配置集中在 config.py / .env(端口 8080、库 bikeshare)。
图4.0 系统整体实现流程图
4.1 用户认证模块的实现
登录、注册、退出在 app.py 中实现;登录页使用 bike-theme.css 与 bike-bg.jpg 背景,表单字段为 userName、password,以 JSON 返回校验结果。
功能实现流程设计
图4.1 用户认证模块实现流程图
核心代码实现
# 来源:app.py — 前台登录(节选)
@app.route('/', methods=['GET', 'POST'])
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
nxt = (request.args.get('next') or '').strip()
if nxt.startswith('/admin'):
return redirect(url_for('admin.login', next=nxt))
return render_template('login.html')
else:
return_dict = {'code': '200', 'msg': '处理成功', 'result': False}
user = db.query(
"select user_name, avatar, is_admin from tbl_user "
"where user_name = %s and password = %s",
[request.form['userName'], request.form['password']], 'select')
if user:
session['userName'] = request.form['userName']
# 写入头像与 is_admin
return jsonify(return_dict)
return_dict['code'] = '400'
return_dict['msg'] = '用户名和密码不一致'
return jsonify(return_dict)
功能访问路径
- 前台登录:
http://127.0.0.1:8080/login - 注册:
http://127.0.0.1:8080/register - 退出:
http://127.0.0.1:8080/logout - 个人中心:
http://127.0.0.1:8080/profile - 默认账号:
admin/admin123
界面截图见第 4.7 节图4.9。
4.2 借还多维可视化模块的实现
六类可视化页共用筛选项组件与 bundle API;聚合逻辑在 utils/bike_viz_charts.py,前端由 bike_viz_pages.js 渲染(先就绪 options 再请求图表,城市与运营区联动对齐)。首页 /index 调用 get_home_dashboard() 注入 KPI、潮汐 TOP、运营商饼图与 24h 曲线。
功能实现流程设计
图4.2 借还多维可视化模块实现流程图
核心代码实现
# 来源:app.py / utils/bike_viz_charts.py — 站点热度 API(节选)
@app.route('/bike/station_heat')
def bike_station_heat():
return render_template(
'bike_station_heat.html',
userName=session.get('userName'),
active_menu='bike_station_heat',
)
@app.route('/bike/api/viz/station-heat')
@app.route('/bike/api/viz/station-rank')
def bike_api_viz_station_heat():
from utils.bike_viz_charts import station_heat_bundle
a = _viz_args()
return jsonify({
"success": True, "ok": True,
"data": station_heat_bundle(a["city"], a["zone_id"], a["month"])
})
# 来源:utils/index_data.py — 首页看板(节选)
def get_home_dashboard():
# kpi: 总借、总还、平均时长、潮汐预警站点数、运营商数
# tide_top / operator_pie / hourly24
...
功能访问路径
- 首页:
/index - 站点热度:
/bike/station_heat - 潮汐不均衡:
/bike/tide_imbalance - 骑行时长:
/bike/ride_duration - 运营商对比:
/bike/operator_compare - 借还时序:
/bike/flow_trend - 天气影响:
/bike/weather_flow
界面截图见第 4.7 节图4.10~图4.16。
4.3 数据总览模块的实现
数据总览在 app.py 的 /data_preview 路由中实现,查询 bike_hourly 关联 bike_stations 并渲染表格。
功能实现流程设计
图4.3 数据总览模块实现流程图
核心代码实现
# 来源:app.py — 数据总览路由(节选)
@app.route('/data_preview', methods=['GET', 'POST'])
def data_preview():
userName = session.get('userName')
page = request.args.get('page', 1, type=int)
# 按站点名/日期条件查询 bike_hourly JOIN bike_stations
# 组装分页结果后渲染 templates/data_preview.html
return render_template(
'data_preview.html',
userName=userName,
active_menu='data_preview',
# ... tableData, total_count, filters ...
)
功能访问路径
- 数据总览:
http://127.0.0.1:8080/data_preview
界面截图见第 4.7 节图4.17。
4.4 随机森林借还量预测模块的实现
页面 bike_rf_predict.html,算法类位于 models/random_forest_model.py,接口 /bike/api/rf_predict 一次完成训练与预测。
功能实现流程设计
图4.4 随机森林借还量预测模块实现流程图
核心代码实现
# 来源:models/random_forest_model.py — 特征与训练(节选)
class RandomForestPredictor:
def __init__(self, lookback=24, n_estimators=80, random_state=42):
self.lookback = int(lookback)
self.n_estimators = int(n_estimators)
self.model = None
def _feature_row(self, lag_values, ts):
hour = int(ts.hour)
dow = int(ts.dayofweek)
hour_sin = np.sin(2 * np.pi * hour / 24.0)
hour_cos = np.cos(2 * np.pi * hour / 24.0)
return np.asarray(list(lag_values) + [hour, dow, hour_sin, hour_cos], dtype=float)
def train(self, train_data):
# 时间顺序 80%/20% 留出,拟合 RandomForestRegressor
...
# 来源:app.py — 一键预测 API(节选)
@app.route('/bike/api/rf_predict', methods=['POST'])
def bike_api_rf_predict():
from models.random_forest_model import RandomForestPredictor
# 查询 bike_hourly.total_trips → model.train(df) → model.predict(steps)
return jsonify({
'success': True,
'metrics': metrics,
'history': {'labels': hist_labels, 'values': hist_values},
'forecast': {'labels': fut_labels, 'values': fut_values},
})
功能访问路径
- 预测页:
http://127.0.0.1:8080/bike/rf_predict - 预测 API:
POST /bike/api/rf_predict
界面截图见第 4.7 节图4.18。
4.5 AI智能助手模块的实现
页面 bike_ai_assistant.html,服务类 utils/ai_assistant.py 中的 BikeAIAssistant,接口 /bike/api/ai_ask。
功能实现流程设计
图4.5 AI智能助手模块实现流程图
核心代码实现
# 来源:utils/ai_assistant.py — 智谱调用(节选)
class BikeAIAssistant:
def __init__(self):
self.api_key = (os.getenv("ZHIPU_API_KEY") or "").strip()
self.base_url = (os.getenv("ZHIPU_BASE_URL")
or "https://open.bigmodel.cn/api/paas/v4").rstrip("/")
self.model = os.getenv("ZHIPU_MODEL", "glm-4-flash").strip()
def ask(self, question, history=None):
url = f"{self.base_url}/chat/completions"
headers = {"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"}
payload = {"model": self.model, "messages": messages,
"temperature": 0.7, "max_tokens": 2048}
resp = requests.post(url, headers=headers, json=payload, timeout=self.timeout)
...
功能访问路径
- AI 助手:
http://127.0.0.1:8080/bike/ai_assistant - 问答 API:
POST /bike/api/ai_ask
界面截图见第 4.7 节图4.19。
4.6 后台数据管理模块的实现
后台 Blueprint 注册于 app.py:app.register_blueprint(admin_bp)。模块定义见 utils/admin_registry.py,路由见 utils/admin_blueprint.py。
功能实现流程设计
图4.6 后台数据管理模块实现流程图
核心代码实现
# 来源:utils/admin_registry.py — 模块声明(节选)
ADMIN_MENU = [
("index", "数据概览", "bi-speedometer2"),
("users", "用户管理", "bi-people"),
("zones", "运营区", "bi-signpost-2"),
("stations", "借还站点", "bi-geo-alt"),
("hourly", "小时借还", "bi-bar-chart"),
]
MODULES = {
"zones": {"label": "运营区", "table": "bike_zones", ...},
"stations": {"label": "借还站点", "table": "bike_stations", ...},
"hourly": {"label": "小时借还", "table": "bike_hourly", ...},
}
# 来源:utils/admin_blueprint.py — 后台登录与权限(节选)
admin_bp = Blueprint("admin", __name__, url_prefix="/admin")
def admin_required(view):
@wraps(view)
def wrapped(*args, **kwargs):
if not _is_admin_user():
flash("请使用管理员账号登录后台", "warning")
return redirect(url_for("admin.login", next=request.path))
return view(*args, **kwargs)
return wrapped
功能访问路径
- 后台登录:
http://127.0.0.1:8080/admin/login - 后台首页:
http://127.0.0.1:8080/admin/ - 模块:用户 / 运营区 / 借还站点 / 小时借还
界面截图见第 4.7 节图4.20、图4.21。
4.7 用户界面实现
界面基于 templates/base.html 侧栏布局与 bike-theme.css。侧栏分组为「借还洞察」(六类可视化)、「数据与预测」(数据总览、随机森林、AI 助手)、「个人信息」。首页 /index 展示五 KPI、潮汐 TOP、运营商占比与 24h 借还曲线;可视化、预测、AI、后台分别对应独立模板。
功能实现流程设计
图4.7 用户界面功能实现流程图
图4.9 登录界面

(系统运行截图)
图4.10 首页总览界面

(系统运行截图)
图4.11 站点热度界面

(系统运行截图)
图4.12 潮汐不均衡界面

(系统运行截图)
图4.13 骑行时长界面

(系统运行截图)
图4.14 运营商对比界面

(系统运行截图)
图4.15 借还时序界面

(系统运行截图)
图4.16 天气影响界面

(系统运行截图)
图4.17 数据总览界面

(系统运行截图)
图4.18 随机森林预测界面

(系统运行截图)
图4.19 AI助手界面

(系统运行截图)
图4.20 后台管理界面

(系统运行截图)
图4.21 后台登录界面

(系统运行截图)
4.8 系统集成与部署
功能实现流程设计
图4.8 系统集成与部署功能实现流程图
部署步骤简述:
- 安装依赖:
pip install -r requirements.txt - 创建并导入数据库:
bikeshare.sql,确认库名bikeshare - 确认
data/raw/hour.csv存在;推荐执行python scripts/import_uci_bikeshare.py --days 60 --force(约六万条小时记录);空库启动时auto_initialize_data也会尝试 UCI 导入 - 配置
.env(数据库账号、可选ZHIPU_API_KEY) - 启动:
python app.py(端口 8080) - 访问:前台
http://127.0.0.1:8080/login,后台http://127.0.0.1:8080/admin/login,账号admin/admin123
数据来源说明见项目内 data/DATA_SOURCES.md:时序形状来自 UCI Capital Bikeshare 公开小时聚合;中文站点名与运营商为课题演示配置。
5 系统测试
5.1 系统功能测试
5.1.1 用户认证功能测试用例
| 编号 | 说明 | 条件 | 操作步骤 | 预期结果 | 实际结果 |
|---|---|---|---|---|---|
| TC-A01 | 正确登录 | 库中存在 admin/admin123 | 打开 /login,输入 admin/admin123 提交 |
登录成功并进入 /index |
通过 |
| TC-A02 | 错误密码 | 账号存在 | 输入错误密码提交 | 提示用户名和密码不一致 | 通过 |
| TC-A03 | 注册新用户 | 用户名未占用 | /register 填写一致密码并提交 |
注册成功可登录 | 通过 |
| TC-A04 | 未登录拦截 | 清空会话 | 直接访问 /index |
跳转 /login |
通过 |
| TC-A05 | 退出登录 | 已登录 | 点击退出 | 会话清空并回登录页 | 通过 |
5.1.2 数据管理功能测试用例
| 编号 | 说明 | 条件 | 操作步骤 | 预期结果 | 实际结果 |
|---|---|---|---|---|---|
| TC-B01 | 后台登录 | admin 账号 | 打开 /admin/login 登录 |
进入后台概览 | 通过 |
| TC-B02 | 用户列表 | 已登后台 | 打开用户管理 | 显示 tbl_user 列表 | 通过 |
| TC-B03 | 新增运营区 | 已登后台 | 运营区管理中新增一条记录 | 保存成功并可检索 | 通过 |
| TC-B04 | 编辑借还站点 | 已有站点 | 修改站点名称并保存 | 列表显示更新后数据 | 通过 |
| TC-B05 | 小时借还增删 | 已有运营区站点 | 新增/删除 bike_hourly 记录 | 写库成功,可视化缓存失效 | 通过 |
5.1.3 核心业务功能测试用例
| 编号 | 说明 | 条件 | 操作步骤 | 预期结果 | 实际结果 |
|---|---|---|---|---|---|
| TC-C01 | 首页访问 | 已登录 | 打开 /index |
五 KPI、潮汐 TOP、运营商、24h 曲线正常 | 通过 |
| TC-C02 | 站点热度 | 库有借还 | 打开 /bike/station_heat 选筛选 |
图表显示 TOP 站点借还 | 通过 |
| TC-C03 | 潮汐不均衡 | 库有 imbalance | 打开 /bike/tide_imbalance |
潮汐差相关图表可读 | 通过 |
| TC-C04 | 随机森林预测 | 站点历史充足 | /bike/rf_predict 点击预测 |
返回指标与预测曲线 | 通过 |
| TC-C05 | AI 问答 | 已配置 Key | /bike/ai_assistant 提问借还问题 |
返回中文回答 | 通过 |
5.1.4 数据分析功能测试用例
| 编号 | 说明 | 条件 | 操作步骤 | 预期结果 | 实际结果 |
|---|---|---|---|---|---|
| TC-D01 | 骑行时长 | 有 avg_duration_min | /bike/ride_duration |
时长分布/对比图正确 | 通过 |
| TC-D02 | 运营商对比 | 有哈啰/美团/青桔 | /bike/operator_compare |
运营商借还对比正确 | 通过 |
| TC-D03 | 借还时序 | 有小时序列 | /bike/flow_trend |
借/还时序折线可读 | 通过 |
| TC-D04 | 天气影响 | 有 weather 字段 | /bike/weather_flow |
天气维度聚合正确 | 通过 |
| TC-D05 | 数据总览筛选 | 库有记录 | /data_preview 改条件 |
表格按条件刷新 | 通过 |
5.1.5 系统集成功能测试用例
| 编号 | 说明 | 条件 | 操作步骤 | 预期结果 | 实际结果 |
|---|---|---|---|---|---|
| TC-E01 | 前后台联通 | 服务已启动 | 后台改小时借还后刷新可视化 | 图表反映新数据 | 通过 |
| TC-E02 | 后台写后缓存 | 改 bike_hourly | 再打开站点热度 | 结果更新而非旧缓存 | 通过 |
| TC-E03 | 会话共享 | 后台已登录 | 同浏览器打开前台页 | 可正常访问受保护页 | 通过 |
| TC-E04 | 端口与入口 | 本机环境 | python app.py |
监听 8080 可访问 | 通过 |
| TC-E05 | 静态资源本地 | 断外网 | 打开可视化页 | ECharts/样式仍可用 | 通过 |
5.1.6 用户界面功能测试用例
| 编号 | 说明 | 条件 | 操作步骤 | 预期结果 | 实际结果 |
|---|---|---|---|---|---|
| TC-F01 | 侧栏高亮 | 已登录 | 依次点击各菜单 | active 状态与页面一致 | 通过 |
| TC-F02 | 主题样式 | 已登录 | 查看首页与后台 | bike-theme 与 bike-bg 生效 | 通过 |
| TC-F03 | 图表悬停 | 可视化页 | 鼠标悬停系列 | tip 显示名称与数值 | 通过 |
| TC-F04 | 预测页控件 | 预测页 | 改步数再预测 | 曲线长度随步数变化 | 通过 |
| TC-F05 | 后台登录页 | 未登后台 | 打开 /admin/login |
独立登录界面展示 | 通过 |
5.2 系统性能测试
5.2.1 响应时间性能分析
在本地演示数据规模(约六万条小时借还记录)下,登录接口与普通页面渲染通常在数百毫秒内完成;可视化 bundle 首次查询受 SQL 聚合影响,二次访问因 TTL 缓存明显加快;随机森林一键预测受样本长度与 n_estimators=80 影响,一般可在数秒内返回,满足课题演示。
5.2.2 并发性能测试
课题场景以单人/少量并发为主。Flask 开发服务器适合演示;若需更高并发,可改为 Waitress/gunicorn 等 WSGI 部署,并对可视化查询加索引与缓存。智谱免费档存在 RPM 限制,AI 助手宜一问一答演示。
5.2.3 数据库性能测试
bike_hourly 在 datetime、station_id、zone_id、city 及 (datetime, station_id) 等字段建有索引,支撑按城市/运营区/月份筛选。站点与运营区外键保证引用完整。大批量 UCI 导入时走批量写入,避免逐条插入拖慢初始化。
5.2.4 性能优化措施
- 可视化 bundle 短时缓存(约 120 秒)与版本失效;首页看板 TTL 约 90 秒。
- 预测接口限制历史条数上限(2000)与步数/lookback 范围,控制训练耗时。
- 静态资源本地化,减少外网依赖。
- 后台写操作后主动
invalidate_viz_cache()(联动首页缓存),避免脏读与过久缓存并存。 - SQL 参数化与必要索引,降低全表扫描概率。
6 总结与展望
6.1 总结
本文完成了基于 Flask 的城市共享单车借还数据分析与预测系统的设计与实现。系统以 MySQL 库 bikeshare 存储用户、运营区、借还站点与小时借还时序,前台提供登录鉴权、首页五 KPI 看板、六类借还可视化、数据总览、随机森林一键预测与智谱 AI 助手(BikeAIAssistant / glm-4-flash),后台提供独立登录与用户/运营区/站点/小时借还四类 CRUD。功能模块约六大业务模块(认证、可视化、总览、预测、AI、后台),入口 app.py 运行于端口 8080,默认账号 admin/admin123。主数据来自 UCI Bike Sharing Dataset 映射导入,推荐规模约六万条小时记录。实践表明,该方案结构清晰、部署轻量,能够支撑毕业设计答辩与教学演示。
6.2 展望
后续可在不改变现有交付主线的前提下,扩展更细粒度的再平衡策略仿真、优化随机森林特征与超参搜索,并将 AI 助手与库内聚合统计做更深度的数据接地,使问答回答更具业务针对性。生产环境可进一步强化密码哈希、权限分级与 WSGI 部署。若引入真实城市订单明细,可在保持表结构语义的前提下替换导入脚本,使站点地理与运营指标更贴近实际运维场景。
参考文献
[1] 张海藩, 牟永敏. 软件工程导论[M]. 北京: 清华大学出版社, 2013.
[2] Grinberg M. Flask Web Development[M]. 2nd ed. Sebastopol: O’Reilly Media, 2018.
[3] 王珊, 萨师煊. 数据库系统概论[M]. 北京: 高等教育出版社, 2014.
[4] McKinney W. Python for Data Analysis[M]. 3rd ed. Sebastopol: O’Reilly Media, 2022.
[5] Pedregosa F, et al. Scikit-learn: Machine Learning in Python[J]. Journal of Machine Learning Research, 2011, 12: 2825-2830.
[6] Breiman L. Random Forests[J]. Machine Learning, 2001, 45(1): 5-32.
[7] Apache ECharts 官方文档[EB/OL]. https://echarts.apache.org/
[8] 智谱 AI 开放平台文档[EB/OL]. https://open.bigmodel.cn/
[9] Fanaee-T H, Gama J. Event labeling combining ensemble detectors and background knowledge[J]. Progress in Artificial Intelligence, 2014.(UCI Bike Sharing Dataset 相关)
[10] UCI Machine Learning Repository: Bike Sharing Dataset[EB/OL]. https://archive.ics.uci.edu/dataset/275/bike+sharing+dataset
[11] 李航. 统计学习方法[M]. 北京: 清华大学出版社, 2019.
[12] PyMySQL Documentation[EB/OL]. https://pymysql.readthedocs.io/
[13] Flask Documentation[EB/OL]. https://flask.palletsprojects.com/
致谢
本科阶段的学习与本次毕业设计即将告一段落。感谢指导老师在选题、系统设计与论文撰写过程中给予的耐心指导与严格要求,使课题能够紧扣现有代码实现,避免空泛论述。感谢同学们在联调演示、界面核对与问题讨论中提供的帮助。感谢家人一直以来的理解与支持。通过本系统的开发,对 Flask Web 开发、MySQL 数据建模、ECharts 可视化与随机森林借还量预测有了更完整的实践认识。文中若有不足之处,恳请各位老师批评指正。
更多推荐

所有评论(0)