[毕业设计]2023-2024年最新最全计算机专业毕设选题推荐汇总
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人 。
这款汽车信息网站是基于多项技术和框架设计的全面的汽车信息展示及查询系统。其中,采用了Python Django框架和Scrapy爬虫技术实现数据的抓取和处理,结合MySQL数据库进行数据存储和管理,利用Vue3、Element-Plus、ECharts以及Pinia等前端技术实现了丰富的数据可视化展示和用户交互功能。
(5)后台数据管理
(6)爬虫数据采集页面
可在后台增删改查管理所有数据
使用Django SimpleUI实现管理后台,并且配置相应的权限控制,管理员可以登录后台,对汽车数据和投诉数据进行增删改查和其他操作。
用户登陆注册
(1)后端实现
from django.shortcuts import render
from datetime import datetime, timedelta
from .models import *
from django.http.response import JsonResponse
from itertools import groupby
from .models import *
import json
from django.http.response import HttpResponse
from django.shortcuts import render
from django.http import JsonResponse
from pyecharts import options as opts
from pyecharts.charts import Map, Grid, Bar, Line, Pie, WordCloud, Radar, Timeline
from pyecharts.faker import Faker
from pyecharts.commons.utils import JsCode
from pyecharts.options.charts_options import MapItem
from datetime import datetime, time
from django.core.paginator import Paginator
from django.db.models import Q, F
from pyecharts.globals import SymbolType
from django.db.models import Sum, Count, Max, Min, Avg
from collections import Counter
from requests_html import requests
from itertools import chain
from functools import lru_cache
def to_dict(l, exclude=tuple(), single=False):
# 将数据库模型 变为 字典数据 的工具类函数
def transform(v):
if isinstance(v, datetime):
return v.strftime("%Y-%m-%d %H:%M:%S")
return v
def _todict(obj):
j = {
k: transform(v)
for k, v in obj.__dict__.items()
if not k.startswith("_") and k not in exclude
}
return j
if single:
return _todict(l)
return [_todict(i) for i in l]
def all_grouped_brands(request):
"""
返回按拼音分组的所有品牌的JSON响应。
Args:
request (HttpRequest): HTTP请求对象。
Returns:
JsonResponse: 按拼音分组的所有品牌的JSON响应。
"""
# 获取请求数据
data = request.json
# 获取所有品牌并转换为字典
brands = to_dict(Brand.objects.all().order_by("pinyin", "-on_sale_series_count"))
# 按拼音分组品牌
result = [(i[0], list(i[1])) for i in groupby(brands, key=lambda x: x["pinyin"])]
# 返回JSON响应
return JsonResponse(result, safe=False)
def query_car_series(request):
"""根据请求参数查询车系。
Args:
request (HttpRequest): HTTP请求。
Returns:
JsonResponse: 包含车系的JSON响应。
"""
# 获取请求参数
body = request.json
pagesize = body.get("pagesize", 10)
page = body.get("page", 1)
exclude_fields = ["pagesize", "page", "total", "orderby"]
orderby = body.get("orderby")
# 从请求参数构建查询
query = {k: v for k, v in body.items() if k not in exclude_fields and v}
q = Q(**query)
# 获取车系对象并对结果进行分页
objs = CarSeries.objects.filter(q).order_by(orderby)
paginator = Paginator(objs, pagesize)
# 获取指定页面并将结果转换为字典列表
try:
pg = paginator.page(page)
result = list(pg.object_list)
except Exception as e:
result = []
result = to_dict(result)
# 将结果作为JSON响应返回
return JsonResponse({"total": paginator.count, "records": result})
def lasted_sales_rank_months(request):
months = list(
CarSale.objects.values_list("month", flat=True)
.order_by("-month")
.distinct()[:24]
)
return JsonResponse(months, safe=False)
def lasted_sales_issue_months(request):
months = list(
CarIssue.objects.values_list("stime", flat=True)
.order_by("-stime")
.distinct()[:24]
)
return JsonResponse(months, safe=False)
def car_rank(request):
body = request.json
id = body.get("id")
return _car_rank(id)
@lru_cache()
def _car_rank(id):
# 获取当前日期及1年前的日期
today = datetime.now().date()
one_year_ago = today - timedelta(days=365)
# 设置查询条件
q = Q(month__gte=one_year_ago.strftime("%Y%m"), month__lte=today.strftime("%Y%m"))
result = (
CarSale.objects.filter(q)
.values("series_id", "series_name")
.annotate(total_sales=Sum("rank_value"))
.filter(total_sales__gt=0)
.order_by("-total_sales")
)
sales_rank = next(
(
i
for i, e in enumerate(
result,
start=1,
)
if e["series_id"] == int(id)
),
-1,
)
# ---------
# 获取当前日期及1年前的日期
q = Q(
stime__gte=one_year_ago.strftime("%Y-%m-%d"),
stime__lte=today.strftime("%Y-%m-%d"),
)
result = (
CarIssue.objects.filter(q)
.values("series_id", "series_name")
.annotate(total_issues=Sum("count"))
.filter(total_issues__gt=0)
.order_by("-total_issues")
)
issue_rank = next(
(
i
for i, e in enumerate(
result,
start=1,
)
if e["series_id"] == int(id)
),
-1,
)
return JsonResponse(dict(sales_rank=sales_rank, issue_rank=issue_rank))
def car_sales_rank(request):
# 获取请求体中的数据
body = request.json
# 获取请求体中的月份
month = body.get("month")
# 定义查询条件
q = Q()
# 根据月份设置查询条件
if month == "1y":
# 获取当前日期及1年前的日期
today = datetime.now().date()
one_year_ago = today - timedelta(days=365)
# 设置查询条件
q &= Q(
month__gte=one_year_ago.strftime("%Y%m"), month__lte=today.strftime("%Y%m")
)
elif month == "6m":
# 近半年,即6个月
today = datetime.now().date()
half_year_ago = today - timedelta(days=365 // 2)
# 设置查询条件
q &= Q(
month__gte=half_year_ago.strftime("%Y%m"), month__lte=today.strftime("%Y%m")
)
else:
q &= Q(month=month)
# 统计各个车系一年内的总销量,并按照销量进行排序和排名
result = (
CarSale.objects.filter(q)
.values("series_id", "series_name")
.annotate(total_sales=Sum("rank_value"))
.order_by("-total_sales")
)
# 对结果进行排名
result_list = list(result)
for i, item in enumerate(result_list):
item["sales_rank"] = i + 1
# 分页处理数据
pagesize = body.get("pagesize", 20)
page_num = body.get("page", 1)
paginator = Paginator(result_list, pagesize) # 创建Paginator对象
page = paginator.get_page(page_num) # 获取指定页码的数据
result = list(page.object_list)
# 获取每个车系的详细信息,并将其添加到结果中
for i in result:
car_series = to_dict([CarSeries.objects.get(series_id=i["series_id"])])[0]
i.update(**car_series)
# 返回分页后的结果
return JsonResponse({"total": paginator.count, "records": result})
def car_issue_rank(request):
body = request.json
stime = body.get("stime")
type = body.get("type")
q = Q()
if stime == "1y":
# 获取当前日期及1年前的日期
today = datetime.now().date()
one_year_ago = today - timedelta(days=365)
q &= Q(
stime__gte=one_year_ago.strftime("%Y-%m-%d"),
stime__lte=today.strftime("%Y-%m-%d"),
)
elif stime == "6m":
# 近半年,即6个月
today = datetime.now().date()
half_year_ago = today - timedelta(days=365 // 2)
q &= Q(
stime__gte=half_year_ago.strftime("%Y-%m-%d"),
stime__lte=today.strftime("%Y-%m-%d"),
)
else:
q &= Q(stime=stime)
if type:
q &= Q(type=type)
# 统计各个车系一年内的总问题数,并按照问题数进行排序和排名
result = (
CarIssue.objects.filter(q)
.values("series_id", "series_name")
.annotate(total_issues=Sum("count"))
.order_by("-total_issues")
)
# 对结果进行排名
result_list = list(result)
for i, item in enumerate(result_list):
item["issues_rank"] = i + 1
# 分页处理数据
pagesize = body.get("pagesize", 20)
page_num = body.get("page", 1)
paginator = Paginator(result_list, pagesize) # 创建Paginator对象
page = paginator.get_page(page_num) # 获取指定页码的数据
result = list(page.object_list)
for i in result:
car_series = to_dict([CarSeries.objects.get(series_id=i["series_id"])])[0]
counter = Counter()
for x in CarIssue.objects.filter(q, series_id=i["series_id"]).values_list(
"dxwt", flat=True
):
counter.update(dict([(j["ctiTitle"], j["count"]) for j in x]))
i["issues"] = counter.most_common(10)
i.update(**car_series)
return JsonResponse({"total": paginator.count, "records": result})
def get_detail(request):
body = request.json
id = body.get("id")
o = CarSeries.objects.get(pk=id)
o = to_dict(o, single=True)
o["brand"] = to_dict(Brand.objects.get(brand_id=o["brand_id"]), single=True)
return JsonResponse(o)
def car_360_color_pic(request):
body = request.json
id = body.get("id")
try:
color_pic_list = requests.get(
f"https://www.dongchedi.com/motor/pc/car/series/car_360_color_pic?aid=1839&app_name=auto_web_pc&series_id={id}"
).json()["data"]["color_pic_list"]
except:
color_pic_list = []
return JsonResponse(color_pic_list, safe=False)
def radar_chart(request):
body = request.json
id = body.get("id")
# 从数据库中读取评分数据
car_series = CarSeries.objects.get(series_id=id)
color = "#f4cf63"
# 转换数据范围
min_score = 1
max_score = 500
scale = 5
comfort_score = car_series.comfort_score / max_score * scale
appearance_score = car_series.appearance_score / max_score * scale
configuration_score = car_series.configuration_score / max_score * scale
control_score = car_series.control_score / max_score * scale
power_score = car_series.power_score / max_score * scale
space_score = car_series.space_score / max_score * scale
interiors_score = car_series.interiors_score / max_score * scale
total_score = round(car_series.total_score / max_score * scale, 2)
# 创建雷达图对象并添加数据
radar_chart = (
Radar()
.add_schema(
schema=[
opts.RadarIndicatorItem(name="舒适性", max_=scale),
opts.RadarIndicatorItem(name="外观", max_=scale),
opts.RadarIndicatorItem(name="配置", max_=scale),
opts.RadarIndicatorItem(name="控制", max_=scale),
opts.RadarIndicatorItem(name="动力", max_=scale),
opts.RadarIndicatorItem(name="空间", max_=scale),
opts.RadarIndicatorItem(name="内饰", max_=scale),
]
)
.add(
series_name=car_series.series_name,
data=[
[
round(i, 1)
for i in [
comfort_score,
appearance_score,
configuration_score,
control_score,
power_score,
space_score,
interiors_score,
]
]
],
areastyle_opts=opts.AreaStyleOpts(opacity=0.9, color=color),
linestyle_opts=opts.LineStyleOpts(color=color),
label_opts=opts.LabelOpts(position="outside", is_show=total_score != 0),
symbol=None,
color="#000",
)
.set_global_opts(
title_opts=opts.TitleOpts(
title=f"{total_score or '暂无评分'}",
pos_bottom="45%",
pos_left="center",
title_textstyle_opts=opts.TextStyleOpts(
color="#000", font_size=30, align="center"
),
),
legend_opts=opts.LegendOpts(is_show=False),
)
)
# 生成 HTML 代码并返回到前端
return HttpResponse(radar_chart.dump_options(), content_type="aplication/json")
def series_sales_trend(request):
body = request.json
id = body.get("id")
# 查询指定车系的月度销量数据
sales = list(CarSale.objects.filter(series_id=id).order_by("-month")[:12])[::-1]
months = [sale.month for sale in sales]
sales_values = [sale.rank_value for sale in sales]
if not sales_values:
return JsonResponse({})
try:
max_ = max(sales_values)
except:
max_ = 0
# 创建一个 Line 图表对象
line_chart = Line()
# 添加 x 轴和 y 轴数据
line_chart.add_xaxis(months)
line_chart.add_yaxis(
"",
sales_values,
symbol="circle",
symbol_size=8,
itemstyle_opts=opts.ItemStyleOpts(color="#ff7f50"),
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值"),
]
),
)
# 设置全局配置项
line_chart.set_global_opts(
title_opts=opts.TitleOpts(title="销量走势图", pos_bottom=0, pos_left="center"),
xaxis_opts=opts.AxisOpts(
name="月份",
axispointer_opts=opts.AxisPointerOpts(is_show=True),
),
yaxis_opts=opts.AxisOpts(
name="销量",
axislabel_opts=opts.LabelOpts(formatter="{value} 辆"),
),
legend_opts=opts.LegendOpts(is_show=False),
visualmap_opts=opts.VisualMapOpts(max_=max_),
)
# 设置序列配置项
line_chart.set_series_opts(
areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
linestyle_opts=opts.LineStyleOpts(width=3),
label_opts=opts.LabelOpts(is_show=False),
)
# 生成 HTML 代码并返回到前端
return HttpResponse(line_chart.dump_options(), content_type="aplication/json")
def series_issue_trend(request):
body = request.json
id = body.get("id")
# 查询指定车系的月度销量数据
months = list(
CarIssue.objects.filter(series_id=id, type=1)
.values_list("stime", flat=True)
.order_by("-stime")[:12]
)[::-1]
months = [i[:-3].replace("-", "") for i in months]
if not months:
return JsonResponse({})
# 创建一个 Line 图表对象
line_chart = Line()
# 添加 x 轴和 y 轴数据
line_chart.add_xaxis(months)
for type, name in [(1, "质量问题"), (2, "服务问题"), (3, "其他问题")]:
counts = list(
CarIssue.objects.filter(series_id=id, type=type)
.values_list("count", flat=True)
.order_by("-stime")[:12]
)[::-1]
line_chart.add_yaxis(
name,
counts,
symbol="circle",
symbol_size=8,
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值"),
]
),
)
# 设置全局配置项
line_chart.set_global_opts(
title_opts=opts.TitleOpts(title="投诉量走势图", pos_bottom=0, pos_left="center"),
xaxis_opts=opts.AxisOpts(
name="月份",
axispointer_opts=opts.AxisPointerOpts(is_show=True),
),
yaxis_opts=opts.AxisOpts(
name="投诉量",
axislabel_opts=opts.LabelOpts(formatter="{value}"),
),
legend_opts=opts.LegendOpts(is_show=True, selected_map={"其他问题": False}),
)
# 设置序列配置项
line_chart.set_series_opts(
areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
linestyle_opts=opts.LineStyleOpts(width=3),
label_opts=opts.LabelOpts(is_show=False),
)
# 生成 HTML 代码并返回到前端
return HttpResponse(line_chart.dump_options(), content_type="aplication/json")
def series_sales_rank_trend(request):
body = request.json
id = body.get("id")
# 查询指定车系的月度销量数据
sales = list(CarSale.objects.filter(series_id=id).order_by("-month")[:12])[::-1]
months = [sale.month for sale in sales]
rank_values = [sale.rank for sale in sales]
if not rank_values:
return JsonResponse({})
# 创建一个 Line 图表对象
line_chart = Line()
# 添加 x 轴和 y 轴数据
line_chart.add_xaxis(months)
line_chart.add_yaxis(
"",
rank_values,
symbol="circle",
symbol_size=8,
itemstyle_opts=opts.ItemStyleOpts(color="#ff7f50"),
)
# 设置全局配置项
line_chart.set_global_opts(
title_opts=opts.TitleOpts(title="销量排名走势图", pos_bottom=0, pos_left="center"),
xaxis_opts=opts.AxisOpts(
name="月份",
axispointer_opts=opts.AxisPointerOpts(is_show=True),
),
yaxis_opts=opts.AxisOpts(
name="销量排名",
axislabel_opts=opts.LabelOpts(formatter="第 {value} 名"),
min_=1,
is_inverse=True,
),
legend_opts=opts.LegendOpts(is_show=False),
)
# 设置序列配置项
line_chart.set_series_opts(
linestyle_opts=opts.LineStyleOpts(width=3),
label_opts=opts.LabelOpts(is_show=True),
)
# 生成 HTML 代码并返回到前端
return HttpResponse(line_chart.dump_options(), content_type="aplication/json")
def issue_timeline_wordcloud(request):
body = request.json
id = body.get("id")
months = list(
CarIssue.objects.filter(series_id=id, type=1)
.values_list("stime", flat=True)
.order_by("-stime")[:12]
)[::-1]
months = [i for i in months] # i[:-3].replace("-", "")
if not months:
return JsonResponse({})
timeline = Timeline().add_schema(is_auto_play=True)
for month in months:
# 创建词云图对象
wordcloud_chart = WordCloud()
for type, name in [(1, "质量问题")]:
dxwt = (
CarIssue.objects.filter(series_id=id, type=type, stime=month)
.values_list("dxwt", flat=True)
.order_by("-stime")
.first()
)
words = [(i["ctiTitle"], i["count"]) for i in dxwt]
# 添加数据并设置全局配置项
wordcloud_chart.add(
name,
words,
shape="diamond",
)
wordcloud_chart.set_global_opts(
title_opts=opts.TitleOpts(title="质量问题词云图", pos_left="center", pos_top=0),
legend_opts=opts.LegendOpts(is_show=False),
)
timeline.add(wordcloud_chart, month)
return HttpResponse(timeline.dump_options(), content_type="aplication/json")
def issue_labels(request):
body = request.json
id = body.get("id")
dxwt = list((CarIssue.objects.filter(series_id=id).values_list("dxwt", flat=True)))
# print(dxwt)
wt = dict()
for i in chain(*dxwt):
if i["ctiChildId"] in wt:
wt[i["ctiChildId"]]["count"] += i["count"]
else:
wt[i["ctiChildId"]] = i
wt = sorted(list(wt.values()), key=lambda x: x["count"], reverse=True)
return JsonResponse(wt, safe=False)
def series_price_diff_bar(request):
# 获取dealer_low_price和official_low_price之间的差值并按total_score倒序排序
price_diffs = (
CarSeries.objects.filter(has_dealer_price=True, has_official_price=True)
.annotate(
price_diff=F("official_low_price") - F("dealer_low_price"),
)
.values_list("series_name", "price_diff")
.order_by("-price_diff")
)
# 取前20个数据进行可视化分析
price_diffs = price_diffs[:100][::-1]
# price_diffs.sort(key=lambda x: x[1], reverse=True)
# 获取车系名称列表和差值列表
series_names = [i[0] for i in price_diffs]
price_diff_values = [round(i[1]) for i in price_diffs]
# 创建柱状图对象并添加数据
bar = (
Bar()
.add_xaxis(series_names)
.add_yaxis(
"官方价与经销商报价的差值",
price_diff_values,
label_opts=opts.LabelOpts(formatter="{b}"),
)
.reversal_axis()
.set_global_opts(
title_opts=opts.TitleOpts(title="车系降价排行榜可视化", pos_left="center", pos_top=0),
legend_opts=opts.LegendOpts(is_show=False),
datazoom_opts=opts.DataZoomOpts(
orient="vertical",
range_start=80,
range_end=100,
),
xaxis_opts=opts.AxisOpts(name="差价(万元)"),
yaxis_opts=opts.AxisOpts(
name="官方价与经销商报价的差值",
axispointer_opts=opts.AxisPointerOpts(is_show=True, type_="shadow"),
),
tooltip_opts=opts.TooltipOpts(formatter="{b} : 降{c}万"),
)
)
return HttpResponse(bar.dump_options(), content_type="aplication/json")
def brand_distribution(request):
data = (
CarSeries.objects.values("brand_name")
.annotate(total=Count("brand_id"))
.order_by("-total")
)[:30]
brands = [x["brand_name"] for x in data]
counts = [x["total"] for x in data]
chart = (
Pie()
.add(
"",
list(zip(brands, counts)),
label_opts=opts.LabelOpts(formatter="{b}: {d}%"),
radius=["40%", "75%"],
)
.set_global_opts(
title_opts=opts.TitleOpts(
title="汽车品牌数量TOP分布图", pos_left="center", pos_top=0
),
legend_opts=opts.LegendOpts(type_="scroll", pos_left=0, orient="vertical"),
)
)
return HttpResponse(chart.dump_options(), content_type="aplication/json")
def car_series_analysis(request):
low_price_data = {}
for i in range(7):
low_price_data[str(i)] = 0
for car_series in CarSeries.objects.all():
if car_series.dealer_low_price is not None:
if car_series.dealer_low_price < 10:
low_price_data["0"] += 1
elif car_series.dealer_low_price < 15:
low_price_data["1"] += 1
elif car_series.dealer_low_price < 20:
low_price_data["2"] += 1
elif car_series.dealer_low_price < 25:
low_price_data["3"] += 1
elif car_series.dealer_low_price < 30:
low_price_data["4"] += 1
elif car_series.dealer_low_price < 40:
low_price_data["5"] += 1
else:
low_price_data["6"] += 1
bar = (
Bar()
.add_xaxis(["0-10万", "10-15万", "15-20万", "20-25万", "25-30万", "30-40万", "50万以上"])
.add_yaxis(
"车系数量",
[
low_price_data["0"],
low_price_data["1"],
low_price_data["2"],
low_price_data["3"],
low_price_data["4"],
low_price_data["5"],
low_price_data["6"],
],
bar_width=50,
)
.set_global_opts(
title_opts=opts.TitleOpts(title="价格范围数量分布图", pos_left="center", pos_top=0),
legend_opts=opts.LegendOpts(is_show=False),
xaxis_opts=opts.AxisOpts(
name="价格范围",
axispointer_opts=opts.AxisPointerOpts(is_show=True, type_="shadow"),
),
yaxis_opts=opts.AxisOpts(name="车系数量"),
)
)
return HttpResponse(bar.dump_options(), content_type="aplication/json")
由于篇幅限制,获取完整文章或源码、代做项目的,查看主页【专栏名称】或者【用户名】或者顶部的【选题链接】就可以找到我获取项目源码学习啦~
大家点赞、收藏、关注、评论啦 !