当前位置: 首页 > news >正文

157-基于Python的懂车帝汽车数据爬虫分析与可视化系统

基于Python的懂车帝汽车数据爬虫分析与可视化系统:从采集到可视化的完整实践

本文分享一个从零到一落地的数据项目:基于 Python + Django 的“懂车帝汽车数据爬虫分析与可视化系统”。项目覆盖数据采集、清洗、入库、后端展示与 ECharts 可视化,适合作为课程设计/毕设/内部数据平台的入门与进阶参考。

本文包含:项目目录结构、技术栈说明、核心代码讲解、运行部署流程、可视化示例与拓展方向,并预留了可视化截图位。


目录

  • 项目简介与功能概览
  • 项目目录结构
  • 技术栈说明
  • 环境准备与安装
  • 配置说明(Django 与数据库)
  • 数据模型设计(Models)
  • 数据采集与清洗(爬虫 + Pandas)
  • 后端视图与路由
  • 前端可视化(ECharts 示例)
  • 运行与体验
  • 常见问题 FAQ
  • 可视化展示(预留位)
  • 拓展方向与总结

项目简介与功能概览

本系统围绕“新能源汽车数据”展开:

  • 数据源:基于懂车帝公开页面与接口采集车型和销量数据;
  • 数据库:落地 MySQL,提供车辆信息、销量、续航与整车参数等多维数据表;
  • 后端:Django 组织页面与数据,提供筛选、分页、统计;
  • 可视化:前端基于 ECharts 展示销量、分布、趋势、排行等图表;
  • 用户体系:注册、登录、退出、资料编辑与密码修改。

已实现的核心功能(真实可用)包括:

  • 用户注册/登录/退出、资料编辑、头像上传、密码修改;
  • 续航榜单、销量榜单、车型与整车参数数据的分页浏览与多条件筛选;
  • ECharts 可视化:月/年销量、月环比、六个月趋势、品牌销量、能源类型、价格区间、厂商分布、车型级别、驱动方式、电池类型/冷却方式、平均 CLTC 续航、平均整备质量等。

项目目录结构

下述为核心目录的精简视图(略去部分静态资源与图片):

car/
├─ car/                      # 业务应用
│  ├─ models.py              # 数据模型(User/Endurance/Car/CarInfo/CarData)
│  ├─ views.py               # 视图函数(列表页、可视化页、用户中心等)
│  ├─ urls.py                # 路由配置
│  └─ templates/             # 模板页面
│     ├─ index.html
│     ├─ login.html
│     ├─ register.html
│     ├─ edit_profile.html
│     ├─ change_password.html
│     ├─ endurance_list.html
│     ├─ car_list.html
│     ├─ car_info_list.html
│     ├─ car_data_list.html
│     ├─ endurance_visualization.html
│     ├─ car_sales_visualization.html
│     ├─ car_info_visualization.html
│     └─ car_data_visualization.html
├─ newcar/                   # Django 项目配置
│  ├─ settings.py            # 数据库/静态资源/语言/时区配置
│  ├─ urls.py
│  └─ wsgi.py / asgi.py
├─ spider/
│  └─ spiders.py             # 爬虫脚本(requests + lxml + pandas)
├─ utils/
│  ├─ reade_car_sales_data.py  # JSON 转 CSV + 图片下载
│  ├─ save_endurance_data.py   # 续航图片下载并更新 DB
│  ├─ getChartData.py          # 图表数据工具(示例/遗留)
│  └─ getPublicData.py         # 公共数据访问工具
├─ static/                   # 前端静态资源(Bootstrap/jQuery/ECharts 等)
├─ media/                    # 上传与下载的图片目录(头像、车辆图)
├─ design_157_car.sql        # MySQL 数据库初始化脚本(含表结构与数据)
└─ manage.py

