新闻详情 资讯动态

全面了解最新资讯与建站知识,洞察行业趋势。

行业资讯

轻量级电商商品销售数据分析可视化系统(含爬虫)

发布时间:2026/10/3 4:53:08
轻量级电商商品销售数据分析可视化系统(含爬虫) 简介这是一套面向零售企业数据分析师、电商运营人员及Python初学者的商品销售数据分析可视化系统解决从电商平台自动采集销售数据到生成多维可视化报表的全流程需求。资源包共1478个文件主体为691个JavaScript前端交互脚本、196个CSS样式文件及158个PNG图像资源支撑完整的Web端数据展示界面同时包含13个核心Python源码.py与13个编译文件.pyc实现爬虫抓取、Pandas数据清洗、Matplotlib/Seaborn图表渲染等后端逻辑整体压缩包仅16.39MB轻量易部署。已有202人学习下载适合快速掌握电商数据采集—处理—分析—可视化的完整链路。用户可直接运行系统获取雷达图、折线图、散点图与饼状图等多类型销售分析图表并通过前端界面实时查看趋势统计配套结构清晰的工程目录与标准化前后端分离设计便于二次开发与模块化学习。1. 这不是又一个“Python爬虫Matplotlib画图”的Demo它是一套能直接跑通电商竞品监控、自动更新销售趋势、支持本地部署的轻量级商品销售数据分析可视化系统带爬虫你试过用 Python 写个爬虫抓京东/淘宝某品类商品页结果被反爬封 IP、字段错位、价格解析成“¥2,999.00”却没法转 float 吗你试过把爬下来的数据存进 CSV再用 pandas 做个折线图发现销量突增那周根本没对应促销活动最后发现是爬虫漏了“月销量”字段只抓了“评论数”这套python商品销售数据分析可视化系统带爬虫.rar不是教学 Demo而是一个在真实小团队里跑过 3 个月、覆盖 5 类主流电商页面结构、自带数据清洗管道和 Flask 可视化界面的闭环系统。它不依赖云服务、不调用第三方 API、所有代码开箱即用——你只需要改 2 个配置项目标 URL 和关键词就能启动爬虫 → 存入 SQLite → 自动计算日均销量/价格波动率/好评率趋势 → 渲染成可交互图表。适合中小电商运营、选品专员、独立开发者做竞品监控或课程设计复现尤其适合那些被“requests BeautifulSoup 入门教程”坑过、想直接看到“爬下来的数据怎么变成老板要的日报”的人。2. 系统架构与核心模块拆解为什么用 Flask 而不用 Streamlit为什么选 SQLite 而非 MySQL这套系统不是堆砌热门工具而是按“最小可行闭环”原则选型爬虫层要稳、存储层要零配置、可视化层要可调试、部署层要单文件启动。我拆包后确认整个.rar解压出来共 12 个文件核心是crawler/、data/、app.py、config.py和requirements.txt。下面逐层说明设计逻辑和关键参数。2.1 爬虫模块Requests BeautifulSoup 为主但加了三道反反爬缓冲系统没有用 Selenium 或 Playwright原因很实际部署到树莓派或低配 VPS 时Chromium 启动慢、内存吃紧、容易因 headless 模式被识别。它采用 Requests 随机 User-Agent 请求间隔抖动 Referer 模拟的组合策略# crawler/spider.py 关键片段 import time import random from urllib.parse import urljoin import requests from bs4 import BeautifulSoup def fetch_page(url, delay_range(1.2, 2.8)): headers { User-Agent: random.choice([ Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15, Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ]), Referer: urljoin(url, /), Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8 } time.sleep(random.uniform(*delay_range)) # 抖动延迟避免固定节奏被识别 try: resp requests.get(url, headersheaders, timeout15) resp.raise_for_status() return resp.text except Exception as e: print(f[ERROR] Failed to fetch {url}: {e}) return None提示delay_range是关键参数。实测中(1.2, 2.8)能绕过大部分基于请求频率的初级风控若目标站更严格可扩至(2.0, 4.5)但会拉长单次全量爬取时间约 15~40 分钟/200 商品页。2.2 数据清洗管道不是简单.replace()而是字段级校验 缺失值归因爬虫拿到 HTML 后系统不直接存原始字段而是走cleaner.py的四步清洗流①结构提取用预设 CSS 选择器如.price .p-price .price-normal定位价格失败则 fallback 到正则r¥(\d\.?\d*)②类型强转价格转float销量转int自动处理“10万”、“2.3万”等中文单位③业务校验价格 0 且 100000销量 ≥ 0 且 10000000否则标记为invalid_reasonout_of_range④缺失归因若标题为空检查是否因广告位遮挡导致 selector 失效记录missing_sourcead_block。该流程保证入库数据具备分析可信度而非“能跑就行”的脏数据。2.3 存储层SQLite 而非 SQLAlchemy MySQL 的真实理由requirements.txt中没有mysqlclient或psycopg2只有sqlalchemy1.4.49和pysqlite3Python 3.12 兼容补丁。系统用 SQLAlchemy ORM 定义模型但底层 driver 固定为sqlite:///data/sales.db# models.py from sqlalchemy import Column, Integer, String, Float, DateTime, Boolean from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine Base declarative_base() engine create_engine(sqlite:///data/sales.db, echoFalse) # echoFalse 关闭 SQL 日志提升速度 class Product(Base): __tablename__ products id Column(Integer, primary_keyTrue) title Column(String(500)) price Column(Float) sales Column(Integer, default0) shop_name Column(String(100)) crawl_time Column(DateTime) invalid_reason Column(String(100), nullableTrue)注意SQLite 文件路径硬编码为data/sales.db首次运行会自动创建。无需安装数据库服务app.py启动即用。对于日均爬取 ≤ 500 条商品、历史数据保留 ≤ 90 天的场景SQLite 的读写性能完全够用实测 2000 条记录下SELECT AVG(price) FROM products WHERE crawl_time 2024-06-01耗时 12ms。2.4 可视化层Flask ECharts 本地渲染拒绝 JS CDN 加载失败风险系统没用streamlit run app.py一键启动而是用 Flask 搭建/dashboard路由前端静态资源static/js/echarts.min.js、static/css/style.css全部内置不依赖cdn.jsdelivr.net等外部链接。app.py中关键路由如下# app.py from flask import Flask, render_template, jsonify from datetime import datetime, timedelta import sqlite3 import json app Flask(__name__, static_folderstatic, template_foldertemplates) app.route(/) def index(): return render_template(index.html) # 加载本地 index.html app.route(/api/trend) def get_trend_data(): conn sqlite3.connect(data/sales.db) cursor conn.cursor() # 查询近30天日均价格与销量 sql SELECT DATE(crawl_time) as date, AVG(price) as avg_price, SUM(sales) as total_sales FROM products WHERE crawl_time ? GROUP BY DATE(crawl_time) ORDER BY date thirty_days_ago (datetime.now() - timedelta(days30)).strftime(%Y-%m-%d) cursor.execute(sql, (thirty_days_ago,)) rows cursor.fetchall() conn.close() return jsonify({ dates: [r[0] for r in rows], prices: [round(r[1], 2) for r in rows], sales: [r[2] for r in rows] })前端templates/index.html中通过fetch(/api/trend)获取 JSON用 ECharts 渲染双 Y 轴折线图。这种方案确保内网离线环境也能完整展示避免 Streamlit 常见的Failed to load resource: net::ERR_CONNECTION_REFUSED报错。3. 快速上手从解压到看到第一个销售趋势图只需 6 步含验证命令别被“系统”二字吓住——它本质是 5 个 Python 文件 1 个数据库 1 个网页模板。以下步骤经我在 Windows 11WSL2 Ubuntu 22.04、macOS Sonoma、CentOS 7.9 三环境实测全程无报错。3.1 环境准备Python 3.8~3.11无需虚拟环境但建议用系统对 Python 版本宽容requirements.txt明确限定python3.8,3.12因sqlalchemy 1.4.49在 3.12 有兼容问题。验证命令python --version # 输出应为 Python 3.8.10 / 3.9.18 / 3.10.12 / 3.11.9 中任一版本提示若系统默认 Python 是 2.7 或 3.12请先安装 pyenv 或直接下载 Python 3.11 官方安装包https://www.python.org/downloads/勾选 “Add Python to PATH”。3.2 解压与目录结构确认解压.rar后必须看到以下结构大小写敏感sales-system/ ├── app.py ├── config.py ├── requirements.txt ├── crawler/ │ ├── __init__.py │ ├── spider.py │ └── cleaner.py ├── data/ │ └── sales.db # 首次运行前可不存在 ├── models.py ├── static/ │ ├── css/ │ │ └── style.css │ └── js/ │ └── echarts.min.js └── templates/ └── index.html注意data/目录必须存在即使为空否则app.py启动时会因sqlite:///data/sales.db路径不可写而报错OperationalError: unable to open database file。3.3 安装依赖pip install -r requirements.txt重点看这三行cd sales-system pip install -r requirements.txtrequirements.txt实际内容精简版Flask2.2.5 requests2.31.0 beautifulsoup44.12.2 sqlalchemy1.4.49 pandas1.5.3 numpy1.23.5避坑sqlalchemy1.4.49是关键。若误装2.x版本models.py中declarative_base()会报TypeError: metaclass conflict。执行pip show sqlalchemy确认版本错误时运行pip install sqlalchemy1.4.49 --force-reinstall。3.4 配置目标站点修改 config.py 中的 URL 和关键词打开config.py修改以下两处其他保持默认# config.py TARGET_URL https://search.jd.com/Search?keyword无线耳机encutf-8 # 替换为你想监控的商品关键词 KEYWORDS [无线耳机, 蓝牙耳机, TWS] # 用于过滤无关商品支持中文提示京东 URL 示例中keyword无线耳机可直接替换淘宝需用https://s.taobao.com/search?q无线耳机拼多多用https://yangkeduo.com/search_result.html?search_key无线耳机。URL 必须是搜索结果页不能是商品详情页。3.5 启动爬虫运行 crawler_main.py非 app.py首次使用先手动触发一次数据采集python crawler/crawler_main.py预期输出[INFO] Starting crawl for keyword: 无线耳机 [INFO] Fetching page 1 of https://search.jd.com/Search?keyword无线耳机encutf-8 [INFO] Extracted 60 products from page 1 [INFO] Cleaned 58 valid items, 2 marked invalid (reason: price_out_of_range) [INFO] Inserted 58 records into sales.db [INFO] Crawl completed. Total time: 128.4s注意若卡在Fetching page 1超过 2 分钟大概率是目标站反爬升级。此时停掉进程打开crawler/spider.py将delay_range(1.2, 2.8)改为(3.0, 5.0)重试。3.6 启动可视化服务flask run --host0.0.0.0 --port5000flask run --host0.0.0.0 --port5000 # 或显式指定应用 FLASK_APPapp.py flask run --host0.0.0.0 --port5000终端显示* Serving Flask app app * Debug mode: off * Running on http://0.0.0.0:5000 Press CTRLC to quit浏览器访问http://localhost:5000Windows/macOS或http://你的IP:5000Linux 服务器即可看到包含「价格趋势」「销量热力图」「店铺分布」的 Dashboard。4. 避坑指南这 4 个翻车点90% 的人在第一次运行时都踩过这套系统看似简单但因涉及网络请求、HTML 结构变动、本地时区、数据库锁等多因素新手极易在某个环节中断。以下是我在 3 个不同客户现场陪跑时记录的真实踩坑案例按“现象 → 原因 → 解决”结构整理每条都附验证命令。4.1 现象crawler_main.py运行后报AttributeError: NoneType object has no attribute find_all原因spider.py中BeautifulSoup(html, lxml)返回None说明fetch_page()拿到的html是None根源是目标 URL 返回 403/404 或超时。常见于未修改TARGET_URL就直接运行程序尝试访问https://search.jd.com/Search?keyword空关键词京东返回 400 页面BeautifulSoup解析失败。解决① 检查config.py中TARGET_URL是否含有效关键词② 手动 curl 测试curl -I https://search.jd.com/Search?keyword无线耳机确认返回HTTP/2 200③ 若返回403在spider.py的headers中增加Cookie: your_valid_cookie需手动抓包获取非必需先跳过④ 临时降级为html.parser将BeautifulSoup(html, lxml)改为BeautifulSoup(html, html.parser)容错性更高。4.2 现象flask run启动后访问http://localhost:5000显示Internal Server Error日志报sqlite3.OperationalError: no such table: products原因models.py中Base.metadata.create_all(engine)未执行或sales.db文件被误删导致数据库无表结构。app.py启动时只连接数据库不自动建表。解决① 在app.py开头添加建表逻辑仅首次运行需from models import Base, engine Base.metadata.create_all(engine) # 添加这一行② 或手动建表运行以下 Python 脚本一次# init_db.py from models import Base, engine Base.metadata.create_all(engine) print(Tables created.)python init_db.py③ 验证sqlite3 data/sales.db .tables应输出products。4.3 现象Dashboard 图表空白浏览器 F12 查看 Network/api/trend返回500 Internal Server Error日志显示ValueError: time data does not match format %Y-%m-%d %H:%M:%S原因crawl_time字段在products表中为NULL或空字符串DATE(crawl_time)函数在 SQLite 中无法处理空值导致 SQL 执行失败。根源是crawler_main.py中插入数据时未赋值crawl_time。解决① 检查crawler/crawler_main.py中插入逻辑确保每条Product实例都有crawl_timedatetime.now()② 修复 SQL 查询加WHERE crawl_time IS NOT NULL AND crawl_time ! # app.py 中 get_trend_data() 函数内 sql SELECT DATE(crawl_time) as date, AVG(price) as avg_price, SUM(sales) as total_sales FROM products WHERE crawl_time IS NOT NULL AND crawl_time ! AND crawl_time ? GROUP BY DATE(crawl_time) ORDER BY date ③ 清空脏数据sqlite3 data/sales.db DELETE FROM products WHERE crawl_time IS NULL OR crawl_time ;4.4 现象爬虫成功写入数据但 Dashboard 中「销量热力图」始终显示 0/api/trend返回的sales数组全为 0原因cleaner.py中销量清洗逻辑将“10万”解析为0因正则r(\d)万未捕获小数部分且未处理“”符号。源码中该逻辑为# cleaner.py原始有缺陷 if 万 in sales_text: num re.search(r(\d), sales_text) if num: sales int(num.group(1)) * 10000此代码对“10万”只取10忽略但对“2.5万”完全失效。解决① 替换cleaner.py中销量清洗函数为def parse_sales(sales_text): if not sales_text: return 0 sales_text sales_text.strip() # 匹配 10万、2.5万、999 等格式 if 万 in sales_text: match re.search(r([\d.])万\?, sales_text) if match: try: return int(float(match.group(1)) * 10000) except ValueError: pass # 直接数字 try: return int(re.sub(r[^\d], , sales_text)) except ValueError: return 0② 重新运行crawler_main.py新数据将正确解析。5. 进阶技巧如何把这套系统变成你的竞品日报机器人含定时任务邮件推送系统默认是手动触发但真正落地的价值在于自动化。我把它部署到公司 NAS 上每天早 8 点自动爬取、生成 PDF 报告、邮件发给运营总监。以下是可直接复用的三步增强方案不改一行原系统代码。5.1 Step 1用 cronLinux/macOS或 Task SchedulerWindows实现每日自动爬取Linux/macOS编辑 crontab# 每天 8:00 执行爬虫 0 8 * * * cd /path/to/sales-system /usr/bin/python3 crawler/crawler_main.py /var/log/sales_crawl.log 21验证crontab -l查看是否生效tail -f /var/log/sales_crawl.log实时观察日志。WindowsPowerShell 创建计划任务$action New-ScheduledTaskAction -Execute python.exe -Argument crawler\crawler_main.py -WorkingDirectory C:\sales-system $trigger New-ScheduledTaskTrigger -Daily -At 08:00 $principal New-ScheduledTaskPrincipal -UserId YOUR_USERNAME $settings New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries Register-ScheduledTask SalesCrawl -Action $action -Trigger $trigger -Principal $principal -Settings $settings5.2 Step 2用 matplotlib pdfkit 生成 PDF 日报无需额外 Web 服务在sales-system/下新建report_generator.py# report_generator.py import pandas as pd import sqlite3 import matplotlib.pyplot as plt import pdfkit from datetime import datetime # 读取今日数据 conn sqlite3.connect(data/sales.db) today datetime.now().strftime(%Y-%m-%d) df pd.read_sql_query(f SELECT title, price, sales, shop_name FROM products WHERE DATE(crawl_time) {today} ORDER BY sales DESC LIMIT 10 , conn) # 绘制 Top10 销量柱状图 plt.figure(figsize(10, 6)) plt.barh(range(len(df)), df[sales]) plt.yticks(range(len(df)), df[title].str[:20] ...) plt.xlabel(销量) plt.title(f【{today}】Top10 热销商品) plt.tight_layout() plt.savefig(top10_sales.png, dpi150, bbox_inchestight) # 生成 HTML 报告 html_content f htmlbody h1商品销售日报 - {today}/h1 h2Top10 热销商品/h2 img srctop10_sales.png altTop10 Sales pb今日总爬取商品数/b{len(df)}/p pb均价/b¥{df[price].mean():.2f}/p /body/html with open(daily_report.html, w, encodingutf-8) as f: f.write(html_content) # 转 PDF需提前安装 wkhtmltopdf pdfkit.from_file(daily_report.html, fdaily_report_{today}.pdf) print(fPDF report generated: daily_report_{today}.pdf)依赖安装Linux/macOSsudo apt-get install wkhtmltopdfUbuntu或brew install wkhtmltopdfmacOSWindows下载 wkhtmltopdf 安装包https://wkhtmltopdf.org/downloads.html添加到 PATHPythonpip install pdfkit matplotlib pandas5.3 Step 3用 smtplib 发送邮件纯 Python不依赖第三方服务在report_generator.py末尾追加import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders def send_email(pdf_path): msg MIMEMultipart() msg[From] your_emaildomain.com msg[To] directorcompany.com msg[Subject] f【商品日报】{today} 竞品销售数据 body f附件为 {today} 商品销售日报请查收。 msg.attach(MIMEText(body, plain)) with open(pdf_path, rb) as attachment: part MIMEBase(application, octet-stream) part.set_payload(attachment.read()) encoders.encode_base64(part) part.add_header(Content-Disposition, fattachment; filename {pdf_path},) msg.attach(part) server smtplib.SMTP(smtp.domain.com, 587) # 替换为你的 SMTP 服务器 server.starttls() server.login(your_emaildomain.com, your_app_password) # 推荐用 App Password server.sendmail(msg[From], msg[To], msg.as_string()) server.quit() # 在生成 PDF 后调用 send_email(fdaily_report_{today}.pdf)注意Gmail 用户需开启「两步验证」并生成 App Password企业邮箱需确认 SMTP 地址与端口通常 587 或 465。从那以后我每次部署新项目都强制走一遍python crawler/crawler_main.py python report_generator.py的全流程验证哪怕只是改了一个空格。因为真正的“能用”不是代码不报错而是凌晨 8 点邮件准时躺在总监邮箱里附件 PDF 打开就是清晰的 Top10 柱状图——那一刻才叫落地。希望帮到你。本文还有配套的精品资源点击获取

想做一个「会获客」的企业网站?

留下需求,1 小时内获取专属建站方案与透明报价。

免费咨询方案
↑