当前位置: 首页 > news >正文

Python电商数据分析平台:Django+爬虫+机器学习完整实战

这次我们来看一个典型的 Python 综合性项目:电商数据分析平台。它不是一个单独的算法脚本,而是把爬虫采集、数据清洗、销量预测、可视化大屏、词云图展示和 Django Web 框架串成一条完整链路的工程。如果你正在做毕业设计、竞赛项目,或者想在公司内部搭一套轻量级数据分析后台,这个方向覆盖的技术点非常全,值得完整跑一遍。

先看核心结论:项目基于 Django 框架搭建 Web 服务,用爬虫获取电商公开数据,用 pandas 做清洗和统计,用 scikit-learn 训练销量预测模型,用 ECharts 做可视化,用 wordcloud 生成词云图。整个系统可以通过浏览器访问,也能把预测能力封装成 API 接口,供其他系统调用。本文不绑定某个具体仓库,而是给出一套可直接落地的工程实现思路,并给出关键代码示例和验证方法。

1. 核心能力速览

能力项说明
项目类型Python Web 数据分析平台
核心框架Django + Django REST Framework
数据采集requests + BeautifulSoup4 / Scrapy
数据处理pandas + numpy
机器学习scikit-learn(线性回归、随机森林等)
可视化ECharts 前端图表 + Django JSON 接口
词云图wordcloud + jieba 中文分词
数据库SQLite 或 MySQL,按项目需要切换
启动方式命令行启动 Django 开发服务器
接口能力REST API 返回 JSON,可支持销量预测、统计数据查询
批量任务Celery + Redis 可实现定时采集和批量预测
适合场景电商数据分析、销量预测、毕业设计、内部数据看板

需要说明的是,这个项目的硬件门槛很低,普通电脑就能跑。预测模型用的不是大模型,而是传统机器学习算法,训练数据量在几千到几万条时,CPU 即可完成训练。主要内存开销集中在 pandas 读取 DataFrame 和词云图生成阶段。

2. 适用场景与使用边界

这类项目适合以下几类读者:

  • Python 学习者:想在一个项目里同时接触爬虫、Web 开发、数据处理和机器学习。
  • 数据分析岗位候选人:需要一个能展示完整数据流水线的作品,而不是只做 Kaggle 练习赛。
  • 毕设选题者:电商销量预测是经典选题,功能边界清晰,容易出成果。
  • 中小团队开发者:需要快速搭建一个内部数据看板,把运营数据变成可查询的 Web 页面。

项目能解决的问题包括:

  • 商品销量数据的自动采集与入库。
  • 销量趋势的统计和可视化。
  • 基于历史数据训练销量预测模型。
  • 评论关键词的提取与词云展示。
  • 通过 Web 页面和 API 对外输出分析结果。

但要明确使用边界。电商数据爬虫涉及版权、隐私和平台规则,只允许采集公开数据,并且要遵守目标网站的 robots.txt 协议。不要爬取用户个人信息、订单隐私数据,也不要对目标站点造成压力。采集频率要合理控制。个人学习和内部研究场景下,建议优先使用公开数据集或自己模拟生成数据,避开法律风险。涉及商业数据时,必须先确认数据来源的授权情况。

3. 技术架构与模块设计

整套系统的模块职责如下:

爬虫采集模块 -> 数据清洗模块 -> 数据库存储 -> Django Web 模块 -> 前端可视化 |-> 机器学习预测模块 -> 输出预测结果 |-> 词云图生成模块 -> 输出图片和词频

Django 在这里的角色是 Web 框架和业务调度中心。爬虫采集的数据通过 ORM 写入数据库,Django 的 View 对前端提供 JSON 接口,机器学习模型在训练完成后被加载到内存中,通过独立接口对外提供预测服务。

在 Django 项目中,建议划分以下 App:

App 名称职责
crawler爬虫采集逻辑、数据清洗、入库
analysis数据统计、销量预测、词云生成
dashboard页面渲染和图表接口
apiREST API 接口,对外输出数据