技术栈说明

  • 后端与框架:
    • Django 4.1(模板 / ORM / 会话 / 路由)
    • Django SimpleUI(管理后台美化)
  • 数据库:
    • MySQL(django.db.backends.mysql
    • PyMySQL(脚本直连与更新)
  • 爬虫与数据处理:
    • requests、lxml(采集与解析)
    • pandas(CSV 清洗去重)
  • 前端与可视化:
    • Bootstrap、jQuery、Font Awesome
    • ECharts(含 wordcloud 与 liquidfill 扩展)

环境准备与安装

建议 Python 3.9+、MySQL 5.7+/8.0。

# 1) 创建并激活虚拟环境(任选其一)
python -m venv venv
"venv/Scripts/activate"  # Windows# 2) 安装依赖(根据实际需要精简/补充)
pip install django==4.1 pymysql requests lxml pandas# 如需使用 SimpleUI(可选)
pip install django-simpleui# 3) 数据库准备(两种方式,二选一)
# 方式A:导入现成 SQL(推荐用于快速跑通)
# 在 MySQL 中创建数据库 design_157_car 并导入根目录的 design_157_car.sql# 方式B:使用 Django 迁移(如果你打算从空库启动)
python manage.py makemigrations
python manage.py migrate# 4) 启动开发服务
python manage.py runserver 0.0.0.0:8000

配置说明(Django 与数据库)

关键设置位于 newcar/settings.py

DATABASES = {"default": {"ENGINE": "django.db.backends.mysql","NAME": "design_157_car","USER": "root","PASSWORD": "123456","HOST": "localhost","PORT": "3306",}
}STATIC_URL = "/static/"
STATICFILES_DIRS = (BASE_DIR / 'static',)MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / 'media'

数据模型设计(Models)

系统围绕五张核心表展开:用户、续航、销量、车辆信息、整车参数。

# car/models.py(节选)
class User(models.Model):username = models.CharField(max_length=255, default='')password = models.CharField(max_length=255, default='')address = models.CharField(max_length=255, default='')avatar = models.FileField(upload_to='avatar', default='avatar/default.png')textarea = models.CharField(max_length=255, default='')creatTime = models.DateField(auto_now_add=True)class Endurance(models.Model):img = models.FileField(upload_to='carPicture', default='')carName = models.CharField(max_length=255, default='')carType = models.CharField(max_length=255, default='')price = models.FloatField(default=0.0)range = models.IntegerField(default=0)achieveRate = models.CharField(max_length=255, default='')avgRate = models.CharField(max_length=255, default='')season = models.CharField(max_length=255, default='')temperature = models.CharField(max_length=255, default='')class Car(models.Model):seriesName = models.CharField(max_length=255, default='')masterPic = models.URLField(max_length=512, default='https://.../default.png')year = models.CharField(max_length=6, default='')  # '202410'monthSale = models.IntegerField(default=0)yearSale = models.IntegerField(default=0)monthBasis = models.CharField(max_length=10, default='')sixMonth = models.CharField(max_length=255, default='')  # '32691,34464,...'class CarInfo(models.Model):brand = models.CharField(max_length=100)carName = models.CharField(max_length=100)carImg = models.URLField(max_length=200)saleVolume = models.IntegerField()price = models.CharField(max_length=50)manufacturer = models.CharField(max_length=100)rank = models.IntegerField()carModel = models.CharField(max_length=100)energyType = models.CharField(max_length=50)marketTime = models.CharField(max_length=50)insure = models.CharField(max_length=50)class CarData(models.Model):manufacturer_model = models.CharField(max_length=100)car_name = models.CharField(max_length=100)guide_price = models.DecimalField(max_digits=10, decimal_places=2)car_level = models.CharField(max_length=50)body_structure = models.CharField(max_length=50)length = models.IntegerField()width = models.IntegerField()height = models.IntegerField()wheelbase = models.IntegerField()curb_weight = models.IntegerField()battery_type = models.CharField(max_length=50)energy_type = models.CharField(max_length=50)cell_brand = models.CharField(max_length=50)battery_cooling = models.CharField(max_length=50)cltc_range = models.IntegerField(null=True, blank=True)wltc_range = models.IntegerField(null=True, blank=True)battery_capacity = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)drag_coefficient = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)energy_density = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)drive_type = models.CharField(max_length=50)

数据采集与清洗(爬虫 + Pandas)

爬虫入口位于 spider/spiders.py,采用 requests 请求懂车帝接口,配合 lxml 抓取详情页补充字段,使用 pandas 清洗 CSV 再写入数据库。

# spider/spiders.py(节选)
class Spider(object):def __init__(self):self.baseUrl = 'https://www.dongchedi.com/motor/pc/car/rank_data'self.headers = {'User-Agent': 'Mozilla/5.0 (... Chrome/104.0.0.0 Safari/537.36)'}def get_month_list(self):months = []for year in range(2022, 2023):for month in range(1, 13):months.append(f'{year}{month:02d}')return monthsdef scrape_data_for_month(self, month):params = { 'month': month, 'count': 10000, 'rank_data_type': 11 }page_json = requests.get(self.baseUrl, headers=self.headers, params=params).json()car_list = page_json.get("data", {}).get("list", [])for car in car_list:# 组装品牌/车系/图片/销量/价格/厂商/排名等字段...# 请求详情页,抓取 carModel/energyType/marketTime/insure 等...def clear_csv(self):df = pd.read_csv('./temp.csv')df.dropna(inplace=True)df.drop_duplicates(inplace=True)return df.valuesdef save_to_sql(self):data = self.clear_csv()for car in data:CarInfo.objects.create(brand=car[0], carName=car[1], carImg=car[2], saleVolume=car[3],price=car[4], manufacturer=car[5], rank=car[6], carModel=car[7],energyType=car[8], marketTime=car[9], insure=car[10])if __name__ == '__main__':spider_obj = Spider()spider_obj.init()for month in spider_obj.get_month_list():spider_obj.scrape_data_for_month(month)spider_obj.save_to_sql()

图片下载与本地路径替换(以销量数据为例)在 utils/reade_car_sales_data.py

output_dir = '../media/cars'
os.makedirs(output_dir, exist_ok=True)with open('car_sales_data.json', 'r', encoding='utf-8') as file:response = json.load(file)for item in response.get('data', []):master_pic_url = "https://cdn-fs.touchev.com" + item['masterPic']img_response = requests.get(master_pic_url)if img_response.status_code == 200:img_name = f"{item['seriesName']}.jpg"with open(os.path.join(output_dir, img_name), 'wb') as img_file:img_file.write(img_response.content)# 将 URL 替换为本地可访问路径master_pic_url = f"/media/cars/{img_name}"

后端视图与路由

数据的分页、筛选与可视化入口在 car/views.py。示例:

# 列表与筛选:车辆榜单(按市场时间、能源类型、车型、厂商、车名)
def car_info_list(request):car_info_list = CarInfo.objects.all()market_time = request.GET.get('market_time')energy_type = request.GET.get('energy_type')car_model = request.GET.get('car_model')manufacturer = request.GET.get('manufacturer')car_name = request.GET.get('car_name')if market_time: car_info_list = car_info_list.filter(marketTime=market_time)if energy_type: car_info_list = car_info_list.filter(energyType=energy_type)if car_model: car_info_list = car_info_list.filter(carModel=car_model)if manufacturer: car_info_list = car_info_list.filter(manufacturer=manufacturer)if car_name: car_info_list = car_info_list.filter(carName__icontains=car_name)car_info_list = car_info_list.order_by('-marketTime', 'rank')paginator = Paginator(car_info_list, 10)page_obj = paginator.get_page(request.GET.get('page', 1))return render(request, 'car_info_list.html', { 'page_obj': page_obj, ... })# 可视化数据准备:销量
def car_sales_visualization(request):car_data = Car.objects.all()series_names = [d.seriesName for d in car_data]month_sales = [d.monthSale for d in car_data]year_sales = [d.yearSale for d in car_data]month_bases = []for d in car_data:try:month_bases.append(float(d.monthBasis.rstrip('%')) if d.monthBasis else 0)except ValueError:month_bases.append(0)six_month_sales_list = [[int(s) for s in d.sixMonth.split(',') if s] for d in car_data]return render(request, 'car_sales_visualization.html', {'series_names_json': json.dumps(series_names),'month_sales_json': json.dumps(month_sales),'year_sales_json': json.dumps(year_sales),'month_bases_json': json.dumps(month_bases),'six_month_sales_list_json': json.dumps(six_month_sales_list),})

路由集中在 car/urls.py

urlpatterns = [path("home/", views.home),path("login/", views.login),path("register/", views.register),path("logOut/", views.logOut),path('endurance-list/', views.endurance_list),path('car-list/', views.car_list),path('car-info-list/', views.car_info_list),path('car-data-list/', views.car_data_list),path('endurance-visualization/', views.endurance_visualization),path('car-sales-visualization/', views.car_sales_visualization),path('car-info-visualization/', views.car_info_visualization),path('car-data-visualization/', views.car_data_visualization),path('edit-profile/', views.edit_profile),path('change-password/', views.change_password),
]

前端可视化(ECharts 示例)

以“电动汽车销量分析”页面为例(car/templates/car_sales_visualization.html),从后端注入 JSON,再用 ECharts 渲染:

<!-- 模板中通过后端上下文注入数据 -->
<script>const seriesNames = JSON.parse('{{ series_names_json|safe }}');const monthSales = JSON.parse('{{ month_sales_json|safe }}');const yearSales = JSON.parse('{{ year_sales_json|safe }}');const monthBases = JSON.parse('{{ month_bases_json|safe }}');const sixMonthSalesList = JSON.parse('{{ six_month_sales_list_json|safe }}');const monthChart = echarts.init(document.getElementById('month-sales-chart'));monthChart.setOption({title: { text: '月销量' },tooltip: {},xAxis: { type: 'category', data: seriesNames },yAxis: { type: 'value' },series: [{ type: 'bar', data: monthSales }]});// 其余图表同理...
}</script>

