懂车帝汽车销售数据可视化分析系统

🚗 懂车帝汽车销售数据分析系统

项目概述

本项目是一个完整的汽车销售数据采集与可视化分析系统,从懂车帝网站自动采集热门新能源品牌的销量数据,并通过 Django + ECharts 技术栈实现多维度数据可视化分析。项目涵盖了数据采集、数据存储、数据导入、可视化分析的全流程解决方案。

技术栈: Python 爬虫 | Django Web框架 | MySQL数据库 | ECharts可视化

目标品牌: 蔚来、理想、小鹏、小米汽车、极氪


📑 目录

  1. 一、爬虫模块
  2. 二、数据导入模块
  3. 三、数据可视化模块
  4. 四、项目结构
  5. 五、总结与展望

一、爬虫模块

1.1 模块介绍

爬虫模块负责从懂车帝网站自动采集汽车销量数据。系统针对国内热门新能源品牌(蔚来、理想、小鹏、小米汽车、极氪)进行定向数据采集,获取每月各车系的销量排名数据。

1.2 核心功能

  • 多品牌并行采集:支持同时采集多个品牌的销量数据
  • 月度数据追溯:支持从指定起始月份到当前月份的历史数据采集
  • 智能请求限流:设置请求间隔,避免对目标网站造成过大压力
  • 自动重试机制:网络请求失败时自动重试,提高数据采集成功率
  • 增量更新策略:采用 DELETE + INSERT 策略确保数据最新

1.3 核心代码解析

请求参数构建:

python 复制代码
def build_rank_params(month: int | str | None, brand_id: int) -> dict:
    return {
        "aid": "1839",
        "app_name": "auto_web_pc",
        "city_name": "",
        "count": "100",
        "offset": "0",
        "month": "" if month in (None, "") else str(month),
        "new_energy_type": "",
        "rank_data_type": "11",
        "brand_id": str(brand_id),
        "price": "",
        "manufacturer": "",
        "series_type": "",
        "nation": "0",
    }

数据替换写入:

python 复制代码
def replace_month_sales(conn, month: int, sales_list: list[dict]) -> int:
    rows = transform_sales_rows(month, sales_list)
    with conn.cursor() as cursor:
        cursor.execute("DELETE FROM sales_vehicledata WHERE month = %s", (month,))
        if rows:
            cursor.executemany(
                """
                INSERT INTO sales_vehicledata (
                    brand_name, series_id, series_name, month, rank_no, sales_count,
                    min_price, max_price, price_text, dealer_price, image_url,
                    description, created_at, updated_at
                )
                VALUES (...)
                ON DUPLICATE KEY UPDATE ...,
                """,
                rows,
            )
    conn.commit()
    return len(rows)

1.4 使用方式

bash 复制代码
python scraw.py

运行效果示例:

复制代码
目标月份: [202301, 202302, 202303, ...]
[1/15] 202301: 写入 320 条全国销量数据 (蔚来:85, 理想:72, 小鹏:68, 小米汽车:45, 极氪:50)
[2/15] 202302: 写入 315 条全国销量数据 (蔚来:82, 理想:75, 小鹏:65, 小米汽车:48, 极氪:45)
...
完成,成功任务数: 15,失败任务数: 0
MySQL 数据库: localhost:3306/dongchedi_db -> sales_vehicledata

二、数据导入模块

2.1 模块介绍

数据导入模块提供将 CSV 格式的销量数据批量导入 Django 数据库的功能。通过 Django ORM 的 update_or_create 方法实现数据的 upsert 操作,确保数据的唯一性同时支持重复导入。

2.2 核心功能

  • CSV 批量导入:支持读取本地 CSV 文件并批量写入数据库
  • Upsert 策略:根据车系ID和月份组合判断,数据存在则更新,不存在则创建
  • 进度显示:实时显示导入进度,便于监控大批量数据导入
  • 错误处理:详细的错误日志记录,便于排查问题

2.3 核心代码解析

