110-基于Flask的电信用户流失信息分析系统

基于 Flask 的电信用户流失信息分析系统:从零到一的实战分享

一套可落地的企业级客户流失分析与预测系统,覆盖数据建模、可视化大屏、权限体系、预测训练全流程。

目录

  • 背景与目标
  • 功能总览与系统截图说明
  • 技术栈与架构设计
  • 项目目录结构说明
  • 核心功能与关键代码
    • 鉴权与权限控制
    • 客户数据管理(导入/导出/搜索筛选)
    • 数据分析与可视化
    • 机器学习训练与预测
    • 仪表盘与业务指标
  • 安装部署与初始化
  • 可视化展示占位(可替换为实际效果)
  • 常见问题与优化建议
  • 结语与联系
  • 毕业设计必备章节
    • 需求分析
    • 系统设计(架构/模块/流程)
    • 数据库设计(表结构)
    • API 设计与说明
    • 实验与评估(指标与结果)
    • 创新点与难点攻关
    • 答辩要点与演示脚本

背景与目标

电信行业天然具备高频、长周期、强服务属性的特征,客户流失(Churn)预警与挽留是降本增效的重要抓手。本项目面向实际业务场景,提供:

  • 客户全量信息管理与批量导入导出
  • 多维度统计分析与趋势洞察
  • 机器学习模型训练与在线预测
  • 角色/权限/日志等通用后台能力

目标是开箱即用、易扩展、可自定义,既适合教学演示,也能作为中小业务的落地骨架。


功能总览与系统截图说明

实际功能(依据前端模板与后端接口实现):

  • 客户管理:新增、编辑、删除、分页搜索、条件筛选、批量导入(Excel/CSV)、批量导出
  • 数据分析与可视化:流失率、合同/服务维度对比,在网时长/月费与流失关系趋势图,洞察卡片
  • 预测中心:单客户预测、批量预测、模型训练、训练历史、预测历史、模型性能指标展示
  • 系统管理:用户/角色/权限、操作日志、账户安全(修改资料/密码、找回密码)
  • 仪表盘:核心 KPI(客户数、流失数、流失率、平均月费)、最新流失客户、最近活动日志、常用维度图表

注:运行后可在浏览器访问首页与各业务页面进行体验。本文档末尾提供部署步骤。

💕项目源码获取,码界筑梦坊各平台同名,博客底部含联系方式卡片,欢迎咨询!






























技术栈与架构设计

  • 后端与框架

    • Flask、Blueprint 模块化
    • Flask-SQLAlchemy(ORM)、Flask-Migrate(迁移)
    • Flask-Login、Flask-JWT-Extended(鉴权/令牌)
    • Flask-WTF(表单校验)、Flask-RESTful(API)
    • CORS、Mail、Bcrypt 等常用扩展
  • 数据库

    • 默认 SQLite,可切换 MySQL/PostgreSQL
    • 驱动:PyMySQL
  • 数据分析与机器学习

    • NumPy、Pandas、Scikit-learn
    • Matplotlib、Seaborn(后端图表生成)
  • 前端与可视化

    • Jinja2 模板渲染
    • Bootstrap(样式与布局)
    • Chart.js(前端图表)
    • AOS 动画、FontAwesome 图标
  • 部署

    • Gunicorn + Nginx(生产),.env 配置

Jinja2渲染/HTTP 用户/浏览器 Flask 应用 Blueprint: main/auth/customer/analysis/prediction/admin API v1: auth/customers Service/Logic SQLAlchemy ORM 数据库: SQLite/MySQL/PostgreSQL Sklearn Pipeline: 训练/预测 静态模型文件 .pkl Chart.js 可视化 Extensions: Login/JWT/Migrate/Mail/CORS


项目目录结构说明