需要注意的是,Django 的 MTV 模式中,View 负责业务逻辑,Template 负责页面展示。在数据分析和预测场景下,建议把耗时操作放到异步任务中执行,避免请求阻塞。下一节先解决环境问题。

4. 环境准备与前置条件

建议使用 Python 3.9 到 3.11 之间的版本。Python 3.12 部分依赖包可能还没有完全适配,遇到问题会更麻烦。使用虚拟环境隔离依赖。

# 创建虚拟环境 python -m venv venv # 激活虚拟环境 # Windows venv\Scripts\activate # Linux / macOS source venv/bin/activate

安装核心依赖:

pip install django djangorestframework requests beautifulsoup4 pandas numpy scikit-learn wordcloud jieba celery redis

如果使用 MySQL 作为数据库,还需要安装连接驱动:

pip install pymysql

然后创建 Django 项目和应用:

django-admin startproject ecommerce_analysis cd ecommerce_analysis python manage.py startapp crawler python manage.py startapp analysis python manage.py startapp dashboard python manage.py startapp api

创建完成后,在settings.py中注册 App:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'crawler', 'analysis', 'dashboard', 'api', ]

数据库默认使用 SQLite,适合本地开发和测试。如果要切换到 MySQL,修改DATABASES配置:

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'ecommerce_db', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', } }

5. 数据模型设计

数据模型是整个项目的地基。设计不好,后面的分析和预测都会很别扭。核心模型包括商品、销量记录、评论和预测结果。

crawler/models.py中定义商品和销量记录:

from django.db import models class Product(models.Model): product_id = models.CharField(max_length=64, unique=True, verbose_name='商品ID') title = models.CharField(max_length=255, verbose_name='商品标题') category = models.CharField(max_length=64, verbose_name='类目') price = models.FloatField(verbose_name='价格') shop_name = models.CharField(max_length=128, verbose_name='店铺名称') created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'product' verbose_name = '商品' class SalesRecord(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='商品') date = models.DateField(verbose_name='日期') sales_volume = models.IntegerField(verbose_name='销量') sales_amount = models.FloatField(verbose_name='销售额') updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = 'sales_record' verbose_name = '销量记录' unique_together = ('product', 'date')

评论表用于词云分析:

class Comment(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='商品') content = models.TextField(verbose_name='评论内容') rating = models.IntegerField(verbose_name='评分') created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'comment' verbose_name = '商品评论'

生成迁移并建表:

python manage.py makemigrations python manage.py migrate

需要注意,如果使用 SQLite,整型字段的自动增长不是问题,但并发写入能力较弱。如果爬虫采集频率高,建议使用 MySQL。数据量不大时 SQLite 也够用,关键在于字段设计是否满足后续分析需求。

6. 爬虫数据采集模块

爬虫模块负责把电商数据变成结构化数据。这里只讨论“公开商品列表和公开评价”这一类数据,并且要控制采集频率。

最简单的方式是 requests 加 BeautifulSoup。以下是请求公开商品列表页的示例:

import requests from bs4 import BeautifulSoup def fetch_product_list(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } response = requests.get(url, headers=headers, timeout=10) response.encoding = 'utf-8' soup = BeautifulSoup(response.text, 'html.parser') product_nodes = soup.select('.product-item') # 选择器需要按实际页面调整 products = [] for node in product_nodes: title = node.select_one('.title').text.strip() price = node.select_one('.price').text.strip().replace('¥', '') products.append({'title': title, 'price': float(price)}) return products

注意,不同的电商页面 DOM 结构完全不同,选择器必须根据实际页面调整。更稳妥的做法是优先使用平台开放的官方 API,如果没有,再考虑爬虫。爬虫采集必须遵守robots.txt,并且请求间隔要合理,不要让目标服务器压力过大。

采集完成后需要清洗。清洗步骤包括:

  • 去除空值和重复记录。
  • 统一日期格式。
  • 将价格、销量等字符串转为数值类型。
  • 删除明显异常的数据,例如价格小于 0 的记录。
