Python电商数据分析与销量预测:从爬虫到Django完整实战 做电商数据分析的人一定遇到过这样的场景运营每周要一份销售报表老板想提前知道下个月哪些商品能卖爆供应链想知道该备多少货。数据散落在订单表、商品表、用户评价和后台系统里每次都是导出 Excel、手工清洗、再拖几个透视表周期长不说预测基本靠经验。这个问题的本质不是“不会用 Excel”而是缺少一条从数据采集、清洗、分析、可视化到销量预测的完整自动化链路。这篇文章要做的就是用 Python 把这条链路串起来。数据采集用爬虫完成数据清洗与分析交给 Pandas可视化用 Matplotlib 和词云图展示商品结构与用户评价销量预测用机器学习算法建模最后用 Django 框架把所有能力整合成一个可访问的 Web 项目。读完你不仅能跑通一个电商数据分析与销量预测的完整项目还能理解每一层到底解决了什么问题以及在实际工程里最容易踩哪些坑。1. 这篇文章真正要解决的问题如果只看单个环节电商数据分析的技术难度都不高爬虫有 Requests 和 BeautifulSoup分析有 Pandas可视化有 Matplotlib建模有 scikit-learn。但这些工具放在一起时真正的难点并不在某个 API 怎么调用而在于数据流转的工程化设计。具体来说一个完整的电商数据分析项目会经历四个阶段数据从哪里来商品信息、销售记录、用户评论这些数据分散在多个平台和多个页面人工复制粘贴效率极低需要爬虫做定向采集。数据如何变成可用表格采集结果往往有缺失值、异常值、类型错乱、日期格式不一致等问题必须清洗后才能进入分析环节。从指标到结论运营关心的不只是“总销量多少”还包括销量趋势、价格带分布、Top 商品、用户评价焦点这些需要多维度的数据分析和可视化。从历史到未来销量预测是最有业务价值的一步。知道了趋势和规律才能提前排产、备货、制定促销策略。这篇文章的价值在于把这些步骤放进一个 Django 项目里让它们不再是孤立的 Python 脚本而是一个完整可运行的 Web 应用。适合三类读者一是刚学完 Python 基础、想做一个综合项目练手的开发者二是工作中经常处理电商数据的分析师想了解 Python 自动化分析流程三是想入门机器学习但不想只看理论、希望把算法落到业务场景中的学习者。2. 整体技术架构与核心概念2.1 五个核心模块整个项目可以拆成五个模块每个模块都对应一个明确的技术任务。模块技术选型核心任务数据采集Requests BeautifulSoup抓取商品列表、价格、销量、评论数据数据处理Pandas NumPy缺失值处理、字段类型转换、特征工程可视化Matplotlib WordCloud jieba趋势图、分布图、词云图销量预测scikit-learn 随机森林基于历史销量预测未来周期销量Web 集成Django管理数据、提供接口、渲染可视化页面2.2 为什么选 Django 做集成层很多人会问数据分析项目直接用 Jupyter Notebook 写不就行了为什么要套一个 Django关键原因有三个。第一Django 提供数据持久化能力。Jupyter 运行时数据都在内存里关掉就没了Django 配合内置 ORM 可以把采集和分析结果存入数据库形成可复用的数据资产。第二Django 让分析结果可以对外展示。无论给运营看报表还是给老板看趋势图都不能让对方装 Python 环境Django 渲染的 Web 页面是所有业务系统通用的访问方式。第三Django 自带 Admin 后台可以让非技术人员直接维护商品数据或查看分析结果这在团队协作中非常实用。2.3 技术栈选型说明整个项目主要依赖 Pandas、scikit-learn、Django 三个核心库。Pandas 负责表格化数据处理scikit-learn 提供成熟的机器学习算法Django 负责 Web 服务和数据库交互。词云图用 WordCloud 生成配合 jieba 做中文分词。Matplotlib 负责生成统计分析图生成后的图片可以直接被 Django 模板引用。3. 环境准备与项目初始化3.1 环境要求本文演示环境以 Python 3.10 和 Django 4.x 为例版本不必完全一致只要大版本兼容即可。建议使用虚拟环境隔离项目依赖避免污染系统 Python 环境。需要安装的基础依赖如下django4.0 requests2.31 beautifulsoup44.12 pandas2.0 numpy1.24 scikit-learn1.3 matplotlib3.7 wordcloud1.9 jieba0.423.2 创建虚拟环境在命令行中执行mkdir ecommerce_analysis cd ecommerce_analysis python -m venv venv source venv/bin/activateWindows 环境下虚拟环境激活命令是venv\Scripts\activate。激活后命令行前缀会出现(venv)说明已经进入虚拟环境。3.3 安装依赖将上面的依赖保存为requirements.txt然后执行pip install -r requirements.txt安装完成后可以先快速验证核心库是否可用import pandas as pd import sklearn import django print(pd.__version__) print(sklearn.__version__) print(django.get_version())3.4 创建 Django 项目和应用django-admin startproject ecommerce_project cd ecommerce_project python manage.py startapp analysis项目结构如下ecommerce_project/ manage.py ecommerce_project/ settings.py urls.py wsgi.py analysis/ models.py views.py urls.py到这一步Django 骨架已经建立。接下来需要把爬虫采集、数据分析、销量预测和可视化逻辑分别写入analysis应用的不同模块中。为了保持代码清晰建议在应用内再按职责拆分文件analysis/ crawler.py # 爬虫采集 data_process.py # 数据清洗与特征工程 visualize.py # 可视化与词云图 predictor.py # 销量预测算法4. 爬虫采集模块获取电商商品与销量数据4.1 数据采集的边界与合规提醒在写爬虫之前必须先说明一个重要问题。电商平台的数据受版权和用户协议保护采集公开数据时应当遵守目标网站的 robots 协议控制请求频率不得用于商业用途更不得绕过登录或反爬机制获取非公开数据。本文所演示的爬虫代码是一个通用框架数据源是模拟接口和公开测试数据目的是帮助你理解采集流程。实际项目中如果确需采集真实数据务必获得授权或使用官方 API。4.2 基于 Requests 的通用采集框架下面是一个最小可用的商品列表采集框架# 文件路径analysis/crawler.py import requests from bs4 import BeautifulSoup import pandas as pd from datetime import datetime HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36 } def fetch_product_list(url): 抓取商品列表页提取商品名称、价格、销量等信息。 演示代码选择器需要根据真实页面结构调整。 resp requests.get(url, headersHEADERS, timeout10) resp.raise_for_status() soup BeautifulSoup(resp.text, html.parser) records [] for node in soup.select(.product-item): title node.select_one(.title) price node.select_one(.price) sales node.select_one(.sales) if title is None: continue records.append({ title: title.get_text(stripTrue), price: float(price.get_text(stripTrue).replace(¥, )) if price else 0.0, sales: int(sales.get_text(stripTrue)) if sales else 0, crawled_at: datetime.now().strftime(%Y-%m-%d), }) return pd.DataFrame(records) def crawl_sales_history(days90): 模拟获取商品历史销量数据。 生产环境中应从平台接口或业务数据库获取。 dates pd.date_range(enddatetime.now(), periodsdays, freqD) df pd.DataFrame({date: dates}) df[sales_volume] [80 i * 2 (i % 7) * 5 for i in range(days)] return df这段代码做了三件事第一通过 Requests 发起 HTTP 请求第二用 BeautifulSoup 解析 HTML 提取字段第三把结果转换成 DataFrame方便后续处理。实际开发中页面结构调整或反爬策略变化都会导致失败所以生产级爬虫必须做好异常重试、代理切换和日志记录。4.3 数据入库采集到的数据不能只放在内存里。Django 内置了 ORM可以方便地把 DataFrame 写入数据库。先在models.py中定义商品和销售记录模型# 文件路径analysis/models.py from django.db import models class Product(models.Model): title models.CharField(max_length255, verbose_name商品标题) price models.FloatField(verbose_name价格) sales models.IntegerField(verbose_name销量) crawled_at models.DateField(auto_now_addTrue, verbose_name采集日期) class Meta: verbose_name 商品数据 verbose_name_plural verbose_name class SalesRecord(models.Model): product models.ForeignKey(Product, on_deletemodels.CASCADE, verbose_name商品) date models.DateField(verbose_name日期) sales_volume models.IntegerField(verbose_name销量) class Meta: verbose_name 销售记录 verbose_name_plural verbose_name每次执行迁移后就可以把爬虫结果写入数据库# 伪代码将 DataFrame 批量写入数据库 import pandas as pd from analysis.models import Product, SalesRecord df fetch_product_list(https://example.com/products) for _, row in df.iterrows(): product, _ Product.objects.update_or_create( titlerow[title], defaults{price: row[price], sales: row[sales]} )这里用update_or_create的好处是同一商品再次采集时会更新价格和销量而不是重复插入新记录。对于历史销售数据则按日期去重后写入。5. 数据清洗与特征工程5.1 数据加载与预处理爬虫采集的数据通常不能直接用于分析。常见问题包括价格字段混入货币符号、销量字段为空、日期格式不统一、存在重复记录。下面的代码演示完整的清洗流程# 文件路径analysis/data_process.py import pandas as pd import numpy as np def load_and_clean_data(df): 对采集到的原始数据进行清洗。 输入原始 DataFrame 输出清洗后的 DataFrame df df.copy() # 1. 去掉完全重复的记录 df df.drop_duplicates() # 2. 价格字段清洗去掉货币符号和逗号 if price in df.columns: df[price] ( df[price] .astype(str) .str.replace(¥, , regexFalse) .str.replace(,, , regexFalse) .astype(float) ) # 3. 销量字段空值用中位数填充 if sales in df.columns: median_sales df[sales].median() df[sales] df[sales].fillna(median_sales) # 4. 日期字段标准化 if date in df.columns: df[date] pd.to_datetime(df[date], errorscoerce) # 5. 剔除明显异常值价格为负数或为 0 if price in df.columns: df df[(df[price] 0)] return df清洗的核心原则是宁可用统计量填充缺失值也不要把整条记录删掉。销量为空的记录很可能是真实存在的商品删除会损失分析样本。但价格异常、日期解析失败这类数据保留反而会污染后续指标计算。5.2 特征工程销量预测的质量关键很多初学机器学习的人把精力放在调参上却忽略了一个事实销量预测真正拉开差距的地方是特征工程。所谓特征工程就是从原始数据中构造出对预测目标有解释力的新变量。对于销量预测常用的特征有两类。第一类是时间特征包括星期几、是否节假日、月份、季度。第二类是历史统计特征包括过去 7 天销量均值、过去 14 天销量均值、环比变化率。下面代码演示如何构造这些特征# 文件路径analysis/data_process.py续 def build_features(df, targetsales_volume): 为销量预测构造特征。 输入包含 date 和 sales_volume 的 DataFrame 输出带特征列和标签列的 DataFrame df df.sort_values(date).reset_index(dropTrue) # 日期时间特征 df[weekday] df[date].dt.weekday df[month] df[date].dt.month df[day_of_year] df[date].dt.dayofyear # 滚动统计特征 df[sales_lag_7] df[target].shift(7) df[sales_roll_mean_7] df[target].rolling(window7).mean() df[sales_roll_mean_14] df[target].rolling(window14).mean() df[sales_roll_std_7] df[target].rolling(window7).std() # 删除构造特征产生的空值行 df df.dropna().reset_index(dropTrue) return df这里的shift(7)是把 7 天前的销量作为当前时间的特征相当于告诉模型“上周这个时候卖了多少”。rolling(window7).mean()是过去 7 天的平均销量能反映近期的销售趋势。这些特征构造完成后模型才能看到数据背后的时间规律。6. 数据分析与可视化6.1 销量趋势分析数据清洗完成后第一件事是看整体趋势。通过 Matplotlib 绘制销量折线图可以直观判断销量是否存在周期性、是否呈上升或下降趋势。# 文件路径analysis/visualize.py import matplotlib.pyplot as plt import pandas as pd def plot_sales_trend(df, save_pathstatic/images/sales_trend.png): 绘制销量趋势图并保存到静态目录。 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False fig, ax plt.subplots(figsize(12, 6)) ax.plot(df[date], df[sales_volume], color#2E86AB, linewidth1.5) ax.set_title(商品销量趋势图) ax.set_xlabel(日期) ax.set_ylabel(销量) ax.grid(alpha0.3) plt.tight_layout() plt.savefig(save_path, dpi150) plt.close()这里有一个容易被新手忽略的点Matplotlib 默认不支持中文字体显示必须设置plt.rcParams[font.sans-serif]否则图表上的中文会变成方框。在不同操作系统上中文字体名称不同Windows 可以用SimHeiLinux 需要提前安装中文字体。6.2 商品结构与价格分布分析除了时间趋势商品结构分析也很重要。通过价格分桶可以回答一个问题“这个店铺的销量主要集中在哪个价格区间”实现方式如下def plot_price_distribution(df, bins10, save_pathstatic/images/price_dist.png): 绘制商品价格分布直方图。 fig, ax plt.subplots(figsize(10, 6)) ax.hist(df[price], binsbins, edgecolorwhite, color#F18F01) ax.set_title(商品价格分布) ax.set_xlabel(价格区间元) ax.set_ylabel(商品数量) plt.tight_layout() plt.savefig(save_path, dpi150) plt.close()6.3 用户评论词云图词云图是电商数据分析里展示效果最直观的图表之一。它能从大量评论中提取高频关键词帮助运营快速了解用户对商品的关注点。# 文件路径analysis/visualize.py续 import jieba from wordcloud import WordCloud def generate_wordcloud(comments, save_pathstatic/images/comment_wordcloud.png): 根据用户评论生成词云图。 text .join(comments) words .join(jieba.cut(text)) wc WordCloud( width800, height500, background_colorwhite, font_pathmsyh.ttc, # 中文字体路径Linux 需替换 max_words200, ).generate(words) wc.to_file(save_path)中文词云与英文词云有一个明显区别英文单词本身有空格分隔直接生成即可中文必须先用 jieba 分词把连续的中文语句切分成词语否则 WordCloud 会把整句话当作一个词处理生成结果完全不可用。另外font_path必须指定一个支持中文的字体文件否则词云中的中文会变成方块。7. 销量预测算法从线性回归到随机森林7.1 预测问题定义销量预测本质上是一个回归问题即根据历史数据预测未来某个时间点的具体销量数值。建模前需要明确三点预测粒度是按天预测还是按周、按月预测。本文以天为单位。预测目标单一商品的总销量还是所有商品的汇总销量。本文演示单商品。评估指标一般用平均绝对误差MAE或均方根误差RMSE。MAE 更直观含义是“平均每天预测偏差多少件”。7.2 数据划分与模型训练使用 scikit-learn 的RandomForestRegressor作为预测模型。随机森林是一种集成学习算法它训练多棵决策树并综合所有树的预测结果能够自动捕捉特征之间的非线性关系对缺失值和异常值有一定容忍度非常适合作为销量预测的 baseline 模型。# 文件路径analysis/predictor.py import pandas as pd from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error def train_sales_model(df, targetsales_volume): 训练销量预测模型并返回评估指标。 features [ weekday, month, day_of_year, sales_lag_7, sales_roll_mean_7, sales_roll_mean_14, sales_roll_std_7, ] X df[features] y df[target] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, shuffleFalse ) model RandomForestRegressor( n_estimators200, max_depth10, random_state42 ) model.fit(X_train, y_train) y_pred model.predict(X_test) mae mean_absolute_error(y_test, y_pred) print(f测试集 MAE{mae:.2f}) return model, mae这里有一个非常重要的细节时间序列数据划分时不能随机打乱。train_test_split默认shuffleTrue会打乱数据顺序导致模型用未来的数据预测过去的数据测试结果虚高。因此必须设置shuffleFalse保证训练集全部在测试集之前。7.3 模型评估与基线对比训练完成后模型会输出测试集 MAE。但这个数字到底好不好需要和一个简单基线对比。基线策略可以是“用过去 7 天销量均值预测明天的销量”。如果随机森林模型的误差接近基线说明复杂模型没有带来明显增益这时应优先优化特征而不是继续调参。这在实际项目中很常见模型复杂度不等于业务效果。上线时也要建立基线监控一旦模型效果不如基线就说明数据分布发生了变化需要重新训练。8. Django Web 集成与可视化展示8.1 注册应用与路由模型训练和分析图表都做好了最后一步是通过 Django 把分析结果展示给用户。首先在settings.py中注册应用# 文件路径ecommerce_project/settings.py INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, analysis, # 新增 ]然后在项目级 URL 中挂载应用路由# 文件路径ecommerce_project/urls.py from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(, include(analysis.urls)), ]8.2 视图与模板在analysis/views.py中编写视图。视图的核心任务是从数据库读取数据、生成图表、将上下文数据传给模板。# 文件路径analysis/views.py from django.shortcuts import render from django.http import JsonResponse import pandas as pd from analysis.models import Product, SalesRecord from analysis.data_process import load_and_clean_data, build_features from analysis.visualize import plot_sales_trend, generate_wordcloud def dashboard(request): 数据看板展示销量趋势和商品结构分析结果。 records SalesRecord.objects.all().values(date, sales_volume) if not records: return render(request, analysis/dashboard.html, {error: 暂无销售数据}) df pd.DataFrame.from_records(records) df load_and_clean_data(df) plot_sales_trend(df, save_pathstatic/images/sales_trend.png) context { total_sales: int(df[sales_volume].sum()), avg_daily_sales: round(df[sales_volume].mean(), 2), } return render(request, analysis/dashboard.html, context)8.3 模板页面在templates/analysis/dashboard.html中通过img标签直接引用生成的图表图片!DOCTYPE html html langzh-CN head meta charsetUTF-8 title电商数据分析看板/title style body { font-family: Microsoft YaHei, sans-serif; margin: 40px; } .card { border: 1px solid #eee; border-radius: 8px; padding: 20px; margin-bottom: 20px; } /style /head body h1电商数据分析看板/h1 {% if error %} p stylecolor: red;{{ error }}/p {% else %} div classcard h2总销量{{ total_sales }} 件/h2 p日均销量{{ avg_daily_sales }} 件/p /div div classcard h2销量趋势/h2 img src/static/images/sales_trend.png alt销量趋势图 stylemax-width: 100%; /div {% endif %} /body /html8.4 静态文件配置确保settings.py中静态文件路径已配置好。开发环境比较简单项目目录下的static文件夹就是 Django 查找静态文件的位置# 文件路径ecommerce_project/settings.py import os STATIC_URL /static/ STATICFILES_DIRS [ os.path.join(BASE_DIR, static), ]最后运行开发服务器python manage.py migrate python manage.py runserver 0.0.0.0:8000浏览器访问http://127.0.0.1:8000就能看到完整的分析看板。如果页面上图片不显示首先检查static目录是否存在、图片文件是否生成成功。9. 常见问题与排查思路问题现象可能原因排查方式解决方案爬虫运行无结果只显示 exit code 0页面结构变化导致选择器匹配不到元素输出响应文本长度和片段检查页面结构用浏览器 DevTools 确认最新 CSS 选择器Matplotlib 图表中文显示为方块未设置中文字体打印当前字体列表设置plt.rcParams[font.sans-serif]并指定系统已有字体词云图中文乱码或空白缺少中文字体文件检查 font_path 指向的文件是否存在下载msyh.ttc等中文字体并指定正确路径Django 页面找不到图片STATICFILES_DIRS 未配置或目录错误访问/static/images/xxx.png看是否 404检查 settings.py 静态文件配置预测结果全部是同一个值特征列选择错误或模型欠拟合打印 X 数据检查特征是否全为常量增加有效特征检查时间窗口构造逻辑时间序列预测误差极大train_test_split使用了随机打乱检查代码是否设置shuffleFalse改为按时间顺序划分数据集数据库写入重复数据update_or_create 未按正确字段匹配检查 ORM 查询条件和唯一约束为产品标题和日期添加唯一索引每个问题都有对应的排查路径核心排查思路可以总结为先看数据是否正常再看模型逻辑最后看页面渲染。运行日志是排错的第一入口不要跳过。10. 最佳实践与工程建议10.1 爬虫模块的工程化爬虫代码在初期可以跑通但进入持续运行时需要补充三层能力请求重试和异常处理、请求频率控制、日志记录。对目标网站的压力要克制time.sleep()是最简单也最有效的礼貌策略。10.2 数据表结构设计生产环境下商品信息、销售记录、评论数据应该拆分成独立的表通过外键关联。不要把所有字段塞进一张宽表否则后续增加评论情感分析、商品类目时又要重构表结构。10.3 模型更新策略销量预测模型不是训练一次就永久使用。商品销售受季节、促销、竞品等因素影响数据分布会不断变化。更稳妥的做法是设定一个时间周期比如每周日自动重新训练模型并监控 MAE 指标是否恶化。如果指标连续两周超过阈值触发告警并人工介入。10.4 Django 部署注意事项开发环境用runserver没问题但不能用于生产。上线时需要使用 Gunicorn 或 uWSGI 运行 Django配合 Nginx 提供静态文件服务。图片预测结果这类文件应该由 Nginx 直接响应不要经过 Django 进程否则并发稍大就会拖垮服务。10.5 从基线开始迭代任何时候都不要直接上复杂模型。先做一个“预测值等于过去 7 天均值”的基线再逐步加入时间特征、滚动特征、商品维度的交叉特征。这样能始终清楚地知道每一步优化到底带来了多少收益。本文用随机森林作为起点后续可以考虑 XGBoost、LightGBM或者带时间序列特性的 Prophet 模型但每一步都要以评估指标为准。11. 总结与后续学习方向这篇文章把 Python 电商数据分析的完整链路走了一遍爬虫采集商品和销量数据Pandas 完成清洗和特征工程Matplotlib 与 WordCloud 完成趋势图和词云图展示随机森林模型完成销量预测最后通过 Django 把图表和指标集成到一个 Web 看板中。这套流程覆盖了数据采集、数据处理、可视化、模型训练和服务化部署五个核心环节也是大多数电商数据分析项目的基本骨架。下一步的实践方向可以根据兴趣选择想深入爬虫方向可以研究 Scrapy 框架、请求代理池和增量采集机制想深入数据分析方向可以加入用户画像、商品类目维度的交叉分析或者研究 RFM 用户价值模型想深入预测算法方向可以对比 Prophet、XGBoost、LSTM 在本项目数据上的效果差异。无论选择哪个方向都建议先把本文的项目完整跑通理解数据在整个链路中如何流转——这比单独记一堆 API 用法更有价值。