text 复制代码
code/
├─ app/
│  ├─ templates/
│  │  ├─ main/                # 仪表盘与首页
│  │  ├─ auth/                # 登录/注册/重置密码
│  │  ├─ customer/            # 客户管理(列表/新增/编辑/导入/查看)
│  │  ├─ analysis/            # 数据分析(概览/流失分析)
│  │  ├─ visualization/       # 可视化大屏(流失概览、服务影响、时长分布)
│  │  ├─ prediction/          # 预测中心(训练/预测/历史/批量结果)
│  │  └─ admin/               # 系统管理(用户/角色/日志/系统设置)
│  ├─ static/                 # 静态资源(样式、脚本、图片)
│  ├─ models.py               # 数据模型(User/Role/Customer/Log 等)
│  ├─ views/                  # 各模块蓝图(auth/customer/prediction/...)
│  ├─ forms.py                # 表单定义(Flask-WTF)
│  └─ __init__.py             # 应用工厂
├─ migrations/                # 数据库迁移记录
├─ data/                      # 数据样例/导入导出目录
├─ docs/                      # 文档与示例
├─ app.py                     # 开发启动入口
├─ wsgi.py                    # 生产入口(gunicorn 使用)
├─ requirements.txt           # 依赖列表
├─ create_tables.py           # 初始化表结构脚本
├─ update_roles.py            # 初始化/更新角色权限脚本
├─ generate_mock_data.py      # 生成大规模模拟数据
└─ quick_generate_data.py     # 快速生成少量模拟数据

实际文件路径以本仓库为准,以上为核心目录与职责的说明性视图。


核心功能与关键代码

鉴权与权限控制(位运算权限)

角色与权限采用位掩码(Bitmask)实现,页面渲染与后端接口双重校验。在前端模板中可以看到权限判断:

