Python+Django+机器学习:搭建电商数据分析与销量预测系统

📅 发布时间:2026/9/1 6:24:10
Python+Django+机器学习:搭建电商数据分析与销量预测系统 最近在和做电商运营的朋友聊天时他提到一个很具体的痛点店铺后台导出几十万行订单Excel 一打开就卡想分析一下“哪些商品最近卖得好”“未来一个月该备多少货”基本靠感觉做一次报表要花大半天。我相信这不是个例很多做电商数据分析的人每天做的不是分析而是重复地导出、清洗、制表。这篇文章要讲的就是怎么用 Python 搭建一套“采集—清洗—可视化—预测—展示”的完整电商数据分析方案。技术栈围绕 Python、Django、机器学习展开包含爬虫采集商品数据、Pandas 清洗、Matplotlib 和 WordCloud 可视化、Scikit-learn 销量预测以及最终用 Django 把分析结果做成一个可访问的 Web 页面。先说一个明确判断这类项目的核心难点根本不在 Django 或某个 Python 库怎么用而在于你能不能把“原始数据到业务决策”这条链路打通。很多人学完 Python 语法却做不出完整项目就是因为只学了零散知识点没有按业务场景把它们串起来。读完这篇你可以得到一个可运行的完整示例也知道每条链路里的坑在哪里、怎么排查。1. 这篇文章真正要解决的问题电商数据分析最常见的状态是数据有了工具不会用工具会一点链路走不通。单独看 Python、Django、机器学习网上教程很多。但把它们组合成一个能解决实际问题的项目时你就会遇到几个绕不开的问题数据从哪来手工下载 Excel 太慢接口被限制怎么处理数据怎么变成能建模的样子几十万行订单缺失值、异常值、日期格式乱七八糟怎么清洗可视化图怎么生成中文乱码、词云不出图问题出在哪里销量预测怎么做用哪个模型怎么避免“预测结果看起来很准但实际不能用”这篇文章会覆盖上述所有环节并给出代码示例和排查思路。目标读者是正在学 Python 数据分析但缺乏完整项目练手的人。已经会用 Django 做网站想扩展数据分析、机器学习能力的开发者。电商运营或产品经理想用技术手段替代手工 Excel 报表。读完你至少能获得三样东西一套可直接运行的代码框架、一整套排错方法论、以及对“数据分析项目到底怎么落地”的完整认知。2. 核心概念与系统架构在进入代码之前先把这个系统里涉及的概念讲清楚避免后续看到代码却不知道它在整个链路中的位置。2.1 核心概念速览爬虫爬虫是自动化获取网页数据的程序。它模拟浏览器向服务器发起请求拿到 HTML 或 JSON 后解析出结构化字段。电商场景里可以抓商品标题、价格、销量、评论内容。需要特别提醒的是爬虫只能用于合法授权或公开非敏感数据并且要注意目标网站的 robots.txt 和访问频率限制绝不能用于盗取隐私数据或攻击系统。数据分析数据分析是对清洗后的数据进行统计、聚合、对比找出业务规律。比如“哪类商品销量增长最快”“客单价怎么分布”“复购率是否受促销影响”。常用的 Python 库是 Pandas它提供了 DataFrame 数据结构能高效处理表格数据。数据可视化可视化是把分析结果变成图表帮助人快速理解数据。常见图表包括折线图、柱状图、饼图、词云图。文章会用到 Matplotlib 绘制统计图用 WordCloud 生成评论关键词词云。电商场景里词云可以直观展示用户评价中的高频词。机器学习与销量预测销量预测属于监督学习中的回归问题。我们用历史销量、价格、促销标记、时间特征作为输入用未来销量作为输出训练模型。常见模型有线性回归、随机森林、XGBoost。预测的意义不是得到一个精确数字而是给运营一个“大概区间”用来指导备货和活动节奏。DjangoDjango 是 Python 最流行的 Web 框架之一自带 ORM、Admin 后台、模板系统和安全机制。在这个项目里它的职责是把数据分析结果和模型预测结果包装成 Web 页面。你不必从零造轮子Django 帮你处理了 URL 路由、请求响应、数据库操作这些通用逻辑。2.2 系统整体架构整个系统可以拆成五层层级职责核心技术数据采集层抓取商品信息、销量、评论Requests、BeautifulSoup、CSV数据存储层保存原始数据和清洗后数据CSV 文件、SQLite、Django ORM数据分析层清洗、统计、特征工程Pandas、NumPy算法预测层训练销量预测模型并保存Scikit-learn、Joblib展示层渲染图表、预测结果和管理入口Django、Matplotlib、WordCloud流程图可以这样理解爬虫把外部数据抓下来存入本地文件或数据库Pandas 对数据做清洗和特征工程清洗后的数据一部分生成可视化图表一部分送入机器学习模型训练训练好的模型接收新特征输出预测销量Django 把历史统计、图表、预测结果统一渲染到页面上。这个架构的核心优点是模块清晰每一层都可以独立替换。比如你之后想换数据库只需改动存储层想使用更复杂的时序模型只需替换算法层的模型对象。对个人项目或小团队来说这种“能用、能维护、能扩展”的架构比过度设计更有价值。3. 环境准备与项目初始化下面开始实操。本文示例以 Python 3.9 为主依赖版本请以实际环境为准重点演示通用思路不锁定精确版本号。3.1 安装 Python 与虚拟环境建议使用虚拟环境隔离项目依赖避免污染系统 Python。# 创建项目目录 mkdir ecommerce_analysis cd ecommerce_analysis # 创建虚拟环境 python -m venv venv # 激活虚拟环境 # Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate虚拟环境创建后你会看到命令行前面出现(venv)字样说明已经在隔离环境内。这一步非常重要后续所有 pip 安装的包都会进入这个环境不会影响其他项目。3.2 安装依赖库pip install django pip install pandas pip install numpy pip install matplotlib pip install wordcloud pip install scikit-learn pip install joblib pip install requests pip install beautifulsoup4如果你不想一条条安装也可以将依赖写入requirements.txt文件然后执行pip install -r requirements.txt3.3 创建 Django 项目和应用# 创建项目项目名取 ecommerce_project django-admin startproject ecommerce_project # 进入项目目录 cd ecommerce_project # 创建数据分析应用 python manage.py startapp analysis创建完成后目录结构大致如下ecommerce_project/ ├── manage.py ├── ecommerce_project/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── analysis/ ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── views.py └── urls.py # 这个文件默认不存在需要手动创建在settings.py的INSTALLED_APPS中加入analysisINSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, analysis, ]到这里Django 项目骨架已经搭好。下面开始往这个骨架里填充数据分析能力。4. 数据采集层爬虫获取电商数据4.1 合法性与安全边界在写爬虫代码之前先说三条必须遵守的底线只采集公开、非敏感、合法授权的数据不碰个人隐私和交易数据。遵守目标网站的 robots.txt 协议控制请求频率不要给目标服务器造成压力。采集数据仅用于学习和技术验证不能用于商业竞争或侵犯他人权益。从工程角度爬虫也不是“跑一次就能永久用”的工具。网站页面结构会变接口参数会变因此爬虫代码必须设计成易于修改和维护的结构。更推荐的做法是优先寻找官方开放 API只有 API 无法满足需求时才考虑页面解析。4.2 使用 Requests BeautifulSoup 抓取页面下面是一个商品信息抓取示例。网站结构为假设的公开 Demo 页面字段包括商品标题、价格、销量、评价数。# 文件路径analysis/spider.py import csv import time import requests from bs4 import BeautifulSoup def fetch_product_page(page_num): 获取单页商品列表返回 HTML 文本 url fhttps://example.com/products?page{page_num} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept: text/html,application/xhtmlxml, } resp requests.get(url, headersheaders, timeout10) resp.raise_for_status() return resp.text def parse_products(html): 解析 HTML提取商品字段 soup BeautifulSoup(html, html.parser) products [] for item in soup.select(.product-item): title item.select_one(.product-title).get_text(stripTrue) price_text item.select_one(.product-price).get_text(stripTrue) sales_text item.select_one(.product-sales).get_text(stripTrue) # 假设价格形如 ¥299.00销量形如 销量 1234 price float(price_text.replace(¥, ).replace(,, )) sales int(sales_text.replace(销量, ).replace(,, )) products.append({ title: title, price: price, sales: sales, }) return products def save_to_csv(products, file_pathdata/products.csv): 追加写入 CSV 文件 import os os.makedirs(os.path.dirname(file_path), exist_okTrue) file_exists os.path.isfile(file_path) with open(file_path, a, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[title, price, sales]) if not file_exists: writer.writeheader() writer.writerows(products) if __name__ __main__: for page in range(1, 5): html fetch_product_page(page) product_list parse_products(html) save_to_csv(product_list) print(f第 {page} 页已保存 {len(product_list)} 条数据) time.sleep(2) # 延时控制请求频率核心逻辑说明使用requests.get发送请求设置User-Agent模拟浏览器降低被拒绝概率。使用 BeautifulSoup 的 CSS 选择器定位元素。实际项目中.product-item这类选择器要以真实页面结构为准。用utf-8-sig编码写入 CSV这样用 Excel 打开不会出现中文乱码。每次请求后强制time.sleep(2)这是最基本的“礼貌爬取”手段。4.3 优先考虑 JSON API 接口很多电商网站的前端数据是通过 JSON 接口返回的解析 JSON 比解析 HTML 更稳定。示例import requests import json def fetch_json_data(page_num): url https://example.com/api/products params {page: page_num, size: 50} headers {User-Agent: Mozilla/5.0} resp requests.get(url, paramsparams, headersheaders, timeout10) resp.raise_for_status() data resp.json() return data[data][list]JSON 接口通常包含结构化的字段比如id、title、price、sales、comment_count直接转成字典列表即可入库。推荐策略是优先探查开发者工具中的 Network 面板找到 XHR/Fetch 请求只有找不到接口时才退回到页面解析方式。4.4 爬虫数据的存储选择个人项目和演示场景建议先存 CSV 或 SQLite。原因有三点CSV 方便用 Pandas 直接读取调试直观。SQLite 是 Python 内置的轻量数据库无需额外安装服务。数据量小于百万级时SQLite 性能足够不需要引入 MySQL 或 PostgreSQL。当数据量增长、多人协作或需要并发读写时再迁移到 MySQL/PostgreSQL 也来得及。Django ORM 屏蔽了底层数据库差异迁移成本相对可控。5. 数据分析层数据清洗与探索性分析采集到的原始数据通常不能用必须清洗。这里以data/products.csv为例展示常见清洗操作。5.1 读取数据并查看概况# 文件路径analysis/data_clean.py import pandas as pd def load_data(file_pathdata/products.csv): df pd.read_csv(file_path) print(数据行数, len(df)) print(列名, df.columns.tolist()) print(\n缺失值统计) print(df.isnull().sum()) print(\n数据概况) print(df.describe()) return df运行后会看到行数、列名、缺失值等基本信息。描述性统计可以快速发现异常值比如价格为 0、销量为负、销量远超正常范围等。5.2 去重、缺失值处理与类型转换def clean_data(df): # 去除完全重复的行 df df.drop_duplicates() # 删除商品标题为空的行 df df.dropna(subset[title]) # 价格缺失时用中位数填充 df[price] df[price].fillna(df[price].median()) # 销量缺失时填充 0或根据业务决定 df[sales] df[sales].fillna(0) # 强制类型转换出错的行会被置为 NaN df[price] pd.to_numeric(df[price], errorscoerce) df[sales] pd.to_numeric(df[sales], errorscoerce) # 删除转换后仍为空的异常记录 df df.dropna(subset[price, sales]) # 过滤异常值价格大于 0销量大于等于 0 df df[(df[price] 0) (df[sales] 0)] return df这里真正容易踩坑的地方是类型转换。原始 CSV 里的价格可能是¥1,299、1.299,00这样的字符串直接pd.to_numeric会失败。正确做法是先做字符串清理再转换def parse_price(value): if isinstance(value, str): value value.replace(¥, ).replace(,, ).strip() return pd.to_numeric(value, errorscoerce) df[price] df[price].apply(parse_price)5.3 时间特征处理如果数据中包含订单日期建议统一转为 datetime 类型并提取年、月、日、星期等特征。def process_time(df): df[order_date] pd.to_datetime(df[order_date], errorscoerce) df df.dropna(subset[order_date]) df[year] df[order_date].dt.year df[month] df[order_date].dt.month df[day] df[order_date].dt.day df[weekday] df[order_date].dt.weekday return df时间特征的价值在后续建模中会体现出来。比如“节假日”“周末”“月底”通常对销量有显著影响如果不把日期拆成可用特征模型就很难捕捉这种周期性规律。5.4 探索性分析的常用角度清洗完成后至少做以下几个维度的探索销量 TOP10 商品是什么。价格区间分布如何哪个价格段销量最高。按月份统计销量趋势旺季和淡季是什么时候。评论数量与销量是否相关。这些分析结果会直接指导后面的可视化和特征工程。不要跳过这个阶段直接建模因为模型的质量上限取决于你对业务和数据规律的理解。6. 数据可视化与词云图生成6.1 销量趋势折线图假设你有一份按日汇总的销量表daily_sales.csv字段包括order_date和sales。# 文件路径analysis/visualize.py import matplotlib.pyplot as plt import pandas as pd # 支持中文显示 plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] False def plot_sales_trend(): df pd.read_csv(data/daily_sales.csv, parse_dates[order_date]) df df.sort_values(order_date) fig, ax plt.subplots(figsize(12, 5)) ax.plot(df[order_date], df[sales], markero, linewidth1.5) ax.set_title(每日销量趋势) ax.set_xlabel(日期) ax.set_ylabel(销量) fig.autofmt_xdate() plt.tight_layout() plt.savefig(static/images/sales_trend.png, dpi150) plt.close()几个容易踩的坑中文字体缺失会显示方框。解决办法是指定系统存在的字体Linux 服务器可能需要先安装中文字体。不调用plt.close()会导致内存持续上涨在 Django 视图中反复生成图表时尤其明显。保存图片的目录需要提前存在建议使用os.makedirs(..., exist_okTrue)创建。6.2 商品价格分布柱状图def plot_price_distribution(): df pd.read_csv(data/products.csv) fig, ax plt.subplots(figsize(10, 5)) ax.hist(df[price], bins30, edgecolorwhite) ax.set_title(商品价格分布) ax.set_xlabel(价格元) ax.set_ylabel(商品数量) plt.tight_layout() plt.savefig(static/images/price_dist.png, dpi150) plt.close()6.3 评论词云图词云图能把用户评论中的高频词可视化适合电商评论分析。# 文件路径analysis/wordcloud_gen.py import jieba from wordcloud import WordCloud import matplotlib.pyplot as plt def generate_wordcloud(text_filedata/comments.txt, image_pathstatic/images/comment_wordcloud.png): with open(text_file, r, encodingutf-8) as f: text f.read() # 中文分词 words .join(jieba.cut(text)) # 自定义停用词 stopwords {这个, 那个, 什么, 一个, 没有, 可以, 就是} wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, # 换成你系统中文字体路径 width800, height500, background_colorwhite, max_words200, stopwordsstopwords, ).generate(words) wc.to_file(image_path) print(词云图已生成, image_path)中文字体路径在不同操作系统上不一样Windows 常见路径C:/Windows/Fonts/simhei.ttf、C:/Windows/Fonts/msyh.ttc。macOS 常见路径/System/Library/Fonts/PingFang.ttc。Linux 常见路径/usr/share/fonts/...如果服务器没中文字体需要安装 fonts-wqy-zenhei 或类似包。词云生成时还需要先安装jieba分词库pip install jieba6.4 保存可视化结果的工程建议所有图片都应保存到 Django 的static目录下方便模板直接引用。目录组织建议static/ ├── images/ │ ├── sales_trend.png │ ├── price_dist.png │ └── comment_wordcloud.png如果图片是动态生成的可以在 Django 视图中按需调用可视化函数。如果数据更新不频繁也可以手动生成一次再提交到代码库减少服务器计算压力。7. 销量预测机器学习建模销量预测是这套系统里最受关注也最容易出错的部分。很多人直接拿历史销量喂给模型结果训练集 R² 很高实际场景却完全失效。核心问题通常是特征工程和验证方式不对。7.1 特征工程预测模型不能只输入“日期”要把日期扩展成模型能理解的数值特征。以下特征可以组合使用时间特征月份、星期几、是否月初/月末。业务特征前一天销量、前一周同一天销量、价格、是否促销。外部特征节假日标记、天气如有数据。滞后特征lag feature在销量预测中很常用。思路是“昨天的销量对今天的销量有影响”。def make_features(df): df df.sort_values(order_date).copy() df[month] df[order_date].dt.month df[weekday] df[order_date].dt.weekday df[is_month_end] df[order_date].dt.is_month_end.astype(int) df[lag_1] df[sales].shift(1) df[lag_7] df[sales].shift(7) df[rolling_mean_7] df[sales].rolling(7).mean().shift(1) df df.dropna() return df注意生成滞后特征后必须丢弃前几行 NaN否则模型会报错。另一个关键点是在时间序列预测中随机划分训练集和测试集是错的必须按时间顺序划分否则模型会偷看未来数据导致评估结果虚高。7.2 训练销量预测模型下面使用随机森林回归它是一个对特征缩放不敏感、能处理非线性关系的模型很适合作为基线。# 文件路径analysis/train_model.py import pandas as pd from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score from sklearn.model_selection import TimeSeriesSplit from joblib import dump def prepare_data(): df pd.read_csv(data/daily_sales.csv, parse_dates[order_date]) df make_features(df) feature_cols [month, weekday, is_month_end, lag_1, lag_7, rolling_mean_7] X df[feature_cols] y df[sales] # 按时间顺序划分 split_idx int(len(df) * 0.8) X_train, X_test X.iloc[:split_idx], X.iloc[split_idx:] y_train, y_test y.iloc[:split_idx], y.iloc[split_idx:] return X_train, X_test, y_train, y_test, feature_cols def train(): X_train, X_test, y_train, y_test, feature_cols prepare_data() model RandomForestRegressor( n_estimators200, max_depth10, random_state42, n_jobs-1, ) model.fit(X_train, y_train) # 评估 y_pred model.predict(X_test) print(MAE:, mean_absolute_error(y_test, y_pred)) print(RMSE:, mean_squared_error(y_test, y_pred, squaredFalse)) print(R2:, r2_score(y_test, y_pred)) # 保存模型和特征列 dump(model, data/sales_model.joblib) dump(feature_cols, data/feature_cols.joblib) print(模型已保存) if __name__ __main__: train()评估指标解读MAE平均绝对误差单位与销量一致比如 15 表示平均每天预测偏差 15 件。RMSE均方根误差对较大误差更敏感。R²拟合优度越接近 1 表示模型解释力越强但时序预测中 R² 不是唯一标准。实际项目中不要只看 R²要结合业务看 MAE。比如日均销量 1000MAE 20 说明误差只有 2%就很好如果 MAE 200说明模型误差太大不适合直接指导备货。7.3 模型选择建议模型优点适合场景线性回归简单、可解释性强特征与销量近似线性关系随机森林能处理非线性、对缺失值容忍度较高中等规模数据、特征维度不高XGBoost精度高、训练效率好特征较多、数据量较大的场景Prophet专为时间序列设计自动处理季节性和节假日有长期历史数据、周期明显从工程角度来看先用线性回归或随机森林作为基线确认数据链路和后处理流程没问题再去尝试更复杂的模型。如果你已经有 1 年以上的日度数据可以尝试 Prophetpip install prophet但注意 Prophet 不是万能药它对数据质量要求高如果历史数据里缺了很多天预测结果会不稳定。更稳妥的判断是先跑通 RandomForest 基线再在时间允许时对比 Prophet两者结果差异也是数据分析报告的一部分。7.4 预测结果展示模型训练完成后预测未来 7 天销量需要构造未来的特征。关键是未来日期的 lag 特征需要滚动填充这比训练复杂需要把预测值当作已知值去生成下一个滞后特征。def predict_future(model, feature_cols, last_df, days7): future_features [] current last_df.copy() for i in range(days): next_date current[order_date].iloc[-1] pd.Timedelta(days1) new_row { order_date: next_date, month: next_date.month, weekday: next_date.weekday(), is_month_end: int(next_date.is_month_end), lag_1: current[sales].iloc[-1], lag_7: current[sales].iloc[-7] if len(current) 7 else current[sales].iloc[0], rolling_mean_7: current[sales].tail(7).mean(), } # 这里先用临时 sales 值填充实际需要预测后再更新 new_row[sales] 0 current pd.concat([current, pd.DataFrame([new_row])], ignore_indexTrue) # 正式预测需要用滚动方式这里仅展示结构 return future_features这段代码展示的是构造未来特征的大致结构实际实现中需要把new_row的sales替换为模型预测值并继续滚动。建议在正式项目中单独封装一个build_future_features模块并写单元测试确保滞后特征计算正确。这也是整个项目里最容易出错的地方。8. Django Web 展示层把结果变成页面数据分析的结果如果只留在 Python 脚本里价值有限。Django 在这里的作用就是把这些统计图和预测结果统一呈现出来。8.1 配置静态文件在settings.py中加入STATIC_URL static/ STATICFILES_DIRS [ BASE_DIR / static, ]同时创建一个templates目录并在settings.py中配置TEMPLATES [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [BASE_DIR / templates], APP_DIRS: True, ... }, ]8.2 编写视图函数在analysis/views.py中写一个视图负责读取统计信息、加载模型、执行预测并渲染模板。# 文件路径analysis/views.py import pandas as pd from django.shortcuts import render from joblib import load from .spider import fetch_product_page, parse_products # 根据实际调整 from .data_clean import load_data, clean_data from .visualize import plot_sales_trend, plot_price_distribution from .wordcloud_gen import generate_wordcloud from .train_model import train, make_features def dashboard(request): # 1. 读取并清洗数据 df load_data(data/products.csv) df clean_data(df) # 2. 生成可视化图表如果文件不存在 plot_sales_trend() plot_price_distribution() generate_wordcloud() # 3. 加载训练好的模型 model load(data/sales_model.joblib) feature_cols load(data/feature_cols.joblib) # 4. 这里可以调用 predict_future 获取未来7天预测 # 为了保持示例简洁先用一个假数据表示 forecast [ {date: 2025-01-08, sales: 1260}, {date: 2025-01-09, sales: 1380}, ] # 5. 基础统计 total_products len(df) avg_price round(df[price].mean(), 2) total_sales int(df[sales].sum()) context { total_products: total_products, avg_price: avg_price, total_sales: total_sales, forecast: forecast, } return render(request, analysis/dashboard.html, context)在真实项目中forecast应该由预测函数生成示例中的假数据只是为了展示渲染方式。8.3 编写模板创建templates/analysis/dashboard.html!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title电商数据分析仪表盘/title /head body h1电商数据分析仪表盘/h1 section h2核心概览/h2 p商品总数{{ total_products }}/p p平均价格{{ avg_price }} 元/p p总销量{{ total_sales }} 件/p /section section h2销量趋势/h2 img src/static/images/sales_trend.png alt销量趋势图 stylemax-width: 100%; /section section h2价格分布/h2 img src/static/images/price_dist.png alt价格分布图 stylemax-width: 100%; /section section h2评论词云/h2 img src/static/images/comment_wordcloud.png alt评论词云图 stylemax-width: 100%; /section section h2未来销量预测/h2 table border1 cellpadding8 cellspacing0 tr th日期/th th预测销量/th /tr {% for item in forecast %} tr td{{ item.date }}/td td{{ item.sales }}/td /tr {% endfor %} /table /section /body /html8.4 配置 URL 并运行创建analysis/urls.pyfrom django.urls import path from . import views urlpatterns [ path(dashboard/, views.dashboard, namedashboard), ]在项目级ecommerce_project/urls.py中注册from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(analysis/, include(analysis.urls)), ]然后运行python manage.py runserver浏览器访问http://127.0.0.1:8000/analysis/dashboard/即可看到仪表盘页面。9. 运行验证与常见问题排查9.1 如何判断项目运行成功页面能正常打开显示商品总数、平均价格、总销量。三张图片正常显示没有裂图。预测表格有数据。Django 控制台没有 500 错误日志。如果页面 500优先看终端输出的异常堆栈。Django 开发模式会显示具体错误文件和行号这是最快的定位方式。9.2 常见问题与排查方法问题现象可能原因排查方式解决方案爬虫请求被拒绝缺少请求头、请求频率过高查看 HTTP 状态码和响应内容添加 User-Agent、设置延时、使用代理池CSV 中文乱码编码格式不正确用记事本或编辑器查看文件头写入使用utf-8-sig读取用utf-8Matplotlib 中文显示方框缺少中文字体运行plt.rcParams查看字体列表安装中文字体或指定正确字体路径WordCloud 不显示中文未指定中文字体查看生成图片是否都是方块设置font_path为中文字体模型预测 R² 很高但实战不准随机切分造成数据泄漏检查数据划分方式使用时间顺序切分使用 TimeSeriesSplitDjango 静态图片 404STATIC_URL 配置错误或目录不存在浏览器直接访问图片 URL检查STATICFILES_DIRS确认图片文件存在预测代码报 NaN滞后特征导致的空值未处理打印df.isnull().sum()清洗后dropna()内存不足爬取数据过多或图表反复生成查看任务管理器内存占用分批采集、图表生成后及时plt.close()9.3 运行失败的第一步排查顺序这里分享一个实用的排查顺序看 Django 终端日志确认是否 Python 报错还是模板渲染错误。如果是 Python 报错复制异常堆栈中第一个非 Django 框架的文件路径和行号。单独运行对应 Python 脚本比如python analysis/data_clean.py确认数据层是否正常。如果数据层正常再检查图片文件是否生成。最后检查模板语法和静态文件路径。按这个顺序走大多数问题可以在 10 分钟内定位而不是直接在浏览器里反复刷新碰运气。10. 最佳实践与工程建议10.1 项目结构规范不要把代码都堆在views.py里。Django 的 MVC 分层天然适合把数据分析逻辑拆分出去。推荐结构analysis/ ├── models.py # 数据模型 ├── views.py # Web 视图只做请求处理和模板渲染 ├── spider.py # 爬虫逻辑 ├── data_clean.py # 数据清洗 ├── visualize.py # 可视化图表 ├── wordcloud_gen.py # 词云生成 ├── train_model.py # 模型训练与评估 └── predict.py # 预测逻辑这样做的最大好处是当你需要从 CSV 切换成 MySQL 时只需要改data_clean.py和models.py不需要动视图层。10.2 使用 Django ORM 存储数据如果数据量增大建议定义模型用 ORM 替代直接读写 CSV。比如# 文件路径analysis/models.py from django.db import models class Product(models.Model): title models.CharField(max_length255) price models.DecimalField(max_digits10, decimal_places2) sales models.IntegerField(default0) created_at models.DateTimeField(auto_now_addTrue) class Meta: db_table product ordering [-sales]然后执行python manage.py makemigrations python manage.py migrate这样做的价值是数据可以复用、查询效率更高并且 Django Admin 可以直接管理数据。在爬虫写入时也尽量使用 ORM 写入而不是手动拼接 SQL避免 SQL 注入风险。10.3 模型预测的更新策略模型训练一次不代表永远有效。电商销量受季节、活动、竞争环境变化影响模型需要定期更新。建议每天增量采集数据每周或每月重新训练。训练前自动检查新数据量数据量太少时不触发训练。模型文件保存时带上时间戳方便回滚。# 保存带时间戳的模型 from datetime import datetime timestamp datetime.now().strftime(%Y%m%d_%H%M%S) dump(model, fdata/sales_model_{timestamp}.joblib)保留历史模型文件是低成本的回滚手段。新模型在验证集上的 MAE 如果比旧模型差应该继续使用旧模型。10.4 安全与合规边界这一点必须写清楚。电商数据采集和分析项目存在几个安全风险点不要采集用户的个人隐私数据比如手机号、地址、聊天记录。爬虫需要控制频率避免对目标服务器造成影响。数据库操作使用 ORM 和参数化查询避免 SQL 注入。Django 部署到生产环境前必须设置DEBUGFalse修改SECRET_KEY配置ALLOWED_HOSTS。涉及删除数据、批量更新时先备份在测试环境验证再执行生产变更。尤其是最后一点很多人在开发时习惯直接操作数据库一旦在生产环境误删数据代价会非常大。建议所有数据变更操作都封装成函数加上日志并在执行前备份相关表。10.5 日志与异常处理数据分析项目经常因为单条脏数据导致整体运行失败。建议在关键步骤添加日志import logging logger logging.getLogger(__name__) def clean_data(df): logger.info(开始清洗数据原始行数%s, len(df)) try: df df.drop_duplicates() ... except Exception as e: logger.error(数据清洗失败%s, e, exc_infoTrue) raise日志的价值在于项目跑一段时间后你不会记得每一步逻辑日志能告诉你数据在哪一步出了问题。10.6 依赖管理与可复现性把依赖写入requirements.txtpip freeze requirements.txt团队协作或换机器时使用pip install -r requirements.txt即使你只是个人项目也建议养成这个习惯。半年后重装系统你不会希望从零回忆自己装过哪些库。11. 总结与后续学习方向这篇文章从电商数据分析的实际痛点出发完整走通了一条技术链路用爬虫获取数据用 Pandas 清洗和探索数据用 Matplotlib 和 WordCloud 生成可视化图表用 Scikit-learn 训练销量预测模型最后用 Django 把所有结果变成一个可访问的 Web 仪表盘。你从中学到的不只是几个 Python 库的用法而是一种“数据项目怎么组织”的思维数据采集、数据清洗、特征工程、模型训练、结果展示每一层职责单一层与层之间通过文件、数据库或接口连接。这种分层方式比单纯套用某个框架的模板更接近真实工程。接下来的实践建议是先找一份公开的电商数据集或自己模拟生成数据把清洗和可视化部分跑通。再接入真实可合法访问的数据源体验爬虫到入库的完整过程。对预测部分优先跑通随机森林基线再尝试 XGBoost 或 Prophet并对比不同模型的误差。最后把 Django 部署到服务器做一个长期运行的仪表盘。如果你后续遇到模型效果不理想的问题不要第一时间换模型先回头检查特征工程和数据切分方式。大多数预测结果虚高根源都是数据泄漏。数据质量决定了模型上限模型只是逼近这个上限的工具。这句话几乎适用于所有数据分析项目。