重点不在可视化,而再数据处理!!!
这几个月一直忙着写自己的博客系统(首先分享一下博客链接,博客链接:http://www.lll.plus/),零零散散写写了将近两个月左右吧,我记得5月份自己初步设计了网页的基本样式,5月底大概写入30%左右,然后后来因为学校的作业,活动啥的,搁置了一段时间,拖着拖着考试周又快到了,所以后来一个月基本上写了10%左右吧,然后今天一整天都在写后台的数据处理,主要是将请求的记录进行可视化,前端的代码很简单,直接用的是pyecharts官方的模板,效果图如下:
代码如下:
#可视化
# 记录 登录页面 注册页面 错误页面 学习星球页面 快乐星球页面 博客编辑页面 搜索功能 个人中心页面 首页 的请求
def draw(xList, dataDic, timeList,filename='demo.html',series_name='年访问量'):
total_data = {}
titleList = [
'首页页面',
'学习星球',
'快乐星球',
'搜索功能',
'个人中心',
'博客编辑',
'登录页面',
'注册页面',
'错误页面',
]
keyList = [
'dataIndex',
'dataLearning',
'dataPlaying',
'dataSearch',
'dataCenter',
'dataModify',
'dataLogin',
'dataRegister',
'dataError',
]
data_login = dataDic[0] # 登录页面
data_register = dataDic[1] # 注册页面
data_error = dataDic[2] # 错误页面
data_learning = dataDic[3] # 学习星球页面
data_playing = dataDic[4] # 快乐星球页面
data_modify = dataDic[5] # 博客编辑页面
data_search = dataDic[6] # 搜索功能
data_center = dataDic[7] # 个人中心页面
data_index = dataDic[8] # 首页页面
def format_data(data: dict) -> dict:
for year in timeList:
max_data, sum_data = 0, 0
temp = data[year]
max_data = max(temp)
for i in range(len(temp)):
sum_data += temp[i]
data[year][i] = {"name": xList[i], "value": temp[i]}
data[str(year) + "max"] = int(max_data / 100) * 100
data[str(year) + "sum"] = sum_data
return data
total_data['dataLogin'] = format_data(data=data_login) # 登录
total_data['dataRegister'] = format_data(data=data_register) # 注册
total_data['dataError'] = format_data(data=data_error) # 错误
total_data['dataLearning'] = format_data(data=data_learning) # 学习
total_data['dataPlaying'] = format_data(data=data_playing) # 快乐
total_data['dataModify'] = format_data(data=data_modify) # 编辑
total_data['dataSearch'] = format_data(data=data_search) # 搜索
total_data['dataCenter'] = format_data(data=data_center) # 中心
total_data['dataIndex'] = format_data(data=data_index) # 首页
#####################################################################################
# 2012 - 2021 年的数据
def get_year_overlap_chart(year: int) -> Bar:
bar = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))
.add_xaxis(xaxis_data=xList)
.add_yaxis(
titleList[0], # 首页
total_data[keyList[0]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[1], # 学习星球
total_data[keyList[1]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[2], # 快乐星球
total_data[keyList[2]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[3], # 搜索功能
total_data[keyList[3]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[4], # 个人中心
total_data[keyList[4]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[5], # 博客编辑
total_data[keyList[5]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[6], # 登录页面
total_data[keyList[6]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.add_yaxis(
titleList[7], # 注册页面
total_data[keyList[7]][year],
label_opts=opts.LabelOpts(is_show=False),
).add_yaxis(
titleList[8], # 错误页面
total_data[keyList[8]][year],
label_opts=opts.LabelOpts(is_show=False),
)
.set_global_opts(
title_opts=opts.TitleOpts(
title="{}各页面访问量统计".format(year), subtitle="数据来自后台统计"
),
toolbox_opts=opts.ToolboxOpts(is_show=True), # 添加toolbox选项,toolbox中提供了一些对图片的操作工具
tooltip_opts=opts.TooltipOpts(is_show=True, trigger="axis", axis_pointer_type="shadow"),
datazoom_opts=opts.DataZoomOpts(type_="inside"),
legend_opts=opts.LegendOpts( pos_top="10%"),
)
)
pie = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK))
.add(
series_name=series_name,
data_pair=[
[titleList[0], total_data[keyList[0]]["{}sum".format(year)]],
[titleList[1], total_data[keyList[1]]["{}sum".format(year)]],
[titleList[2], total_data[keyList[2]]["{}sum".format(year)]],
[titleList[3], total_data[keyList[3]]["{}sum".format(year)]],
[titleList[4], total_data[keyList[4]]["{}sum".format(year)]],
[titleList[5], total_data[keyList[5]]["{}sum".format(year)]],
[titleList[6], total_data[keyList[6]]["{}sum".format(year)]],
[titleList[7], total_data[keyList[7]]["{}sum".format(year)]],
[titleList[8], total_data[keyList[8]]["{}sum".format(year)]],
],
center=["75%", "35%"],
radius="28%",
)
.set_series_opts(tooltip_opts=opts.TooltipOpts(is_show=True, trigger="item"))
)
return bar.overlap(pie)
# 生成时间轴的图
timeline = Timeline(init_opts=opts.InitOpts(width="1600px", height="800px"))
for time in timeList:
timeline.add(get_year_overlap_chart(year=time), time_point=str(time))
# 1.0.0 版本的 add_schema 暂时没有补上 return self 所以只能这么写着
timeline.add_schema(is_auto_play=True, play_interval=1000)
return timeline.render(filename)
主要的绘图代码是官方的,我只是将示例数据改成了我自己的数据,所以这一修改基本上没有什么难度,大概1个小时就搞定了.
接着就是后台数据的统计和整理了,首先贴代码:
# 后台数据的统计
def statisticData(whichOne=2):
nowyear = datetime.now().year
nowmonth = datetime.now().month
month_list = [
'一月',
'二月',
'三月',
'四月',
'五月',
'六月',
'七月',
'八月',
'九月',
'十月',
'十一月',
'十二月'
] # 横坐标的值
year_list = [year for year in range(nowyear - 9, nowyear + 1)] # 从现在开始前退10年
x_list = ['day' + i for i in getMothDate(nowyear, nowmonth)] # x的坐标改为日期
requestObjs = RequestLogTable.objects.all()
if whichOne == 2:
data_login = {} # 登录页面 数据里面的时间key要与timeline的同步
data_register = {} # 注册页面
data_error = {} # 错误页面
data_learning = {} # 学习星球页面
data_playing = {} # 快乐星球页面
data_modify = {} # 博客编辑页面
data_search = {} # 搜索功能
data_center = {} # 个人中心页面
data_index = {} # 首页页面
for year in range(nowyear - 9, nowyear + 1):
data_login[year] = [0 for i in range(12)]
data_register[year] = [0 for i in range(12)]
data_error[year] = [0 for i in range(12)]
data_learning[year] = [0 for i in range(12)]
data_playing[year] = [0 for i in range(12)]
data_modify[year] = [0 for i in range(12)]
data_search[year] = [0 for i in range(12)]
data_center[year] = [0 for i in range(12)]
data_index[year] = [0 for i in range(12)]
for requestObj in requestObjs:
rPath = requestObj.requestPath
ryear = requestObj.requestTime.year
rmonth = requestObj.requestTime.month
if rPath == '/':
data_index[ryear][rmonth - 1] += 1
elif search(r'login', rPath):
data_login[ryear][rmonth - 1] += 1
elif search(r'register', rPath):
data_register[ryear][rmonth - 1] += 1
elif search(r'error', rPath):
data_error[ryear][rmonth - 1] += 1
elif search(r'learningPlanet', rPath):
data_learning[ryear][rmonth - 1] += 1
elif search(r'playingPlanet', rPath):
data_playing[ryear][rmonth - 1] += 1
elif search(r'modifyBlog', rPath):
data_modify[ryear][rmonth - 1] += 1
elif search(r'search', rPath):
data_search[ryear][rmonth - 1] += 1
elif search(r'personalCenter', rPath):
data_center[ryear][rmonth - 1] += 1
dataDic = [
data_login,
data_register,
data_error,
data_learning,
data_playing,
data_modify,
data_search,
data_center,
data_index
]
draw(xList=month_list, dataDic=dataDic, timeList=year_list, filename='demo2.html', series_name='年访问量')
else:
data_login2 = {} # 登录页面 数据里面的时间key要与timeline的同步
data_register2 = {} # 注册页面
data_error2 = {} # 错误页面
data_learning2 = {} # 学习星球页面
data_playing2 = {} # 快乐星球页面
data_modify2 = {} # 博客编辑页面
data_search2 = {} # 搜索功能
data_center2 = {} # 个人中心页面
data_index2 = {} # 首页页面
for month in month_list:
data_login2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_register2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_error2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_learning2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_playing2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_modify2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_search2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_center2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
data_index2[month] = [0 for i in getMothDate(nowyear, nowmonth)]
for requestObj in requestObjs:
rPath = requestObj.requestPath
ryear = requestObj.requestTime.year
rmonth = requestObj.requestTime.month
rday = requestObj.requestTime.day
if str(ryear) == str(nowyear): # 统计当年的数据
if rPath == '/':
data_index2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'login', rPath):
data_login2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'register', rPath):
data_register2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'error', rPath):
data_error2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'learningPlanet', rPath):
data_learning2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'playingPlanet', rPath):
data_playing2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'modifyBlog', rPath):
data_modify2[month_list[rmonth - 1]][rday - 1] += 1
elif search(r'personalCenter', rPath):
data_center2[month_list[rmonth - 1]][rday - 1] += 1
# 月数据
dataDic2 = [
data_login2,
data_register2,
data_error2,
data_learning2,
data_playing2,
data_modify2,
data_search2,
data_center2,
data_index2
]
draw(xList=x_list, dataDic=dataDic2, timeList=month_list, filename='demo1.html', series_name='月访问量')
# 返回可视化的代码
def returnPicture(request):
if request.method == 'POST':
whichOne = request.POST.get('whichOne') # 1代表月数据 2代表年数据
statisticData(int(whichOne)) # 绘图
with open(f'demo{whichOne}.html', 'r', encoding='utf8') as f:
content = f.read().replace(
'<script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>', '')
div = search(r'<div.*div>', content).group().replace('width:1600px; height:800px',
'width:908px; height:600px')
script = sub(
r'(<div.*div>)|</script>|<script>|<!DOCTYPE html>|<html>|<head>|<meta charset="UTF-8">|<title>Awesome-pyecharts</title>|</head>|<body>|</body>|</html>',
'', content)
with open(f'static/js/demo{whichOne}.js', 'w+', encoding='utf8') as f:
f.write(script)
return JsonResponse({'div': div}) # ,'script':script
return JsonResponse({'msg': '数据请求失败!'})
总共两个函数,一个用于统计,一个用于将统计的数据传给前端,用于统计的函数分别统计了从当前年份开始一直到前10年的(虽然我这个博客系统才刚刚运行了1个多月,但我早就为它永久运行下去做好了打算哈哈哈)每一年的每一个月的各个页面的访问量以及当前年份的每一个月的每一天的访问量,听着就拗口,但是,在Python面前,在难的数据处理,只是需要时间罢了,很快呀~花了我大概半天的时间终于把它写出来了,然后连接到数据,把数据库中的所有数据拿来测试(不是绘图测试),看了测试的结果,自己也拿着笔对着数据库中的数据算了算,好像是对的,于是就把数据放到绘图的函数中进行绘图,很快呀!还没一眨眼的功夫,一大段一大段的红色日志就出现在终端了,点开下面的最后一个报错记录,跳转到对应的报错地方,居然是报错在我的数据源!!!于是我再仔细的检查了一下我的数据,将它打印在终端,和我的测试数据进行比较,咦,数据结构没有问题呀???
闲话少说,直接将问题所在的地方!
很明显的可以看出来,我的这个代码写的非常的"累赘",比如这一段:
这段代码的目的是给初始的几个列表赋0值,其实循环里面并不需要把所有的列表都写在里面,里面只用写一个列表,然后循环结束后,将该列表的值赋给其他列表就可以,因为这几个列表的结构都是一模一样的,我一开始就是这么想的,但是问题就是出在这里(当我分别给各自列表赋初值,也就是把所有列表都写在这个循环中的时候,一段优美的英文打在了终端,
彼时的我有种说不出的无奈和欣慰,调试了好几个小时,终于调试出来了
不知道是不是因为这些列表的地址都是一样引起的问题),虽然我现在也还没搞明白出现的原因,但是我知道这么让它不出bug了!!!
总结一下:
写bug好简单,调试bug好难。
分享一下自己的博客链接,有兴趣的小伙伴可以一起学习呀!
博客链接:http://www.lll.plus/
博客链接:http://www.lll.plus/
博客链接:http://www.lll.plus/