ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python+Django电商数据分析系统:从爬虫到销量预测全流程

Python+Django电商数据分析系统:从爬虫到销量预测全流程 在电商业务中数据是一切决策的基础。无论是商品定价、库存备货还是营销活动节奏都离不开对历史数据的分析和未来趋势的判断。本文将围绕“Python电商数据分析 Django框架 预测算法 销量预测 数据可视化 词云图 爬虫 机器学习”这条完整链路手把手搭建一套电商数据分析系统。从爬虫采集数据开始经过清洗、分析、可视化再到机器学习建模预测销量最后通过 Django 框架完成 Web 化展示。1. 背景与核心概念1.1 这套系统解决什么问题很多电商运营人员或数据分析师会遇到这样的场景手动从后台导出 Excel 表格再用透视表做分析流程繁琐且无法实时更新。想知道某款商品近三个月的销量趋势但数据散落在多个平台整理成本高。下个月该备多少货是参考去年同期的销量还是根据最近一周的增长趋势纯靠经验容易拍脑袋。用户评论里提到最多的词是“质量好”还是“发货慢”如果人工逐条阅读效率极低。电商数据分析系统的目标就是将这些问题串成一条自动化流水线爬虫负责采集外部数据pandas 负责清洗和统计机器学习模型负责销量预测词云图负责文本洞察Django 负责把这些能力以网页形式开放给业务人员使用。1.2 技术栈之间的关系这里涉及的几个技术栈非常经典它们各司其职Python整个系统的胶水语言负责爬虫、数据分析、建模和 Web 后端。爬虫Requests BeautifulSoup从电商平台页面或开放接口采集商品信息、评论内容和销量数据。Django高完整的 Python Web 框架把分析结果封装成网页和服务接口。数据分析pandas NumPy完成数据清洗、字段筛选、聚合统计、趋势计算。机器学习scikit-learn基于历史销量数据训练回归模型预测未来销量。可视化Matplotlib ECharts 或 Pyecharts把数据结果转成直观图表。词云图jieba WordCloud对评论/标题文本做分词和词频统计生成视觉化词云。一句话概括这套系统的价值从数据采集到业务决策形成完整闭环。1.3 为什么选择 Django很多入门者会问数据分析用 Jupyter Notebook 不就行了吗为什么还要用 Django答案是Notebook 适合单机探索但无法直接给业务人员使用。Django 提供了完整的 MTV 架构、ORM 数据库操作、模板渲染和 URL 路由。你可以把训练好的模型定期更新把分析图表嵌入管理后台让运营人员通过浏览器直接查看预测结果而不需要接触任何代码。2. 环境准备与版本说明2.1 运行环境本文示例以以下环境为基础版本需要根据你的项目实际情况调整但思路完全通用软件推荐版本说明Python3.9 或 3.10建议 64 位版本避免第三方库安装问题Django4.x安装命令pip install djangopandas2.x数据分析核心库numpy1.24 以上数值计算scikit-learn1.2 以上机器学习建模jieba0.42.1中文分词wordcloud1.9.2词云图生成matplotlib3.7 以上基础图表requests2.31 以上网络请求beautifulsoup44.12 以上HTML 解析2.2 创建虚拟环境开发 Python 项目强烈建议使用虚拟环境避免不同项目之间依赖冲突。Windows 与 Linux/macOS 的命令略有区别下面分别说明。# Windows python -m venv ecommerce_env ecommerce_env\Scripts\activate # macOS / Linux python3 -m venv ecommerce_env source ecommerce_env/bin/activate激活虚拟环境后再安装依赖pip install django pandas numpy scikit-learn jieba wordcloud matplotlib requests beautifulsoup42.3 项目结构规划整个项目不是简单的单文件脚本而是按“数据层 - 分析层 - 表现层”三层组织ecommerce_analysis/ ├── manage.py ├── analysis_app/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── views.py │ ├── urls.py │ └── migrations/ ├── core/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── data_scripts/ │ ├── crawl_data.py │ ├── clean_data.py │ ├── analysis.py │ ├── wordcloud_gen.py │ └── predict_sales.py ├── templates/ │ ├── base.html │ ├── index.html │ ├── analysis.html │ ├── wordcloud.html │ └── predict.html ├── static/ │ ├── css/ │ └── images/ └── data/ ├── raw_data.csv ├── clean_data.csv └── predict_result.csv这里我把爬虫、分析、建模脚本放在data_scripts目录下Django 只负责读取结果并展示。这样分层的好处是数据分析逻辑和 Web 逻辑解耦后续如果换成 Flask 或 FastAPI 也无需改动分析代码。3. 数据采集爬虫模块设计3.1 爬虫的边界与合法性在编写爬虫前必须先强调爬取数据要遵守目标网站的robots.txt协议控制请求频率不要对目标服务器造成压力。本文示例使用公开测试数据结构演示实际开发中应优先使用官方 API 或已授权的数据源。合法的爬虫应用包括爬取自己店铺后台允许导出的数据。爬取公开的行业报告数据。爬取已授权第三方平台的开放接口。3.2 商品基础信息爬取示例下面是一个基础的商品列表采集示例目标页面结构假设每个商品项包含classproduct-item内部有商品名、价格、评价数、销量等字段。实际页面需要根据目标网站结构调整解析规则。# 文件路径data_scripts/crawl_data.py import csv import time 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 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } response requests.get(url, headersheaders, timeout10) response.encoding utf-8 soup BeautifulSoup(response.text, html.parser) products [] items soup.select(.product-item) for item in items: name_tag item.select_one(.product-name) price_tag item.select_one(.product-price) sales_tag item.select_one(.product-sales) comment_tag item.select_one(.product-comment) products.append({ name: name_tag.text.strip() if name_tag else , price: price_tag.text.strip() if price_tag else 0, sales: sales_tag.text.strip() if sales_tag else 0, comment_count: comment_tag.text.strip() if comment_tag else 0 }) return products def save_to_csv(products, filenamedata/raw_data.csv): 保存数据到 CSV 文件 with open(filename, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[name, price, sales, comment_count]) writer.writeheader() writer.writerows(products) if __name__ __main__: # 演示页按实际项目需求替换为合法目标地址 demo_url https://example.com/items result fetch_product_list(demo_url) save_to_csv(result) print(f采集完成共 {len(result)} 条数据)这段代码有几个值得注意的点encodingutf-8-sig保存 CSV 时带上 BOMExcel 打开中文不乱码。time.sleep()在批量请求时应加入避免高频访问被限制。选择器.product-name需要根据真实页面结构调整不要照搬。4. 数据清洗与预处理4.1 为什么清洗必不可少爬虫采集的原始数据几乎一定存在脏数据价格字段带有“¥”符号、销量字段是“5000”、评论数可能缺失、商品名称包含重复空格等。直接把这些数据丢给机器学习模型会直接报错或产生严重偏差。清洗的核心工作缺失值处理删除或填充。格式统一去除货币符号、单位转成数值类型。去重同一商品重复抓取时保留一条。异常值过滤销量为负、价格极端异常等情况。4.2 清洗代码示例# 文件路径data_scripts/clean_data.py import pandas as pd def clean_sales_data(input_pathdata/raw_data.csv, output_pathdata/clean_data.csv): 清洗原始数据并输出标准化 CSV df pd.read_csv(input_path) # 1. 去除完全重复的行 df df.drop_duplicates(subset[name]) # 2. 去除价格中的货币符号和逗号 df[price] df[price].str.replace(¥, , regexFalse) df[price] df[price].str.replace(,, , regexFalse) df[price] pd.to_numeric(df[price], errorscoerce) # 3. 销量字段处理去掉 号保留数字 df[sales] df[sales].str.replace(, , regexFalse) df[sales] pd.to_numeric(df[sales], errorscoerce) # 4. 评论数字段处理 df[comment_count] pd.to_numeric(df[comment_count], errorscoerce) # 5. 删除价格或销量为空的行 df df.dropna(subset[price, sales]) # 6. 过滤异常值价格小于 0 或销量小于 0 df df[(df[price] 0) (df[sales] 0)] # 7. 重置索引 df df.reset_index(dropTrue) df.to_csv(output_path, indexFalse, encodingutf-8-sig) print(f清洗完成剩余 {len(df)} 条数据) return df if __name__ __main__: clean_sales_data()4.3 日期字段处理如果数据中包含日期还需要统一格式df[date] pd.to_datetime(df[date], errorscoerce) df df.dropna(subset[date]) df[month] df[date].dt.to_period(M)按月份聚合销量是后续预测中非常关键的一步因为模型输入的是时间序列特征而不是单日离散记录。5. 数据分析与可视化5.1 核心分析指标清洗完数据后可以先从几个维度做探索性分析EDA总销量、总销售额。价格区间分布。销量 Top10 商品。各月份销量趋势。评论数与销量之间的关系。5.2 用 pandas 做聚合统计# 文件路径data_scripts/analysis.py import pandas as pd def load_data(): df pd.read_csv(data/clean_data.csv, encodingutf-8-sig) return df def top_sales(df, n10): 销量最高的商品 return df.nlargest(n, sales)[[name, price, sales]] def price_distribution(df): 价格区间分布 bins [0, 50, 100, 200, 500, 1000, 50000] labels [0-50, 50-100, 100-200, 200-500, 500-1000, 1000] df[price_range] pd.cut(df[price], binsbins, labelslabels) return df[price_range].value_counts().sort_index() if __name__ __main__: df load_data() top top_sales(df) print(销量 Top10) print(top) print(\n价格分布) print(price_distribution(df))5.3 生成销量趋势图可视化是数据分析的“最后一公里”。Matplotlib 生成的静态图片可以直接嵌入 Django 模板也可以保存为文件后用 ECharts 在前端动态展示。# 文件路径data_scripts/chart_sales_trend.py import matplotlib.pyplot as plt import pandas as pd plt.rcParams[font.sans-serif] [SimHei] # 解决中文乱码 plt.rcParams[axes.unicode_minus] False def draw_sales_trend(): df pd.read_csv(data/clean_data.csv, encodingutf-8-sig) df[date] pd.to_datetime(df[date]) df.set_index(date, inplaceTrue) # 按月汇总销量 monthly df[sales].resample(M).sum() plt.figure(figsize(10, 5)) monthly.plot(markero) plt.title(月度销量趋势图) plt.xlabel(月份) plt.ylabel(销量) plt.grid(True, linestyle--, alpha0.5) plt.tight_layout() plt.savefig(static/images/sales_trend.png, dpi150) plt.close() if __name__ __main__: draw_sales_trend()这里有一项重要的配置plt.rcParams[font.sans-serif] [SimHei]。如果不设置中文字体生成的图表上中文会变成方框这是新手最容易踩的坑。6. 词云图评论数据洞察6.1 中文分词的必要性英文文本用空格分隔而中文没有天然分隔符所以必须先使用jieba分词。分词后过滤掉“的”“了”“是”等停用词再统计词频最后用 WordCloud 生成词云图。6.2 生成商品评论词云# 文件路径data_scripts/wordcloud_gen.py import jieba import matplotlib.pyplot as plt from wordcloud import WordCloud def generate_wordcloud(text_filedata/comments.txt, output_filestatic/images/comment_wordcloud.png): 根据评论文件生成词云图 with open(text_file, r, encodingutf-8) as f: text f.read() # 1. jieba 分词 words jieba.lcut(text) # 2. 过滤停用词和单字词 stopwords {的, 了, 是, 我, 你, 他, 这, 那, 也, 都, 就} filtered_words [w for w in words if w not in stopwords and len(w) 1] # 3. 合并为空格分隔的文本 word_text .join(filtered_words) # 4. 生成词云 wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, # Windows 中文字体路径 width800, height600, background_colorwhite, max_words200 ).generate(word_text) plt.figure(figsize(10, 7)) plt.imshow(wc, interpolationbilinear) plt.axis(off) plt.tight_layout() plt.savefig(output_file, dpi150) plt.close() if __name__ __main__: generate_wordcloud()注意font_path必须指向一个中文字体文件例如 Windows 的simhei.ttf或 macOS 的PingFang.ttc否则词云中的中文会显示为方框。6.3 词云画面的业务解读词云不仅能展示高频词还能辅助业务判断如果高频词包含“质量”“不错”“正品”说明商品口碑较好。如果高频词包含“发货”“物流”“太慢”说明物流体验是用户关注的痛点。如果高频词包含“客服”“态度”“差”需要检查售前售后服务流程。当然词云分析只是起点更严谨的做法是对评论做情感分类把正面、负面、中性评论分开统计再分别生成词云才能定位具体问题。7. 机器学习销量预测7.1 预测模型的选择销量预测是一个典型的回归问题适合的算法包括线性回归适合销量与时间近似线性关系的情况解释性强。决策树回归对非线性数据更友好但容易过拟合。随机森林回归集成多个决策树稳定性更好是工业界常用的默认选项。XGBoost / LightGBM在数据量较大时表现更强但需要额外安装。本文使用随机森林回归演示因为它在小样本数据集上表现稳定且不需要过多的特征缩放。7.2 特征工程模型不能直接吃原始日期需要把日期转换为可计算的数值特征。常用特征包括month月份。day日。weekday星期几0 表示周一。is_weekend是否周末1 / 0。lag_1前一天销量。lag_7前一周同一天销量。rolling_mean_7最近 7 天销量均值。滞后特征lag和滚动均值能够让模型捕捉到时间序列的周期性。# 文件路径data_scripts/predict_sales.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, r2_score def build_features(df): 基于日期列构造特征 df df.copy() df[date] pd.to_datetime(df[date]) df[month] df[date].dt.month df[day] df[date].dt.day df[weekday] df[date].dt.weekday df[is_weekend] df[weekday].isin([5, 6]).astype(int) # 滞后特征 df[lag_1] df[sales].shift(1) df[lag_7] df[sales].shift(7) # 7 天滚动平均 df[rolling_mean_7] df[sales].rolling(window7).mean() # 删除有缺失值的行滞后和滚动产生的 NaN df df.dropna().reset_index(dropTrue) return df def main(): # 假设 clean_data.csv 中包含 date 和 sales 两列 df pd.read_csv(data/clean_data.csv, encodingutf-8-sig) df build_features(df) feature_cols [month, day, weekday, is_weekend, lag_1, lag_7, rolling_mean_7] X df[feature_cols] y df[sales] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) 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) r2 r2_score(y_test, y_pred) print(f测试集 MAE{mae:.2f}) print(f测试集 R2{r2:.4f}) # 保存测试集预测结果 result pd.DataFrame({ 实际销量: y_test.values, 预测销量: y_pred }) result.to_csv(data/predict_result.csv, indexFalse, encodingutf-8-sig) if __name__ __main__: main()7.3 评估指标怎么解读MAE平均绝对误差实际值与预测值差距的平均值。如果销量平均是 200 件MAE 是 20说明平均误差 10%业务上可以接受。R²决定系数取值范围从负无穷到 1越接近 1 说明模型拟合越好。如果 R² 在 0.8 以上预测能力已经不错如果低于 0.3说明特征不够或数据本身随机性太强。不要盲目追求 R²1那通常意味着过拟合。在实际项目中更应该关注 MAE 是否在业务可接受范围内。7.4 防止过拟合随机森林虽然不容易过拟合但在小样本数据集上仍然可能发生。可以从以下方向调整限制max_depth比如设置为 5~15。增加min_samples_leaf让叶子节点至少包含几条样本。使用交叉验证而不是只划分一次训练/测试集。增加更多历史数据时间序列预测中数据量往往比模型复杂度更重要。8. Django 集成与可视化展示8.1 创建 Django 项目和 app前面几步完成的数据分析都是脚本形式现在把结果封装成 Web 页面。django-admin startproject core . python manage.py startapp analysis_app8.2 配置 settings.py# 文件路径core/settings.py片段 import os INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, analysis_app, ] TEMPLATES [ { BACKEND: django.template.backends.django.DjangoTemplates, DIRS: [os.path.join(BASE_DIR, templates)], APP_DIRS: True, OPTIONS: { context_processors: [ django.template.context_processors.debug, django.template.context_processors.request, django.contrib.auth.context_processors.auth, django.contrib.messages.context_processors.messages, ], }, }, ] STATICFILES_DIRS [ os.path.join(BASE_DIR, static), ]8.3 编写视图视图负责读取分析结果文件并传递给模板渲染。# 文件路径analysis_app/views.py import json import pandas as pd from django.shortcuts import render def index(request): 首页展示项目概况 return render(request, index.html) def analysis_view(request): 数据分析结果页 df pd.read_csv(data/clean_data.csv, encodingutf-8-sig) total_sales df[sales].sum() total_revenue (df[price] * df[sales]).sum() avg_price df[price].mean() top10 df.nlargest(10, sales)[[name, price, sales]].to_dict(records) context { total_sales: total_sales, total_revenue: round(total_revenue, 2), avg_price: round(avg_price, 2), top10: top10, } return render(request, analysis.html, context) def wordcloud_view(request): 词云图展示页 return render(request, wordcloud.html) def predict_view(request): 销量预测结果页 try: result pd.read_csv(data/predict_result.csv, encodingutf-8-sig) records result.head(30).to_dict(records) context {records: records} except FileNotFoundError: context {records: [], error: 预测结果文件不存在请先运行 predict_sales.py} return render(request, predict.html, context)8.4 URL 配置# 文件路径core/urls.py from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(, include(analysis_app.urls)), ]# 文件路径analysis_app/urls.py from django.urls import path from . import views urlpatterns [ path(, views.index, nameindex), path(analysis/, views.analysis_view, nameanalysis), path(wordcloud/, views.wordcloud_view, namewordcloud), path(predict/, views.predict_view, namepredict), ]8.5 模板页面以analysis.html为例!-- 文件路径templates/analysis.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title数据分析结果/title style body { font-family: Microsoft YaHei, sans-serif; margin: 40px; } .card { border: 1px solid #ddd; border-radius: 8px; padding: 20px; margin-bottom: 20px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: center; } th { background-color: #f5f5f5; } img { max-width: 100%; } /style /head body h1电商数据分析结果/h1 div classcard h2核心指标/h2 p总销量{{ total_sales }}/p p总销售额{{ total_revenue }}/p p平均价格{{ avg_price }}/p /div div classcard h2销量 Top10 商品/h2 table tr th商品名称/th th价格/th th销量/th /tr {% for item in top10 %} tr td{{ item.name }}/td td{{ item.price }}/td td{{ item.sales }}/td /tr {% endfor %} /table /div div classcard h2销量趋势图/h2 img src/static/images/sales_trend.png alt销量趋势图 /div div classcard h2评论词云图/h2 img src/static/images/comment_wordcloud.png alt评论词云图 /div /body /html8.6 启动服务验证完成以上配置后启动 Django 开发服务python manage.py migrate python manage.py runserver 0.0.0.0:8000浏览器访问http://127.0.0.1:8000导航到/analysis/、/wordcloud/、/predict/即可看到分析结果、词云图和预测对比数据。9. 常见问题与排查思路问题现象常见原因解决思路爬虫运行没有结果只显示 exit code 0选择器没匹配到内容或页面为动态渲染先用浏览器开发者工具确认元素位置动态页面改用 Selenium 或分析接口CSV 打开中文乱码文件编码不是 utf-8-sig保存时使用encodingutf-8-sig图表中文显示为方框Matplotlib 未设置中文字体设置plt.rcParams[font.sans-serif] [SimHei]词云图中中文不显示WordCloud 未指定中文字体路径设置font_path指向系统中文字体文件predict_sales.py报 NaN 错误滞后特征产生缺失值模型无法处理在建模前执行dropna()Django 页面 404URL 路由配置错误或 app 未注册检查INSTALLED_APPS和urls.py模型 R² 为负数据随机性强或特征不足增加滞后特征、滚动均值或换用更强模型样本数据量太少采集时间范围短扩大采集周期至少获取半年以上历史数据10. 最佳实践与工程建议10.1 数据采集层控制请求频率设置随机延时比如time.sleep(random.uniform(1, 3))。优先使用 API 而非 HTML 解析API 数据结构稳定维护成本低。数据落盘采用 CSV 或 Parquet每次采集增量追加不要覆盖原文件。10.2 数据分析层创建数据质量校验脚本在每次更新数据后自动检查字段类型、缺失值比例、异常值范围。每次分析结果输出一份“数据字典”记录字段含义、单位和取值说明方便团队协作。对价格、销量等数值字段统一单位后保存避免分析时反复转换。10.3 模型层训练集和测试集划分时注意时间顺序不能随机打乱否则会造成未来数据泄露。对时间序列数据更推荐使用TimeSeriesSplit交叉验证而不是普通的 K-Fold。模型上线后监控预测误差一旦误差超过阈值需要重新训练。简单模型优先线性回归能解决的问题不必上随机森林。10.4 Django 工程层生产环境不要使用 Django 自带的开发服务器应部署到 Nginx uWSGI/Gunicorn。敏感配置数据库密码、SECRET_KEY使用环境变量管理不要写死在 settings.py。分析脚本通过 cron 或 Celery 定时执行结果写入数据库Web 端只读取结果不实时跑模型。静态图片放在 CDN 或对象存储中避免 Django 服务器压力过大。11. 总结与下一步学习方向这篇文章完整走通了一条电商数据分析链路用 requests 和 BeautifulSoup 采集商品数据用 pandas 清洗和聚合用 Matplotlib 生成趋势图用 jieba 和 WordCloud 分析用户评论用随机森林模型预测销量最后用 Django 把所有能力整合成 Web 展示页面。建议动手顺序先跑通clean_data.py理解数据清洗每一步做了什么。再跑analysis.py看统计结果尝试调整聚合维度。对销量数据做预测重点观察 MAE 和 R²理解特征重要性。最后把分析结果接入 Django反复修改模板熟悉 MTV 流程。如果你希望继续深入可以从这几个方向扩展使用 Selenium 采集动态渲染的电商页面。使用 Prophet 或 LSTM 做更精细的销量预测。使用 ECharts 替换静态图片生成可交互仪表盘。使用 Celery Redis 实现定时自动更新数据和模型。核心经验是数据分析和机器学习并不是独立的技术孤岛把它们串成自动化流水线才能真正释放业务价值。每一步都亲手敲一遍代码遇到报错先查日志再搜资料你会发现自己进步得比想象中快得多。
返回列表