import pandas as pd def clean_sales_data(raw_data): df = pd.DataFrame(raw_data) df.dropna(inplace=True) df.drop_duplicates(inplace=True) df['date'] = pd.to_datetime(df['date']) df['sales_volume'] = pd.to_numeric(df['sales_volume'], errors='coerce') df['sales_amount'] = pd.to_numeric(df['sales_amount'], errors='coerce') df = df[df['sales_volume'] >= 0] return df

数据清洗的结果保存到数据库:

def save_products(products): for item in products: Product.objects.update_or_create( product_id=item['product_id'], defaults={ 'title': item['title'], 'category': item['category'], 'price': item['price'], 'shop_name': item['shop_name'], } )

使用update_or_create可以避免重复数据,同时保留更新能力。

7. 数据分析与销量预测模块

数据进入数据库后,先做统计分析,再做销量预测。

7.1 销量趋势统计

通过 Django ORM 聚合查询,可以快速统计每日销量:

from django.db.models import Sum from crawler.models import SalesRecord def get_daily_sales(product_id): records = ( SalesRecord.objects .filter(product_id=product_id) .values('date') .annotate(total_volume=Sum('sales_volume')) .order_by('date') ) return list(records)

这一步返回的数据可以直接用于前端 ECharts 折线图。统计结果转成 JSON:

import json from django.http import JsonResponse def daily_sales_api(request, product_id): records = get_daily_sales(product_id) dates = [str(item['date']) for item in records] volumes = [item['total_volume'] for item in records] return JsonResponse({'dates': dates, 'volumes': volumes})

7.2 特征工程

做销量预测前,要先构造特征。常用特征包括:

  • 历史销量序列的滞后值(lag-1, lag-7, lag-30)。
  • 星期几、是否周末、是否节假日。
  • 商品价格。
  • 类目。
  • 滚动平均和滚动标准差。
def build_features(df): df_feature = df.copy() df_feature.sort_values('date', inplace=True) df_feature['lag_1'] = df_feature['sales_volume'].shift(1) df_feature['lag_7'] = df_feature['sales_volume'].shift(7) df_feature['rolling_mean_7'] = df_feature['sales_volume'].rolling(window=7).mean() df_feature['day_of_week'] = df_feature['date'].dt.dayofweek df_feature['is_weekend'] = df_feature['day_of_week'].apply(lambda x: 1 if x >= 5 else 0) df_feature.dropna(inplace=True) return df_feature

特征是机器学习模型的上限,模型只是逼近这个上限。数据量小的时候,滞后特征和星期特征是效果最明显的两个因素。

7.3 训练销量预测模型

这里用随机森林回归作为示例,因为它在小数据集上不容易过拟合,且能输出特征重要性,方便后面解释。

from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_absolute_error, r2_score def train_sales_model(df): feature_cols = ['lag_1', 'lag_7', 'rolling_mean_7', 'day_of_week', 'is_weekend'] X = df[feature_cols] y = df['sales_volume'] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, shuffle=False ) model = RandomForestRegressor( n_estimators=200, max_depth=8, random_state=42 ) model.fit(X_train, y_train) y_pred = model.predict(X_test) print("MAE:", mean_absolute_error(y_test, y_pred)) print("R2:", r2_score(y_test, y_pred)) return model

训练完成后,模型需要保存到磁盘,避免每次请求都重新训练。

import joblib joblib.dump(model, 'sales_model.pkl')

加载模型:

model = joblib.load('sales_model.pkl')

预测下一天销量:

import numpy as np def predict_next_day(model, last_record): features = np.array([[ last_record['lag_1'], last_record['lag_7'], last_record['rolling_mean_7'], last_record['day_of_week'], last_record['is_weekend'], ]]) return model.predict(features)[0]

需要特别强调:模型预测结果只能作为参考,不能作为经营决策的唯一依据。销量受促销、天气、平台流量波动、突发事件等多重因素影响,传统机器学习模型只能学习历史规律,无法感知未来变化。

