🚗 懂车帝汽车销售数据分析系统
项目概述
本项目是一个完整的汽车销售数据采集与可视化分析系统,从懂车帝网站自动采集热门新能源品牌的销量数据,并通过 Django + ECharts 技术栈实现多维度数据可视化分析。项目涵盖了数据采集、数据存储、数据导入、可视化分析的全流程解决方案。
技术栈: Python 爬虫 | Django Web框架 | MySQL数据库 | ECharts可视化
目标品牌: 蔚来、理想、小鹏、小米汽车、极氪
📑 目录
一、爬虫模块
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个月销量预测
- 算法说明面板:解释使用的预测算法和置信度计算
筛选条件:
- 品牌筛选:支持"全部品牌"或具体品牌选择
预测算法:
本页面采用组合预测算法,综合多种预测方法提高准确性:
- 移动平均法 (MA-3):计算最近3个月的平均销量(权重20%)
- 加权移动平均法 (WMA):越近期数据权重越高(权重25%)
- 指数平滑法 (ETS):平滑系数α=0.7,更注重近期数据(权重30%)
- 线性趋势预测:基于历史趋势的线性回归(权重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 项目亮点
- 全流程自动化:从数据采集到可视化分析,实现端到端的自动化流程
- 多种预测算法:采用组合预测算法,综合多种统计方法提高预测准确性
- 丰富的可视化:涵盖柱状图、折线图、散点图、热力图、箱线图、饼图等多种图表类型
- 交互友好:支持多维度筛选,提供详细的交互提示和响应式布局
5.2 未来改进方向
- 扩大数据范围:增加更多汽车品牌和传统燃油车数据
- 增强预测模型:引入机器学习算法,提高预测准确性
- 实时数据看板:实现数据的实时更新和推送
- 移动端适配:优化移动端查看体验
- 数据分析报告:自动生成月度/季度数据分析报告
💡 提示: 需要作者博客中的项目可以直接@即可。