运行与体验

  1. 启动服务后访问:http://127.0.0.1:8000/car/login/

  2. 注册登录后进入系统首页,左侧导航进入:

  • 续航榜单:/car/endurance-list/
  • 车辆数据:/car/car-list/
  • 车辆榜单:/car/car-info-list/
  • 整体数据:/car/car-data-list/
  • 可视化:/car/*-visualization
  1. 头像上传、资料修改与密码修改在“Edit”菜单下。

常见问题 FAQ

  • 静态资源不生效:检查 STATIC_URLSTATICFILES_DIRS,开发环境确保通过模板引用 /static/...
  • 图片 404:确认 MEDIA_URLMEDIA_ROOT 设置,模板中使用 /media/... 路径,Django 开发模式需通过 urlpatterns += static(...) 暴露媒体目录。
  • MySQL 连接失败:检查账号/密码/端口,确保已创建数据库并导入 design_157_car.sql 或执行迁移。
  • pandas/lxml 缺失:pip install pandas lxml,Windows 环境建议提前安装编译依赖或使用预编译轮子。
  • ECharts 无法渲染:确认 <script src="/static/js/echarts.min.js"></script> 已正确引入且容器有宽高。

可视化展示

项目源码获取,码界筑梦坊各平台同名,博客底部含联系方式卡片,欢迎咨询!

基于Python的汽车数据可视化分析系统

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


---## 拓展方向与总结拓展建议:- 增量爬取与定时任务:结合 Celery/Crontab 定时刷新数据;
- 数据质量与异常检测:对销量/价格等关键字段进行阈值校验与异常报警;
- 更丰富的可视化:箱线图、雷达图、桑基图、时序预测;
- 权限与审计:基于 Django 权限体系引入角色与操作审计;
- 前后端分离:将可视化切换为 REST API + 前端框架(Vue/React + ECharts)。至此,一个覆盖“采集—清洗—入库—分析—可视化”的端到端样例已完整跑通,可作为后续课程设计与企业内部数据工具的基础模板。
http://www.dtcms.com/a/340265.html

相关文章:

  • NVIDIA Isaac Sim
  • Ubuntu 主机名:精通配置与管理
  • 全球首款 8K 全景无人机影翎 A1 发布解读:航拍进入“先飞行后取景”时代
  • 从 “模仿” 到 “创造”:AI 大模型的 “思维进化” 背后,技术突破在哪?
  • 沪深股指期货指数「IF000」期货行情怎么看?
  • 利用无事务方式插入数据库解决并发插入问题(最小主键id思路)
  • 海外短剧app、h5、独立站、国内短剧看广告app,短剧小程序、源码交付开发
  • java17学习笔记
  • RK android14 Setting一级菜单IR遥控器无法聚焦问题解决方法
  • VPS海外节点性能监控全攻略:从基础配置到高级优化
  • 02-docker相关知识
  • Java 学习笔记(基础篇6)
  • 29.Linux rsync+inotify解决同步数据实时性
  • 【Tech Arch】Apache HBase分布式 NoSQL 数据库
  • 签名应用APP分发平台的微服务化部署是什么?其有哪些优势?
  • 微服务自动注册到ShenYu网关配置详解
  • mysql数据恢复
  • WT2606B 驱屏语音芯片新增蓝牙功能:功能集成一体化,产品升级自动化,语音交互无线化,场景应用普适化!
  • Java 性能优化实战(二):JVM 调优的 5 个核心维度
  • 2.Shell脚本修炼手册之---创建第一个 Shell 脚本
  • Windows 11 安装 Miniconda + Mamba,配置国内源
  • KV cache
  • java八股文-JVM相关面试题-参考回答
  • 计算机视觉 图片处理 在骨架化过程中,每次迭代都会从图像的边缘移除一层像素,直到只剩下单像素宽度的骨架
  • 机器学习--数据清洗—(续篇)
  • 【论文阅读】Multi-metrics adaptively identifies backdoors in Federated Learning
  • Python文件操作与异常处理详解 :基础方法、注意事项及os模块常用功能
  • day31 SQLITE
  • 百度Q2财报:总营收327亿 AI新业务收入首次超100亿
  • 前端-JavaScript笔记(核心语法)