8. 可视化与词云图展示

8.1 Django 集成 ECharts

ECharts 是一个纯前端图表库,通过 CDN 引入即可,不需要额外安装 Python 包。

dashboard/templates/dashboard/index.html中引入 ECharts 并请求 Django 接口:

<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>电商数据分析平台</title> <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script> </head> <body> <div id="chart" style="width: 100%; height: 400px;"></div> <script> fetch('/api/daily_sales/1/') .then(response => response.json()) .then(data => { const chart = echarts.init(document.getElementById('chart')); chart.setOption({ tooltip: {}, xAxis: {data: data.dates}, yAxis: {}, series: [{ type: 'line', data: data.volumes, smooth: true }] }); }); </script> </body> </html>

这种前后端分离方式的好处是,接口可以做复用。页面只是消费者之一,移动端或者其他系统也可以调用同一套 API。

8.2 词云图生成

词云图用于展示商品评论中的高频关键词。需要先对评论文本进行中文分词,再生成词云图片。

import jieba import wordcloud def generate_wordcloud(product_id): comments = Comment.objects.filter(product_id=product_id).values_list('content', flat=True) text = ' '.join(list(comments)) words = ' '.join(jieba.cut(text)) wc = wordcloud.WordCloud( font_path='msyh.ttc', # Windows 建议指定中文字体路径 width=800, height=600, background_color='white' ) wc.generate(words) wc.to_file('wordcloud.png') return 'wordcloud.png'

中文词云最容易踩的坑是字体问题。默认字体不支持中文,会显示成方框。Windows 下可以指定C:\Windows\Fonts\msyh.ttc,Linux 下需要安装中文字体,比如wqy-microhei

生成词云图后,接口可以直接把图片路径返回给前端:

from django.http import JsonResponse def wordcloud_api(request, product_id): image_path = generate_wordcloud(product_id) return JsonResponse({'image_url': '/static/' + image_path})

更好的方式是把图片保存到媒体目录,然后通过 Django 静态文件服务对外提供。

9. 接口 API 与批量任务

9.1 REST API 设计

使用 Django REST Framework 可以快速把分析结果封装成标准接口。

安装并注册后,在api/views.py中定义接口:

from rest_framework.decorators import api_view from rest_framework.response import Response @api_view(['GET']) def sales_summary(request, product_id): records = SalesRecord.objects.filter(product_id=product_id) total_volume = records.aggregate(total=Sum('sales_volume'))['total'] total_amount = records.aggregate(total=Sum('sales_amount'))['total'] return Response({ 'product_id': product_id, 'total_volume': total_volume, 'total_amount': total_amount, })

api/urls.py中注册路由:

from django.urls import path from . import views urlpatterns = [ path('summary/<str:product_id>/', views.sales_summary), ]

启动服务后,可以直接用浏览器访问:

http://127.0.0.1:8000/api/summary/1001/

返回结果:

{ "product_id": "1001", "total_volume": 12345, "total_amount": 456789.0 }

9.2 批量任务设计

如果采集数据量大,或者需要定时训练模型,建议引入 Celery。Celery 是一个分布式任务队列,配合 Redis 作为消息代理,可以把爬虫采集、模型训练这类耗时任务放到后台执行。

settings.py中配置 Celery:

CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0' CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379/1'

定义异步任务:

from celery import shared_task @shared_task def run_crawler_task(keyword): # 在这里调用爬虫逻辑 products = fetch_product_list(keyword) save_products(products) return len(products)

调用任务:

run_crawler_task.delay('手机')

Celery Worker 启动命令:

celery -A ecommerce_analysis worker -l info

批量预测的场景同样可以做成任务队列:输入商品 ID 列表,后台逐个加载模型并预测,最后把结果写入预测结果表,前端接口直接读取最终结果。

10. 资源占用与性能观察

整个项目的资源消耗主要集中在三块:

  • 爬虫采集阶段:内存占用取决于同时请求的并发数,同步 requests 方式下占用不高。
  • pandas 数据清洗阶段:DataFrame 会一次性把数据加载到内存,几万条记录大概占用几十到几百 MB,数据量超过百万条时建议改用分块读取。
  • 模型训练阶段:随机森林训练速度较快,几万条训练数据在普通 CPU 上几十秒内完成。如果使用 XGBoost,训练速度会更快,但需要单独安装。

观察项目运行状态的方法:

# 查看 Django 进程内存占用 ps aux | grep python # 查看系统资源占用 top -p <pid>

如果发现接口响应慢,优先检查数据库查询次数。Django ORM 最常出现的问题是 N+1 查询,比如循环里查数据库。使用select_relatedprefetch_related可以大幅减少查询次数。

# 错误示例:循环中查询数据库 for record in sales_records: print(record.product.title) # 正确示例:提前关联查询 from django.db.models import Prefetch sales_records = SalesRecord.objects.select_related('product').all()

词云生成是 CPU 密集操作,jieba 分词在文本量大时可能耗时较长。如果部署在服务器上,建议把词云生成放到 Celery 异步任务中,前端先显示“生成中”,任务完成后刷新图片。

11. 常见问题与排查方法

问题现象可能原因排查方式解决方案
启动 Django 报 ModuleNotFoundError依赖包未安装或虚拟环境未激活检查是否有 venv,查看 pip list激活虚拟环境后重新安装依赖
爬虫获取不到数据页面结构变化、请求头被识别打印响应文本,检查 HTTP 状态码更新页面选择器,调整 User-Agent
中文词云显示方框缺少中文字体查看字体路径是否存在指定系统可用的中文字体文件
销量预测结果偏差很大训练数据量不足、特征构造不合理查看训练集和测试集的 MAE增加历史数据,尝试滞后特征和节假日特征
数据库表锁死爬虫写入频繁且数据库为 SQLite观察错误日志切换 MySQL,或降低写入频率
接口返回 500代码异常、数据库连接失败查看 Django 日志修复异常,检查数据库连接配置
Celery 任务不执行Redis 未启动或队列名称不匹配检查 Redis 是否运行,查看 worker 日志启动 Redis,重启 worker

遇到问题时的第一原则:先看日志。Django 开发服务器的终端输出、Celery worker 日志、浏览器开发者工具的 Network 面板,这三处信息足以定位大部分问题。

12. 最佳实践与使用建议

做一个完整的电商数据分析平台,不只是把代码跑通,还要考虑工程化。以下是几个建议。

第一,目录结构要清晰。爬虫代码、数据处理代码、模型训练代码、Web 接口代码分开存放,不要全部堆在views.py里。可以按照crawler/analysis/dashboard/api/划分。

第二,配置使用独立文件。数据库连接、Redis 地址、爬虫请求头、模型路径等常量统一放到settings.py或独立的配置文件中,不要写死在业务代码里。

第三,爬虫要加间隔。每请求一次页面,至少间隔 1 到 2 秒。这既是对目标站点的保护,也是降低被封风险的有效手段。

import time import random def fetch_with_interval(url): time.sleep(random.uniform(1, 2)) response = requests.get(url, headers=headers, timeout=10) return response

第四,模型训练要可复现。固定随机种子、固定训练集和测试集划分比例、保存模型版本。这样即使数据更新后重新训练,也能知道模型的相对变化。

random_state = 42 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=random_state, shuffle=False )