python 复制代码
def import_data():
    csv_file = 'sales_vehicledata.csv'

    with open(csv_file, 'r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        total = sum(1 for _ in open(csv_file, 'r', encoding='utf-8')) - 1
        created_count = 0
        updated_count = 0

        for row in tqdm(reader, total=total, desc="导入数据"):
            try:
                obj, created = VehicleData.objects.update_or_create(
                    series_id=int(row['series_id']),
                    month=int(row['month']),
                    defaults={
                        'brand_name': row['brand_name'],
                        'series_name': row['series_name'],
                        'rank_no': int(row['rank_no']),
                        'sales_count': int(row['sales_count']),
                        'min_price': float(row['min_price']) if row['min_price'] else None,
                        'max_price': float(row['max_price']) if row['max_price'] else None,
                        'price_text': row.get('price_text', ''),
                        'dealer_price': row.get('dealer_price', ''),
                        'image_url': row.get('image_url', ''),
                        'description': row.get('description', ''),
                    }
                )

                if created:
                    created_count += 1
                else:
                    updated_count += 1

            except Exception as e:
                print(f"导入失败: {row} - {e}")

    print(f"导入完成! 新增: {created_count}, 更新: {updated_count}")

2.4 使用方式

bash 复制代码
python import_data.py

三、数据可视化模块

3.1 销量分析页面

路由地址: /vehicle-sales/

页面功能:

  • 展示各汽车品牌的年度总销量柱状图
  • 支持按品牌筛选,动态显示该品牌下所有车系的总销量
  • 图表交互丰富,支持悬停提示、点击筛选等功能

筛选条件:

  • 品牌筛选:支持"全部品牌"或具体品牌选择

核心实现:

python 复制代码
def vehicle_sales_view(request):
    brand_name = request.GET.get('brand_name', '全部品牌')

    # 获取品牌总销量
    brand_data = VehicleData.objects.values('brand_name').annotate(
        total_sales=Sum('sales_count')
    ).order_by('-total_sales')

    # 根据筛选条件获取车系销量
    if brand_name == '全部品牌':
        series_data = VehicleData.objects.values('series_name', 'brand_name').annotate(
            total_sales=Sum('sales_count')
        ).order_by('-total_sales')
    else:
        series_data = VehicleData.objects.filter(
            brand_name=brand_name
        ).values('series_name', 'brand_name').annotate(
            total_sales=Sum('sales_count')
        ).order_by('-total_sales')

    context = {
        'brand_list': brand_list,
        'brand_names': json.dumps(brand_names),
        'brand_sales': json.dumps(brand_sales),
        'series_names': json.dumps(series_names),
        'series_sales': json.dumps(series_sales),
    }
    return render(request, 'VehicleSales.html', context)

效果截图:


3.2 销量趋势页面

路由地址: /vehicle-trend/

页面功能:

  • 展示不同车系在过去一年内的月度销量趋势
  • 支持按品牌和年份双重筛选
  • 多系列折线图展示,直观对比各车系销售走势

筛选条件:

  • 品牌筛选:支持"全部品牌"或具体品牌选择
  • 年份筛选:支持选择不同年份的数据

核心实现:

python 复制代码
def vehicle_trend_view(request):
    brand_name = request.GET.get('brand_name', '全部品牌')
    year = request.GET.get('year', '2023')

    # 按车系组织数据,手动去重
    series_dict = {}
    for item in all_data:
        series_name = item['series_name']
        if series_name not in series_dict:
            series_dict[series_name] = {}
        month = item['month']
        sales = item['sales_count']
        if month not in series_dict[series_name]:
            series_dict[series_name][month] = 0
        series_dict[series_name][month] += sales

    # 构建折线图数据
    series_data = []
    for series in series_list:
        sales_by_month = []
        for m in range(1, 13):
            month = year_int*100 + m
            total = series_dict[series].get(month, 0)
            sales_by_month.append(total)
        series_data.append({
            'series_name': series,
            'sales_data': sales_by_month
        })

效果截图:


3.3 价格销量关系页面

路由地址: /price-sales/

页面功能:

  • 散点图:展示价格与销量的关系分布,每个点代表一个车系
  • 区间柱状图:按价格区间(0-10万、10-20万、20-30万等)统计总销量
  • 区间折线图:展示各价格区间的平均销量趋势
  • 箱线图:展示各价格区间的销量分布情况

筛选条件:

  • 品牌筛选:支持"全部品牌"或具体品牌选择
  • 年份筛选:支持选择不同年份的数据

核心实现:

python 复制代码
def price_sales_view(request):
    # 按价格区间分组统计
    price_ranges = [
        (0, 10, '0-10万'),
        (10, 20, '10-20万'),
        (20, 30, '20-30万'),
        (30, 50, '30-50万'),
        (50, 100, '50-100万'),
        (100, 1000, '100万以上')
    ]

    bar_data = []
    line_data = []
    box_data = []

    for min_p, max_p, name in price_ranges:
        range_data = [d for d in price_sales_list if min_p <= d['price'] < max_p]
        total = sum(d['sales'] for d in range_data)
        avg = total / len(range_data) if range_data else 0

        bar_data.append({'name': name, 'value': total})
        line_data.append({'name': name, 'value': avg})

        # 计算箱线图数据:最小值、Q1、中位数、Q3、最大值
        sales_values = [d['sales'] for d in range_data]
        if sales_values:
            sales_values.sort()
            n = len(sales_values)
            box_data.append({
                'name': name,
                'value': [sales_values[0], sales_values[n//4], sales_values[n//2],
                         sales_values[3*n//4], sales_values[-1]]
            })

效果截图:


3.4 冠军车型排行榜页面

路由地址: /champion-vehicles/

页面功能:

  • 热力图:展示每月各品牌的冠军车型,直观看出谁经常夺冠
  • 柱状图:展示各车系获得冠军次数的排行榜
  • 饼图:展示各品牌获得冠军次数的占比分布

筛选条件:

  • 品牌筛选:支持"全部品牌"或具体品牌选择
  • 年份筛选:支持选择不同年份的数据

核心实现:

python 复制代码
def champion_vehicles_view(request):
    # 找出每个品牌每个月的冠军车型(rank_no=1)
    champion_dict = {}
    for item in all_data:
        brand = item['brand_name']
        month = item['month']
        month_num = int(str(month)[-2:])
        rank = item['rank_no']
        series = item['series_name']

        if rank == 1:
            if brand not in champion_dict:
                champion_dict[brand] = {}
            champion_dict[brand][month_num] = series

    # 构建热力图数据
    heatmap_data = []
    for brand_idx, brand in enumerate(brands):
        for month_idx, month in enumerate(months):
            if brand in champion_dict and month in champion_dict[brand]:
                series_name = champion_dict[brand][month]
                heatmap_data.append([brand_idx, month_idx, series_name])

    # 统计冠军次数
    series_champion_count = {}
    brand_champion_count = {}
    for brand, month_data in champion_dict.items():
        for month, series in month_data.items():
            series_champion_count[series] = series_champion_count.get(series, 0) + 1
            brand_champion_count[brand] = brand_champion_count.get(brand, 0) + 1

效果截图:



3.5 销量预测页面

路由地址: /sales-prediction/

页面功能:

  • 冠军预测卡片:展示未来3个月各品牌的预测冠军车系
  • 销量预测折线图:展示历史销量 + 未来3个月销量预测
  • 算法说明面板:解释使用的预测算法和置信度计算

筛选条件:

  • 品牌筛选:支持"全部品牌"或具体品牌选择

预测算法:

本页面采用组合预测算法,综合多种预测方法提高准确性:

  1. 移动平均法 (MA-3):计算最近3个月的平均销量(权重20%)
  2. 加权移动平均法 (WMA):越近期数据权重越高(权重25%)
  3. 指数平滑法 (ETS):平滑系数α=0.7,更注重近期数据(权重30%)
  4. 线性趋势预测:基于历史趋势的线性回归(权重25%)

置信度计算:

  • 基于可用数据量(数据越多,置信度越高)
  • 基于历史数据的波动幅度(波动越小,置信度越高)
  • 最终置信度 = 0.5 + 数据量权重 + 稳定性权重

核心实现:

python 复制代码
def predict_sales(time_series):
    """使用多种方法进行销量预测"""
    sorted_data = sorted(time_series, key=lambda x: x[0], reverse=True)
    recent_sales = [x[1] for x in sorted_data[:6]]
    recent_sales.reverse()

    predictions = []

    # 方法1: 简单移动平均 (MA-3)
    if n >= 3:
        ma3 = sum(recent_sales[-3:]) / 3
        predictions.append((ma3, 0.2))

    # 方法2: 加权移动平均 (WMA)
    if n >= 3:
        weights = [0.2, 0.3, 0.5]
        wma = sum(recent_sales[-3:][i] * weights[i] for i in range(3))
        predictions.append((wma, 0.25))

    # 方法3: 指数平滑 (ETS, α=0.7)
    if n >= 1:
        ets = recent_sales[0]
        alpha = 0.7
        for i in range(1, n):
            ets = alpha * recent_sales[i] + (1 - alpha) * ets
        predictions.append((ets, 0.3))

    # 方法4: 线性趋势预测
    if n >= 2:
        slope = numerator / denominator if denominator != 0 else 0
        intercept = mean_y - slope * mean_x
        trend_pred = intercept + slope * (n + 1)
        predictions.append((trend_pred, 0.25))

    # 加权平均
    final_pred = sum(p * w for p, w in predictions) / sum(w for p, w in predictions)
    return final_pred, confidence

效果截图:



四、项目结构

复制代码
懂车帝汽车销售数据分析/
├── spider/                          # 爬虫模块
│   ├── scraw.py                    # 数据采集脚本
│   ├── import_data.py             # 数据导入脚本
│   └── sales_vehicledata.csv      # CSV数据文件
│
├── myapp/                          # Django应用
│   ├── models.py                   # 数据模型定义
│   ├── views.py                   # 视图函数
│   └── ...
│
├── templates/                      # HTML模板
│   ├── VehicleSales.html          # 销量分析页面
│   ├── VehicleSalesTrend.html     # 销量趋势页面
│   ├── VehiclePriceSales.html     # 价格销量关系页面
│   ├── ChampionVehicles.html      # 冠军车型排行榜页面
│   └── VehicleSalesPrediction.html # 销量预测页面
│
├── 懂车帝汽车销售数据分析/           # Django项目配置
│   ├── urls.py                    # URL路由配置
│   └── ...
│
└── static/                         # 静态资源
    ├── css/                       # 样式文件
    ├── js/                        # JavaScript文件
    └── imgs/                      # 图片资源

五、总结与展望

5.1 项目亮点

  1. 全流程自动化:从数据采集到可视化分析,实现端到端的自动化流程
  2. 多种预测算法:采用组合预测算法,综合多种统计方法提高预测准确性
  3. 丰富的可视化:涵盖柱状图、折线图、散点图、热力图、箱线图、饼图等多种图表类型
  4. 交互友好:支持多维度筛选,提供详细的交互提示和响应式布局

5.2 未来改进方向

  • 扩大数据范围:增加更多汽车品牌和传统燃油车数据
  • 增强预测模型:引入机器学习算法,提高预测准确性
  • 实时数据看板:实现数据的实时更新和推送
  • 移动端适配:优化移动端查看体验
  • 数据分析报告:自动生成月度/季度数据分析报告

💡 提示: 需要作者博客中的项目可以直接@即可。

相关推荐
X56616 小时前
c++ aot编程 c++如何使用oneapi进行跨平台并行编程
jvm·数据库·python
2501_901006476 小时前
如何按优先级控制 Flex 容器中子元素的截断顺序
jvm·数据库·python
日光明媚6 小时前
torch.compile 与 Triton 的加速本质:从原理到实际效果
人工智能·python·计算机视觉·stable diffusion·aigc
m0_624578596 小时前
CSS如何优化Bootstrap加载速度_利用CSS压缩技术减少体积
jvm·数据库·python
Ulyanov6 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》:动态数据仪表盘与 NumPy 可视化 —— 从标量到向量的数据驱动进化
开发语言·python·qt·架构·numpy
深蓝海拓6 小时前
PySide6,图形按钮使用系统内置图标
笔记·python·学习·pyqt
chushiyunen6 小时前
npy文件笔记
笔记·python
念恒123066 小时前
Python(列表入门)
python·学习
zjy277776 小时前
Go语言怎么用GitHub Actions_Go语言GitHub Actions教程【基础】
jvm·数据库·python