资讯详情 Python商品销售数据分析可视化系统:爬虫+pandas+Pyecharts全链路实战
📅 2026/10/12 20:57:21
简介这份资源是面向高校计算机相关专业学生与Python初学者的一套商品销售数据分析可视化系统源码采用Django框架搭建并附带数据爬虫模块可作为毕业设计、课程设计或数据分析练手项目的完整参考实现。压缩包共收录1480个文件整体约17.68MB其中以691个js脚本、196个css样式、158个png与124个jpg图片资源为主另含50个less、48个scss预编译样式、13个py源码与13个pyc编译文件以及html模板、字体图标、json配置等前端界面与后端逻辑分层清晰便于按模块阅读与二次修改。资源描述显示源码已在本地编译运行通过配置好相应环境即可启动使用功能实现经过指导教师认可能够满足常规课题的功能与展示要求。目前已有181人学习关注适合需要快速搭建数据分析可视化项目、参考爬虫采集与Django前后端整合思路的读者下载研究。1. 从一份商品销售数据分析可视化系统源码说起它到底能解决什么问题电商运营每天面对的是后台导出的几十列订单表字段里混着退款、优惠券、SKU 编码想回答哪个品类在哪个城市卖得最好这种问题靠 Excel 透视表要拖半天。基于 Python 的商品销售数据分析可视化系统带爬虫源码本质是把这条链路固化下来爬虫负责把商品和评论数据抓回来pandas 负责清洗聚合可视化层负责把结论画成图。它适合三类人想拿一个完整项目练手的 Python 入门者、需要给业务方出日报的运营开发、以及想理解数据从采集到看板全链路的转行者。这套东西不是玩具把爬虫的合规边界、数据清洗的字段映射、可视化的交互选型三件事做对它就能直接跑在真实业务里。2. 爬虫层怎么搭requests xpath 抓商品数据的可复现路径2.1 为什么选 requests lxml 而不是上来就上分布式爬虫很多人一提到爬虫就想到 Scrapy 集群、分布式调度但商品销售数据这个场景的数据量通常在几万到几十万条单机 requests 配合并发池完全够用。选 requests 的理由很直接调试成本低出问题能一行行打印响应内容lxml 的 xpath 解析比 BeautifulSoup 快一个量级且对不规范 HTML 容错更好。分布式爬虫留到数据量上百万、或者需要多机 IP 轮换时再考虑过早引入只会让调试变成玄学。真正要提前想清楚的是目标站点的结构。商品列表页通常分页详情页有价格、销量、评论数评论又单独一个接口。我一般先把这三类 URL 的规律摸清楚再决定抓取顺序先列表页拿商品 ID 集合再逐个请求详情最后按需拉评论。这样即使中途失败也能从 ID 集合断点续爬。2.2 最小可运行爬虫列表页 详情页两段式抓取import requests from lxml import etree import time import random import csv HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36, Accept-Language: zh-CN,zh;q0.9, } def fetch(url, retry3): 带重试的请求封装失败返回 None for i in range(retry): try: resp requests.get(url, headersHEADERS, timeout10) if resp.status_code 200: resp.encoding resp.apparent_encoding # 防止中文乱码 return resp.text except requests.RequestException as e: print(f第{i1}次请求失败: {e}) time.sleep(random.uniform(1, 3)) # 随机间隔降低被封风险 return None def parse_list(html): 解析列表页返回商品ID和详情页链接 tree etree.HTML(html) items tree.xpath(//div[classproduct-item]) result [] for item in items: pid item.xpath(./data-id)[0] link item.xpath(./a/href)[0] result.append({pid: pid, url: link}) return result def parse_detail(html, pid): 解析详情页抽取价格、销量、标题 tree etree.HTML(html) def safe(xp): r tree.xpath(xp) return r[0].strip() if r else return { pid: pid, title: safe(//h1[classtitle]/text()), price: safe(//span[classprice]/text()), sales: safe(//span[classsales]/text()), } if __name__ __main__: rows [] for page in range(1, 6): # 抓前5页 list_url fhttps://example.com/list?page{page} html fetch(list_url) if not html: continue for item in parse_list(html): detail_html fetch(item[url]) if detail_html: rows.append(parse_detail(detail_html, item[pid])) time.sleep(random.uniform(0.5, 1.5)) with open(products.csv, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnames[pid, title, price, sales]) writer.writeheader() writer.writerows(rows)这段代码的逻辑分三层fetch负责网络请求的健壮性parse_list和parse_detail负责解析主流程负责调度和落盘。参数上timeout10是防止某个请求卡死拖垮整个任务random.uniform(1, 3)的重试间隔和0.5, 1.5的抓取间隔是经验值太快容易触发风控太慢效率低resp.apparent_encoding是处理中文站点乱码最省事的办法比手动指定 gbk 或 utf-8 稳。提示xpath 里的 class 名一定要用浏览器开发者工具实际确认很多站点 class 是动态生成的写死会直接抓空。2.3 反爬应对与合规边界常见反爬有三类请求头校验、频率限制、动态渲染。请求头校验靠补全 User-Agent、Referer、Cookie 解决频率限制靠随机间隔和并发控制动态渲染数据由 JS 加载则需要看 Network 面板找真实接口直接请求接口比上 Selenium 快得多。我一般优先找接口实在找不到才用无头浏览器。合规这块必须说清楚只抓公开可见的商品信息不碰用户隐私字段遵守目标站点的 robots.txt控制频率不对服务器造成压力。这三条不是道德说教是让项目能长期跑下去的前提。3. 数据清洗与销售指标计算pandas 把脏数据变成能分析的宽表3.1 商品数据常见的四类脏数据爬回来的数据几乎没有直接能用的。价格字段带¥和起字销量带人付款标题里混着促销词还有重复抓取和缺失值。清洗的目标是产出一张宽表每行一个商品列是数值化的价格、销量、品类、城市等维度。这一步做不干净后面所有图表都是错的。我一般按固定顺序处理去重 → 类型转换 → 缺失值处理 → 异常值处理。顺序不能乱先去重能减少后续计算量先转类型才能做数值判断。3.2 用 pandas 完成清洗和派生指标import pandas as pd import numpy as np df pd.read_csv(products.csv) # 1. 去重同一pid只保留一条 df df.drop_duplicates(subset[pid], keepfirst) # 2. 价格清洗去掉非数字字符转float df[price] ( df[price].astype(str) .str.replace(r[^\d.], , regexTrue) .replace(, np.nan) .astype(float) ) # 3. 销量清洗提取数字 df[sales] ( df[sales].astype(str) .str.extract(r(\d))[0] .astype(float) ) # 4. 缺失值价格缺失用中位数填充销量缺失填0 df[price] df[price].fillna(df[price].median()) df[sales] df[sales].fillna(0) # 5. 异常值价格超过99分位或为0的剔除 q99 df[price].quantile(0.99) df df[(df[price] 0) (df[price] q99)] # 6. 派生指标销售额 价格 × 销量 df[revenue] df[price] * df[sales] # 7. 价格分档方便做分组分析 bins [0, 50, 100, 300, 1000, np.inf] labels [50以下, 50-100, 100-300, 300-1000, 1000以上] df[price_band] pd.cut(df[price], binsbins, labelslabels) df.to_csv(products_clean.csv, indexFalse, encodingutf-8-sig) print(df.describe())关键点说明str.replace(r[^\d.], , regexTrue)用正则把所有非数字和小数点的字符清掉这是处理价格字段最通用的写法str.extract(r(\d))从1.2万人付款里提取数字注意这里没处理万字真实场景要加一步判断乘以 10000quantile(0.99)剔除极端值避免个别天价商品把均值拉飞pd.cut做价格分档是后面做分组柱状图的基础。注意fillna用中位数而不是均值是因为价格分布通常右偏均值容易被高价商品带偏。3.3 销售分析常用的五个聚合维度清洗完的宽表要回答业务问题靠的是 groupby。我常用的五个维度按品类看销售额占比、按价格带看销量分布、按城市看区域热度、按时间看销售趋势、按价格和销量的散点看爆款特征。每个维度对应一张图这就是可视化层的数据源。# 按价格带聚合 band_stat df.groupby(price_band).agg( 商品数(pid, count), 总销量(sales, sum), 总销售额(revenue, sum) ).reset_index() # 按品类聚合假设有category列 if category in df.columns: cat_stat df.groupby(category)[revenue].sum().sort_values(ascendingFalse)聚合结果直接喂给可视化库不要在可视化层再做计算这是分层设计的基本原则。4. 可视化层选型ECharts 还是 Pyecharts看板怎么落地4.1 静态图、交互图、大屏三种需求的选型逻辑可视化不是越炫越好要看交付形态。如果只是给自己看分析结论matplotlib 或 seaborn 出静态图最快如果要给业务方一个能点、能筛选的网页ECharts 是首选如果要做成挂在墙上的可视化大屏那要考虑布局、配色、自动刷新ECharts 配合大屏模板更合适。Pyecharts 是 ECharts 的 Python 封装好处是能在 Python 里直接生成 HTML不用写 JS。缺点是复杂交互比如联动筛选、自定义 tooltip还是要回到 ECharts 原生配置。我的做法是常规图表用 Pyecharts 快速出需要深度定制的图表直接写 ECharts 配置项。4.2 用 Pyecharts 生成销售看板的核心图表from pyecharts import options as opts from pyecharts.charts import Bar, Pie, Line, Scatter, Page # 1. 价格带销量柱状图 bar ( Bar() .add_xaxis(band_stat[price_band].astype(str).tolist()) .add_yaxis(总销量, band_stat[总销量].tolist()) .set_global_opts( title_optsopts.TitleOpts(title各价格带销量分布), xaxis_optsopts.AxisOpts(name价格区间), yaxis_optsopts.AxisOpts(name销量), ) ) # 2. 品类销售额饼图 pie ( Pie() .add(, [list(z) for z in zip(cat_stat.index.tolist(), cat_stat.values.tolist())]) .set_global_opts(title_optsopts.TitleOpts(title品类销售额占比)) .set_series_opts(label_optsopts.LabelOpts(formatter{b}: {d}%)) ) # 3. 价格-销量散点图找爆款 scatter ( Scatter() .add_xaxis(df[price].tolist()) .add_yaxis(销量, df[sales].tolist()) .set_global_opts( title_optsopts.TitleOpts(title价格与销量关系), xaxis_optsopts.AxisOpts(name价格, type_value), yaxis_optsopts.AxisOpts(name销量), ) ) # 4. 组合成一个页面 page Page(layoutPage.SimplePageLayout) page.add(bar, pie, scatter) page.render(dashboard.html)参数说明formatter{b}: {d}%是饼图标签模板{b}是名称{d}是百分比散点图的 x 轴要设type_value才能按数值连续分布默认是类目轴会把点挤在一起Page.SimplePageLayout是纵向排列大屏场景要换成DraggablePageLayout手动拖布局。4.3 看板从本地 HTML 到可访问服务的两种路径生成的dashboard.html是纯静态文件双击就能看。如果要给团队访问两条路一是丢到任意静态服务器Nginx 托管一个目录即可二是用 Flask 包一层把数据查询做成接口前端定时刷新。前者适合数据变化不频繁的日报后者适合需要实时或按条件筛选的场景。from flask import Flask, render_template app Flask(__name__) app.route(/) def index(): # 这里可以每次请求重新读数据、重新计算 return render_template(dashboard.html) if __name__ __main__: app.run(host0.0.0.0, port5000)Flask 方案的关键是把数据计算和模板渲染分开模板只负责展示数据在视图函数里准备好传进去。这样后续换数据源不用动前端。5. 避坑与排查这套系统跑起来最容易翻车的五个地方5.1 爬虫返回 200 但解析结果为空现象请求成功状态码 200但 xpath 提取出来全是空列表。原因通常是页面结构变了或者返回的是 JS 渲染的空壳 HTML。解决先把resp.text存到文件里打开看确认是不是真实数据如果是空壳去 Network 面板找 XHR 接口直接请求接口拿 JSON。5.2 中文乱码导致价格和标题全错现象CSV 打开是乱码或者价格字段里混着问号。原因是没有正确设置编码requests 默认用 ISO-8859-1 解码。解决请求后立刻设resp.encoding resp.apparent_encoding写 CSV 时用encodingutf-8-sig这个带 BOM 的格式能让 Excel 正确识别中文。5.3 pandas 读取后价格列是 object 类型无法计算现象df[price].mean()报错或返回奇怪结果。原因是列里混着字符串和数字。解决用pd.to_numeric(df[price], errorscoerce)强制转换无法转换的变成 NaN再统一处理缺失值。比手动 replace 更稳。5.4 Pyecharts 图表在浏览器里空白现象HTML 打开了但图表区域一片白。原因通常是 CDN 资源加载失败Pyecharts 默认从网络加载 echarts.min.js。解决在Page或图表初始化时指定init_optsopts.InitOpts(js_host本地路径)或者把 echarts.min.js 下载到本地改模板引用本地文件。5.5 数据量大了之后内存爆掉现象抓了几十万条后程序卡死或 MemoryError。原因是把所有数据堆在内存里。解决爬虫阶段就分批写盘不要全攒在 list 里pandas 读取时用chunksize分块处理聚合完只保留结果表原始明细及时释放。6. 让这套系统真正可用三个我踩过坑才养成的习惯第一个习惯是给爬虫加断点续爬。我早期抓一个几万条的商品库跑到一半网络断了重头再来白白浪费两小时。后来改成每抓 500 条就写一次盘同时记录已完成的页码或 ID重启时先读进度文件跳过已完成部分。这个改动不大但把长任务的可靠性拉高了一个档次。import os, json PROGRESS_FILE progress.json def load_progress(): if os.path.exists(PROGRESS_FILE): with open(PROGRESS_FILE, encodingutf-8) as f: return json.load(f) return {done_pages: []} def save_progress(progress): with open(PROGRESS_FILE, w, encodingutf-8) as f: json.dump(progress, f, ensure_asciiFalse)第二个习惯是清洗前后都做数据快照。清洗前的原始 CSV 保留一份清洗后的宽表另存一份中间每一步转换都打印行数和关键列的 describe。这样一旦发现最终图表数字不对能快速定位是哪一步把数据改坏了。血泪经验是不要在一个脚本里既抓取又清洗又画图分成三个脚本每个脚本的输入输出都是文件出问题好排查。第三个习惯是给可视化加数据校验。图表画出来好看不代表对我一般会在看板顶部放几个关键数字卡片总商品数、总销售额、平均价格和 pandas 里算出来的对一遍。数字对不上先查数据别急着调样式。习惯解决的问题落地成本断点续爬长任务中断重跑加一个进度文件约 20 行代码数据快照定位清洗错误每步存一个中间文件数字校验卡片图表与数据不一致看板加三个统计值这套系统值不值得做我的判断是如果你需要一个能讲清楚数据从哪来、怎么变干净、怎么变成结论的完整项目它值得如果你只是想要一张图那直接用 Excel 更快。真正拉开差距的不是图表多炫而是爬虫稳不稳、清洗对不对、数字能不能复现。希望帮到你。本文还有配套的精品资源点击获取