第五,接口要做访问控制。如果系统部署到服务器,Django 的ALLOWED_HOSTS要配置成实际域名或 IP。API 如果只限内部使用,可以通过rest_framework.authentication加 Token 认证。

第六,数据合规是底线。采集数据前确认数据来源的公开性,不采集用户隐私数据,不抓取非公开接口,不把采集到的数据用于商业用途。对爬虫代码加适度频率限制,避免给目标服务器带来压力。

13. 总结与下一步

整套系统最值得尝试的点,是把 Django 和机器学习组合起来,让数据分析和预测结果通过 Web 页面跑成一个可交互的工具。对于学习者来说,这个项目比单独跑一个 notebook 更有工程感,也更接近实际工作场景。

第一次跑通时,建议按这个顺序验证:

  1. 启动 Django 服务,访问首页。
  2. 用公开数据集或模拟数据写入商品和销量记录表。
  3. 在页面中查看销量趋势图和词云图。
  4. 训练一个最小销量预测模型,查看评估指标。
  5. 调用 API 接口,确认 JSON 输出符合预期。

最容易踩的坑集中在三处:爬虫选择器和反爬机制、中文词云的字体问题、预测模型训练集和测试集设置不当导致的过拟合。

后续可以扩展的方向很明确:把模型换成 XGBoost 或 LightGBM,对比效果;引入时间序列模型如 Prophet 做更专业的销量预测;加入用户行为数据,做更精细的 RFM 客户分层;或者把可视化页面升级成可筛选、可下钻的交互式仪表盘。

