通过之前的学习,我们已经可以通过各种姿势获取到数据了,但是我们并不能很直观的观察这些数据,这就需要我们通过一些方法实现数据可视化,以达到清晰有效的传达与沟通信息的功能。一些人往往会先下载数据存储下来,再另写代码读取数据以实现数据可视化。本文则借助Scrapy的Pipelines结构,通过实现两个Item下载监控器来展示Scrapy框架的数据可视化实现。
0x00 需求分析
要做数据可视化,我们首先得确认我们要将什么数据进行可视化,然后才能确定用什么方式进行可视化。本节要实现的是对Item下载进行监控,即要直观的看到随时间变化Item下载速度的一个变化趋势。考虑到这个特点,在这里,我采用折线图来绘制图标。Y轴自然是截止到当前时间Item的下载总量,而X轴则是时间的变化。Y轴上的数据绘图工具会自动的帮我们实现,但X轴上的数据是我们自己提供的。所以就要考虑到当运行时间长了,折线点数多了,X轴上的数据就会很多,影响视觉效果,因此还需要以一定的标准对数据进行切片筛选,否则就会出现像下面这样的情况。
0x01 Matplotlib
Matplotlib 是一个 Python 的 2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出具有出版品质级别的图形。在Scrapy中对Item进行监控,我们可以实现一个Pipeline类,在这个类中处理数据并绘图即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import matplotlib.pyplot as pt
class ItemStatisticsMatplotlib(object):
def __init__(self):
self.time = time.time()
self.sum = 0
self.sumlist = [] #每个点的Item数量
self.timecnt = 0
pt.title('Item Download Speed Trend')
pt.xlabel('time(minutes)')
pt.ylabel('Item Sum')
def process_item(self,item,spider):
if time.time()-self.time >= 60:
self.time = time.time()
#pt.cla() #清除当前图像
#print(range(1,self.timecnt+1))
self.timecnt += 1
self.sumlist.append(self.sum)
pt.plot(range(1,self.timecnt+1),self.sumlist,lw=2,label='Item Sum')
#pt.legend() #绘制图例
#pt.show() #显示图像
pt.savefig('trend.png') #保存图像
self.time = time.time()
self.sum += 1
return item
|
0x02 Pyecharts
pyecharts是一款将python与echarts结合的强大的数据可视化工具。matplotlib绘制出的图像是静态图像,但echarts绘制出的却是动态图像。在这里,我们同样以实现一个类的方法进行数据可视化的实现。
PS:根据博主实测发现,pyecharts库更新较快,各种类和方法具有较大改动,安装时建议指定版本号
pip install pyecharts==0.1.9.4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
from pyecharts import Line
class ItemStatisticsEcharts(object):
def __init__(self):
self.time = time.time()
self.sum = 0
self.sumlist = [] #每个点的Item数量
self.timecnt = 0
self.line = None
def process_item(self,item,spider):
if time.time()-self.time >= 60:
self.time = time.time()
self.timecnt += 1
self.sumlist.append(self.sum)
self.line = Line('Item Download Speed Trend') #绘制折线图,参数为标题
if self.timecnt > 20: #当点数超过20个就进行删减
discount = (self.timecnt/20)+1
x = [value for index,value in enumerate(range(1,self.timecnt+1)) if index%discount==0]
y = [value for index,value in enumerate(self.sumlist) if index%discount==0]
else:
x = list(range(1,self.timecnt+1))
y = self.sumlist
self.line.add('Trend',x,y)
#self.line.show_config()
self.line.render('trend.html') #保存图表
self.time = time.time()
self.sum += 1
return item
|