jinja2 复制代码
{# app/templates/customer/index.html #}
{% if current_user.can(Permission.EDIT) %}
  <a href="{{ url_for('customer.create') }}" class="btn-action btn-primary">
    <i class="fas fa-plus"></i>
    <span>添加客户</span>
  </a>
  <a href="{{ url_for('customer.import_data') }}" class="btn-action btn-success">
    <i class="fas fa-file-import"></i>
    <span>导入数据</span>
  </a>
{% endif %}
<a href="{{ url_for('customer.export_data') }}" class="btn-action btn-info">
  <i class="fas fa-file-export"></i>
  <span>导出数据</span>
</a>

配合后端模型的 User.can() 方法,可以精准控制页面按钮与接口权限。

后端基于装饰器进行二次防护:

python 复制代码
# app/decorators.py
from functools import wraps
from flask import abort
from flask_login import current_user
from app.models.role import Permission

def permission_required(permission):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if not current_user.can(permission):
                abort(403)
            return f(*args, **kwargs)
        return decorated_function
    return decorator
客户数据管理(导入/导出/搜索筛选)

客户列表支持多条件筛选(ID、性别、合同类型、网络服务、流失状态等)与分页展示:

jinja2 复制代码
{# app/templates/customer/index.html 片段 #}
<form method="get" action="{{ url_for('customer.index') }}" class="search-form">
  <input type="text" name="customer_id" placeholder="输入客户ID">
  <select name="gender">
    <option value="">全部</option>
    <option value="Male">男</option>
    <option value="Female">女</option>
  </select>
  <select name="contract"> ... </select>
  <select name="internet_service"> ... </select>
  <select name="churn"> ... </select>
  <button type="submit" class="btn-search">搜索</button>
 </form>

新增客户表单涵盖基础信息、服务信息、合同与账单三大板块,字段与业务保持一致:

jinja2 复制代码
{# app/templates/customer/create.html 片段 #}
{{ form.customer_id(class="form-control", placeholder="请输入客户ID") }}
{{ form.gender(class="form-control") }}
{{ form.tenure(class="form-control", type="number", min="0") }}
{{ form.internet_service(class="form-control") }}
{{ form.contract(class="form-control") }}
{{ form.monthly_charges(class="form-control", type="number", step="0.01") }}

后端可使用 Pandas 进行批量导入与数据清洗,示例(可根据模型字段调整):

python 复制代码
import pandas as pd
from app.extensions import db
from app.models.customer import Customer

def import_customers(file_path: str) -> int:
    df = pd.read_excel(file_path) if file_path.endswith('.xlsx') else pd.read_csv(file_path)
    df = df.fillna({"TotalCharges": 0})

    created = 0
    for _, row in df.iterrows():
        customer = Customer(
            customer_id=row["customerID"],
            gender=row["gender"],
            tenure=int(row["tenure"]),
            internet_service=row["InternetService"],
            contract=row["Contract"],
            monthly_charges=float(row["MonthlyCharges"]),
            total_charges=float(row["TotalCharges"]),
            churn=True if str(row["Churn"]).lower() in ("yes", "true", "1") else False,
        )
        db.session.add(customer)
        created += 1
    db.session.commit()
    return created
数据分析与可视化

页面端通过 Chart.js 渲染图表,示例(仪表盘合同类型分布):

html 复制代码
<canvas id="contractChart"></canvas>
<script>
const ctx = document.getElementById('contractChart');
new Chart(ctx, {
  type: 'bar',
  data: { labels: ['月付', '一年', '两年'], datasets: [{ label: '数量', data: [120, 80, 60] }] },
});
</script>

后端也可利用 Matplotlib/Seaborn 生产静态图(用于报表导出等场景):

python 复制代码
import matplotlib.pyplot as plt
import seaborn as sns

def plot_churn_by_contract(df):
    plt.figure(figsize=(6,4))
    sns.barplot(data=df, x="Contract", y="ChurnRate", palette="Blues")
    plt.tight_layout()
    plt.savefig("data/fig_contract_churn.png")
机器学习训练与预测

基于 Scikit-learn 的典型训练流程,可结合业务字段做特征工程与持久化:

python 复制代码
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
import joblib

def train_model(dataset_path: str, model_path: str = "data/model_rf.joblib"):
    df = pd.read_csv(dataset_path)
    y = (df["Churn"].astype(str).str.lower().isin(["yes", "true", "1"]))
    X = df.drop(columns=["Churn", "customerID"])  # 依据表头实际调整

    categorical_cols = X.select_dtypes(include=["object"]).columns.tolist()
    numeric_cols = X.select_dtypes(exclude=["object"]).columns.tolist()

    preprocessor = ColumnTransformer(
        transformers=[
            ("cat", OneHotEncoder(handle_unknown="ignore"), categorical_cols),
            ("num", "passthrough", numeric_cols),
        ]
    )

    pipeline = Pipeline(steps=[
        ("prep", preprocessor),
        ("clf", RandomForestClassifier(n_estimators=300, random_state=42)),
    ])

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
    pipeline.fit(X_train, y_train)
    y_pred = pipeline.predict(X_test)
    print(classification_report(y_test, y_pred))
    joblib.dump(pipeline, model_path)

def predict_once(features: dict, model_path: str = "data/model_rf.joblib") -> float:
    model = joblib.load(model_path)
    df = pd.DataFrame([features])
    proba = model.predict_proba(df)[0][1]
    return float(proba)

接口对接示例(curl):

bash 复制代码
# 1) 登录获取 JWT
curl -s -X POST http://localhost:5000/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"123456"}'

# 假设返回 token 写入变量
TOKEN=...  # 请替换为上一步返回的 data.token

# 2) 分页获取客户(支持筛选)
curl -s 'http://localhost:5000/api/v1/customers?page=1&per_page=10&gender=Male' \
  -H "Authorization: Bearer $TOKEN"

# 3) 新增客户
curl -s -X POST http://localhost:5000/api/v1/customers \
  -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \
  -d '{"customer_id":"CUST-10001","gender":"Male","tenure":12,"contract":"Month-to-month","internet_service":"DSL","monthly_charges":56.5,"total_charges":560.0}'

# 4) 更新客户
curl -s -X PUT http://localhost:5000/api/v1/customers/1 \
  -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \
  -d '{"monthly_charges":66.0}'

# 5) 删除客户
curl -s -X DELETE http://localhost:5000/api/v1/customers/1 \
  -H "Authorization: Bearer $TOKEN"

前端 prediction/index.htmlprediction/train.htmlprediction/batch_predict.html 等页面已提供交互与占位,可与以上接口对接。

仪表盘与业务指标

首页仪表盘汇总关键指标,并展示近期流失客户与活动日志。模板片段:

jinja2 复制代码
{# app/templates/main/dashboard.html 片段 #}
<h2 class="metric-value">{{ stats.total_customers }}</h2>
<h2 class="metric-value">{{ stats.churn_customers }}</h2>
<h2 class="metric-value">{{ stats.churn_rate }}%</h2>
<h2 class="metric-value">¥{{ stats.avg_monthly }}</h2>

后端可将近 30 天内的新增/流失趋势与热力信息注入模板,以支持运营日常观察。


安装部署与初始化

  1. 克隆与进入目录
bash 复制代码
git clone <your-repo-url>
cd code
  1. 创建虚拟环境并安装依赖
bash 复制代码
python -m venv venv
venv/Scripts/activate  # Windows
# source venv/bin/activate  # macOS/Linux
pip install -r requirements.txt
  1. 初始化数据库与角色
bash 复制代码
python create_tables.py
python update_roles.py

# 可选:初始化角色(如果在自定义脚本中)
# from app.models.role import Role; Role.insert_roles()
  1. 启动服务
bash 复制代码
python app.py
# or production
gunicorn -w 4 -b 0.0.0.0:5000 wsgi:app

访问 http://localhost:5000


可视化展示占位(请在替换为实际截图后保留说明)

以下为示意占位,请将运行后的页面截图替换进来:

  • 仪表盘(Dashboard)KPI 总览与图表
  • 客户列表页面(筛选与分页)
  • 可视化大屏(流失概览/服务影响/趋势分析)
  • 预测中心(单客户预测、批量预测、模型训练与历史)
  • 系统管理(用户、角色与日志)

建议统一将图片放置于 docs/images/ 目录,并在本文档中使用相对路径引用:

markdown 复制代码
![仪表盘总览](images/dashboard-overview.png)
![流失概览](images/churn-overview.png)
![预测中心](images/prediction-center.png)

常见问题与优化建议

  • 数据集字段不一致

    • 解决:在导入前统一字段名映射;或在导入脚本中做 rename 与缺失值填充。
  • 训练效果不稳定

    • 解决:做训练/验证/测试分层抽样;网格搜索/随机搜索超参;引入更强模型(XGBoost/LightGBM)。
  • 前端加载较慢

    • 解决:开启 gzip、CDN 静态资源;分页与懒加载;按需引入图表组件。
  • 权限粒度需要更细

    • 解决:基于位掩码扩充位段;在视图层与模板层同时加校验;为敏感操作引入二次确认与审计。
  • 多环境配置

    • 解决:使用 .env 与多配置文件,区分 dev/staging/prod;敏感信息走环境变量。

附:应用工厂与扩展初始化(关键代码)

python 复制代码
# app/__init__.py
from flask import Flask
from app.extensions import db, migrate, login_manager, mail, jwt, bcrypt, cors

def create_app(config_name='default'):
    app = Flask(__name__)
    from app.config import config
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)
    mail.init_app(app)
    jwt.init_app(app)
    bcrypt.init_app(app)
    cors.init_app(app)

    from app.views.main import main_bp
    app.register_blueprint(main_bp)
    # ... 省略其它蓝图注册(auth/customer/analysis/prediction/admin)
    from app.api.v1 import api_v1
    app.register_blueprint(api_v1, url_prefix='/api/v1')
    return app
python 复制代码
# app/config.py 关键配置
class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'hard-to-guess-string'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    POSTS_PER_PAGE = 5
    UPLOAD_PATH = os.path.join(basedir, '..', 'data', 'raw')
python 复制代码
# app/forms/customer.py 片段
class CustomerForm(FlaskForm):
    customer_id = StringField('客户ID', validators=[DataRequired(), Length(1, 64)])
    gender = SelectField('性别', choices=[('Male','男'),('Female','女')])
    tenure = IntegerField('在网时长(月)', validators=[DataRequired(), NumberRange(min=0)])
    contract = SelectField('合同类型', choices=[('Month-to-month','月付'),('One year','一年'),('Two year','两年')])
    monthly_charges = FloatField('月费用', validators=[DataRequired(), NumberRange(min=0)])

附:单元测试示例占位

python 复制代码
# tests/test_customers_api.py
import json

def test_get_customers_requires_auth(client):
    resp = client.get('/api/v1/customers')
    assert resp.status_code in (401, 422)  # 缺少JWT

def test_create_customer_flow(auth_client):
    payload = {"customer_id":"UT-0001","gender":"Male","tenure":3,
               "contract":"Month-to-month","internet_service":"DSL",
               "monthly_charges":30.0,"total_charges":90.0}
    resp = auth_client.post('/api/v1/customers', data=json.dumps(payload),
                            headers={'Content-Type':'application/json'})
    assert resp.status_code == 201

结语与联系

本文分享了一个面向业务的"电信用户流失信息分析系统",涵盖从数据到模型再到可视化与权限的完整闭环。你可以在此基础上快速定制面向自身场景的留存与增长方案。

如需交流与合作,请联系:码界筑梦坊各大平台同名。


毕业设计必备章节

需求分析
  • 角色与权限
    • 管理员:用户与角色管理、权限配置、查看日志、系统设置
    • 数据分析师:数据分析、模型训练与评估、预测历史
    • 数据编辑:客户数据增删改、导入导出
    • 普通用户:查看与导出
  • 功能性需求
    • 客户数据管理(CRUD、批量导入/导出、条件检索、模板下载)
    • 可视化与分析(指标卡、趋势图、多维对比)
    • 机器学习(训练、预测、历史记录、模板下载与结果导出)
    • 系统管理(用户/角色、操作日志、基础设置)
  • 非功能性需求
    • 易用性:清晰导航与筛选;表单校验;错误提示
    • 可维护性:模块化蓝图、ORM、迁移、表单/模型/视图分层
    • 安全性:登录/权限、CSRF 防护、密码哈希
系统设计(架构/模块/流程)
  • 架构分层
    • 表现层:Jinja2 模板渲染,Chart.js 可视化
    • 业务层:Blueprint 划分(main/auth/customer/analysis/prediction/admin/visualization
    • 数据层:SQLAlchemy 模型与迁移
    • 算法层:Sklearn Pipeline 训练与预测
  • 核心流程(以"批量预测"为例)
    1. 前端上传 CSV/XLSX → 2) 校验字段/清洗 → 3) 加载/检查模型 → 4) 逐行推理 → 5) 记录日志 → 6) 结果渲染与导出
  • 权限控制流程
    • 模板显示控制 + 视图 @permission_required 双重校验(位掩码)