如果只是单纯想把销量预测从“能跑”变成“实用”,建议先把功夫花在特征上:引入节假日、促销、天气等外部特征,往往比更换模型提升更明显。整个项目在普通电脑上就能开发测试,值得动手搭一遍。建议收藏备用,后续再往深做时,框架和代码不需要大的改动。

http://www.cnnetsun.cn/news/4357841.html

相关文章:

  • C# 工业级集成 YOLOv12 完整方案:从 ONNX 推理封装到 WPF 实时检测界面全流程
  • 【计算机毕业设计单片机案例】基于 STM32 或 51 单片机的阈值触发式环境报警控制系统设计 基于 STM32 或 51 单片机的光敏采集与 LED 补光控制系统设计(024405)
  • 借条再规范也难获利息:信用卡套现转贷合同无效解析
  • 4小时挣130美元的网约车司机,副业写诗背后的可复制方法
  • 入团资料员证怎么转?考前押题帮你稳过!
  • 危化安全标准化评审员真实经历:学历不够怕报不上名?这招能让你稳过
  • 入团资料员考前押题全攻略,工地太忙根本没时间复习?别慌!
  • 正版施工员证书图片值不值得考?别让钱打了水漂
  • 正版施工员证书图片工作内容与日常职责
  • 正版施工员证书图片怎么拿?官方报名入口在这儿找
  • 施工员自学保姆级教程:过期证书怎么复审?手把手教你搞定
  • 入团资料员怕考不过白交钱?全流程办理全知道,多少钱都值了
  • 八大员施工员自学需要什么材料多少钱
  • 安全员安全检查汇报在哪考,怕考不过白交钱?这篇讲透了
  • 机械员考试实务怎么考?怕考不过白交钱?官方报名入口全在这
  • 机械员考试实务值不值得考?学历不够怕报不上名怎么办
  • 机械员考试实务多久拿证?学历不够也能报上名的干货来了
  • 安全员安全检查汇报怎么写?官方报名入口在哪?证书挂靠找工作必须知道
  • 安全员安全检查汇报千万别踩坑这些雷区你得知道
  • 施工员自学怎么考 官方回应来了,别再被坑
  • UE6 vs Unity 7:2025年游戏引擎选型与迁移实战指南
  • 智曼B2 Pro洗碗机实测:从安装调试到消毒滤盒维护全指南
  • 实测对比|不懂设计做营销海报,哪个AI绘图工具最省心?
  • 从3D打印到ROS2:5自由度机械臂RIG-Arm完整搭建与开发指南
  • 驻场安全员同期声:含金量还在吗?别怕考不过白交钱
  • OpenAI 约 700 个智能体协作攻破 Hugging Face
  • 医学英语入门:神经元与神经核心词汇拆解与记忆
  • 华中师范大学838傅里叶变换备考经验:题型总结与复习方法
  • 量子计算威胁RSA:后量子密码迁移与金融系统应对指南
  • 15个硬件开关电源实战项目:从Buck到LLC,秋招简历必备