数据库设计(表结构)
  • 用户(users
    • 关键字段:id, email, username, password_hash, role_id, member_since, last_seen, avatar_type
  • 角色(roles
    • 关键字段:id, name, default, permissions
    • 权限常量:VIEW, EDIT, ANALYZE, PREDICT, IMPORT, EXPORT, MANAGE, ADMIN
  • 客户(customers
    • 关键字段:id, customer_id, gender, senior_citizen, partner, dependents, tenure, internet_service, contract, paperless_billing, payment_method, monthly_charges, total_charges, churn, created_at, updated_at
  • 日志(logs
    • 关键字段:id, user_id, operation, target, details, ip_address, user_agent, timestamp

以上字段来自实际模型定义文件:app/models/user.pyrole.pycustomer.pylog.py

API 设计与说明(视图路由)
  • 客户模块(app/views/customer.py

    • GET /customer/:客户列表(分页、条件筛选)
    • GET|POST /customer/create:创建客户
    • GET /customer/view/<id>:查看客户详情
    • GET|POST /customer/edit/<id>:编辑客户
    • GET /customer/delete/<id>:删除客户
    • GET|POST /customer/import:导入客户数据(CSV/XLSX)
    • GET /customer/export:导出当前筛选结果(CSV)
    • GET /customer/download-import-template:下载导入模板
  • 预测模块(app/views/prediction.py

    • GET /prediction/:预测首页(模型状态/统计)
    • GET /prediction/api/stats:预测统计(准确率、今日预测量、流失率等)
    • GET|POST /prediction/train:训练模型并持久化 static/models/churn_model.pkl
    • GET /prediction/train-history:训练历史
    • GET /prediction/history:预测/批量预测历史
    • GET|POST /prediction/predict/<id>:单客户预测
    • GET|POST /prediction/batch-predict:批量预测(上传 CSV/XLSX)
    • GET /prediction/download-template:下载批量预测模板
    • GET /prediction/export-batch-results:导出批量预测结果
  • 分析模块(app/views/analysis.py

    • GET /analysis/overview:分析概览(KPI、维度统计、指标进度)
    • GET|POST /analysis/churn-analysis:流失分析(多模型对比与指标输出)
    • GET /analysis/api/churn-by-contract|tenure|monthly-charges|internet-service|payment-method:各维度流失率 API
  • 管理模块(app/views/admin.py

    • GET /admin/users|roles|logs|system:用户/角色/日志/系统页面
    • GET|POST /admin/user/add:新增用户
    • GET|POST /admin/user/<id>/edit:编辑用户
    • POST /admin/user/<id>/delete:删除用户

实际部署时可在 app/api/v1 暴露 REST API(当前仓库已有雏形:auth.pycustomers.py)。

实验与评估(指标与结果)
  • 离线评估指标
    • 准确率 Accuracy、精确率 Precision、召回率 Recall、F1、AUC-ROC
  • 实验流程
    • 数据清洗 → 划分训练/测试 → 预处理(数值标准化、类别独热)→ 训练(RF/GBDT/LogReg/SVM)→ 评估 → 记录 Log
  • 示例代码(来源于 prediction.train_modelanalysis.churn_analysis 简化整理)
python 复制代码
# 见上文训练管道与评估示例;可将报告写入 Log 便于前端读取展示
  • 结果呈现
    • 训练历史页展示训练时间与指标;预测历史页展示近期待测分布
    • 分析页展示混淆矩阵、ROC/PR 曲线与特征重要性(按需)
创新点与难点攻关
  • 权限体系位掩码 + 视图/模板双重校验,保证"可见即有权"
  • 预测闭环:模板下载 → 批量上传 → 预测 → 结果导出(含风险等级与建议)
  • 训练与预测口径一致:以 Pipeline 固化处理环节,减少线上/离线偏差
  • 可视化驱动洞察:前端 Chart.js + 后端统计接口,支持多维对比
  • 可扩展性:Blueprint 模块化、forms/models/views 分层、migrations 可演进
答辩要点与演示脚本
  • 要点
    • 业务痛点:月付客户/高月费/短在网时长为典型高风险群体
    • 技术闭环:数据 → 分析 → 模型 → 预测 → 导出 → 策略
    • 安全合规:权限、日志、CSRF、密码哈希
  • 演示脚本
    1. 登录管理员 → 创建一个分析师账号并分配权限
    2. 切换分析师 → 导入样例数据 → 查看仪表盘与分析页
    3. 训练模型 → 在客户列表中对单个客户发起预测
    4. 批量预测 → 导出预测结果 CSV(含风险等级/建议)
    5. 查看管理员日志页面,展示全链路审计