爬虫自学宝典——使用pygal可视化处理

前文回顾

准备条件:使用pygal模块,应该先装pygal包,最简单的方法就是pip了。


win+R——>cmd打开dos窗口,输入:

pip install pygal

等待数据连接后,模块加载成功后,自然会出现successfully字符的。


使用爬虫爬取数据后,前文我们已经介绍了如何将数据信息写入文件和存入数据库,但是这两者都是建立在干巴巴的数据上的操作;那么如何直观的展示这些信息呢?最好的办法就是将这些数据可视化。可视化的思路是什么?将数据先存入文件中,然后将这些数据通过的读的方法进行分类,最后利用pygal处理这些数据。

首先查看我的博客分类栏,其分类如下:
在这里插入图片描述
上述分类得知,总计十一类,所以我们需要新建是一个字典,字典键名为这十一类的名称,字典的键值为发布博客的数量。下面就是我们本次教学的步骤,请仔细阅读。

步骤一:修改spider文件

修改spider文件的目的是让虫子爬取我们想要的信息,修改后的demo_spider.py文件如下:

# -*- coding: utf-8 -*-
import scrapy
from demo.items import DemoItem
class DemoSpiderSpider(scrapy.Spider):
    name = 'demo_spider'
    allowed_domains = ['csdn.net']
    start_urls = ['https://blog.csdn.net/qq_44503987']
    def parse(self, response):
        for info in response.xpath('//div[@class="article-list"]/div[@class="article-item-box csdn-tracking-statistics"]'):
            item = DemoItem()
            item['name'] = info.xpath('./h4/a/text()').extract()[1].strip()#爬取到博客的name信息
            item['read_number'] = info.xpath('./div[@class="info-box d-flex align-content-center"]/p[3]/span/span/text()').extract_first().strip()#爬取到博客的阅读次数
            item['publish_date'] = info.xpath('./div[@class="info-box d-flex align-content-center"]/p[1]/span/text()').extract_first().strip()#爬取博客的发布日期
            yield item

上述去掉了爬取下一页的代码,原因是CSDN博客中,我发的较少,没有翻页按钮。更重要的是,为了防止出现数据错乱。

步骤二:修改pipeline文件

修改pipeline文件的目的是让我们爬取的信息输出到json文件夹中,方便后面的pygal操作。
修改后的pipeline文件如下:

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
import json


class DemoPipeline(object):
    def __init__(self):
        self.filename = open(file="demo2.json", mode="w", encoding='utf-8')
        self.dict_list = []
        # 存储读取的博客信息

    def close_spider(self, spider):
        print('————————————————————关闭我的小虫子——————————————————————')
        json.dump(self.dict_list, self.filename, ensure_ascii=False)
        # 将博客信息列表存入json文件;ensure_ascii=False表示不以ascii形式存储,方便看得懂json文件
        self.filename.close()

    def process_item(self, item, spider):
        p = dict(item)
        # 博客信息集转换成字典,方便存入列表
        self.dict_list.append(p)
        # 将博客信息存入列表

步骤三:运行虫子,查看爬取结果

在dos命令行中,定位到项目目录下,然后输入如下命令:

scrapy crawl demo_spider

运行后查看项目目录,如果成功的话会出现demo2.json文件,如下图:
在这里插入图片描述
打开文件,文件内容如下:
在这里插入图片描述
这证明我们的数据已经爬取结束了,并且成功了。接下来就是利用pygal处理这些数据了,我有两个思路,一个思路是画柱状图,列出每类博客发布数量以及访问量;第二种思路是画一个圆饼图,列出每类博客发布数量所占总博客的比例,还有就是再画一个圆饼图,列出每类博客访问量所占总访问量的比例。


第一种思路:柱状图

思路很简单,将json中的数据导出,然后归类就行了。代码如下:

import json
import re
import pygal

blogs = {'python': [0, 0], 'java': [0, 0], 'http': [0, 0], 'scrapy': [0, 0], '牛客': [0, 0], 'web': [0, 0],
         'html': [0, 0], 'eclipse': [0, 0], 'tomcat': [0, 0], 'mysql': [0, 0], 'xpath': [0, 0], 'other': [0, 0]}
# 创建一个字典,让其key为类型名,value为一个两列列表,第一列表示访发布量,第二列表示访问量
filePath = 'demo2.json'


def classify(string):
    """
    缺陷很大的一个函数,只能进行一次分类,但是有些博客属于多种类型。
    :param string:
    :return:
    """
    if len(re.findall('py', string, flags=re.I)) > 0:
        return 'python'
    elif len(re.findall('java', string, flags=re.I)) > 0:
        return 'java'
    elif len(re.findall('http', string, flags=re.I)) > 0:
        return 'http'
    elif len(re.findall('scrapy', string, flags=re.I)) > 0:
        return 'scrapy'
    elif len(re.findall('牛客', string, flags=re.I)) > 0:
        return '牛客'
    elif len(re.findall('web', string, flags=re.I)) > 0:
        return 'web'
    elif len(re.findall('html', string, flags=re.I)) > 0:
        return 'html'
    elif len(re.findall('eclipse', string, flags=re.I)) > 0:
        return 'eclipse'
    elif len(re.findall('tomcat', string, flags=re.I)) > 0:
        return 'tomcat'
    elif len(re.findall('mysql', string, flags=re.I)) > 0:
        return 'mysql'
    elif len(re.findall('xpath', string, flags=re.I)) > 0:
        return 'xpath'
    else:
        return 'other'


with open(filePath, mode='r', encoding='utf-8') as f:
    file_list = json.load(f)
    for i in file_list:
        p = classify(i['name'])
        blogs[p][0] += 1
        blogs[p][1] += int(i['read_number'])
# json文件的数据进行分类,并记录数据值
blogs_class = list(blogs.keys())  # x轴分类名称
blogs_Number = []  # 博客发布量
blogs_readNumber = []  # 博客阅读量
for i in blogs_class:
    blogs_Number.append(blogs[i][0])
    blogs_readNumber.append(blogs[i][1])

bar = pygal.Bar()
bar.x_labels = blogs_class
bar.add('发布量', blogs_Number)
bar.add('阅读量', blogs_readNumber)
bar.title = '博客发布量分析图'
bar._x_title = "博客类型"
bar._y_title = "数量"
bar.render_to_file('drawing.svg')

运行后,打开文件结果如下:
在这里插入图片描述
所有的的思路都在代码注释中,阅读代码,理清别人的思路也是程序员的必备功课。

第二种思路:圆饼图

除就是了,没有那么难的,代码如下:

import json
import re
import pygal

blogs = {'python': [0, 0], 'java': [0, 0], 'http': [0, 0], 'scrapy': [0, 0], '牛客': [0, 0], 'web': [0, 0],
         'html': [0, 0], 'eclipse': [0, 0], 'tomcat': [0, 0], 'mysql': [0, 0], 'xpath': [0, 0], 'other': [0, 0]}


# 创建一个字典,让其key为类型名,value为一个两列列表,第一列表示访发布量,第二列表示访问量

def classify(string):
    """
    缺陷很大的一个函数,只能进行一次分类,但是有些博客属于多种类型。
    :param string:
    :return:
    """
    if len(re.findall('py', string, flags=re.I)) > 0:
        return 'python'
    elif len(re.findall('java', string, flags=re.I)) > 0:
        return 'java'
    elif len(re.findall('http', string, flags=re.I)) > 0:
        return 'http'
    elif len(re.findall('scrapy', string, flags=re.I)) > 0:
        return 'scrapy'
    elif len(re.findall('牛客', string, flags=re.I)) > 0:
        return '牛客'
    elif len(re.findall('web', string, flags=re.I)) > 0:
        return 'web'
    elif len(re.findall('html', string, flags=re.I)) > 0:
        return 'html'
    elif len(re.findall('eclipse', string, flags=re.I)) > 0:
        return 'eclipse'
    elif len(re.findall('tomcat', string, flags=re.I)) > 0:
        return 'tomcat'
    elif len(re.findall('mysql', string, flags=re.I)) > 0:
        return 'mysql'
    elif len(re.findall('xpath', string, flags=re.I)) > 0:
        return 'xpath'
    else:
        return 'other'


filePath = 'D:\Desktop\scrapyWork\demo\demo2.json'
with open(filePath, mode='r', encoding='utf-8') as f:
    file_list = json.load(f)
    for i in file_list:
        p = classify(i['name'])
        blogs[p][0] += 1
        blogs[p][1] += int(i['read_number'])
# json文件的数据进行分类,并记录数据值
blogs_class = list(blogs.keys())  # x轴分类名称
blogs_Number = []  # 博客发布量
blogs_readNumber = []  # 博客阅读量
for i in blogs_class:
    blogs_Number.append(blogs[i][0])
    blogs_readNumber.append(blogs[i][1])

su = sum(blogs_Number)
for i in range(len(blogs_Number)):
    blogs_Number[i] /= su
    # 计算各类发布量所占的百分比
su = sum(blogs_readNumber)
for i in range(len(blogs_readNumber)):
    blogs_readNumber[i] /= su
    # 计算各类博客阅读量所占百分比
pie = pygal.Pie()
for i, per in enumerate(blogs_Number):
    pie.add(blogs_class[i], per)
pie.title = "博客数据饼状分析图——发布量"
pie.legend_at_bottom = True
pie.inner_radius = 0.4
pie.half_pie = True
# 以半饼显示
pie.render_to_file('test2_half.svg')


pie2 = pygal.Pie()
for i, per in enumerate(blogs_readNumber):
    pie2.add(blogs_class[i], per)
pie2.title = "博客数据饼状分析图——访问量"
pie2.legend_at_bottom = True
pie2.inner_radius = 0.4
# pie2.half_pie = True
pie2.render_to_file('test2_notHalf.svg')

结果如下:
在这里插入图片描述
在这里插入图片描述


总结

这一节就是纯粹的数据可视化处理,但是旁敲侧击,所用的知识挺多的,包括python对json的支持,python的pygal可视化处理,还有很多小知识点的应用。
不过博主强力推荐,大家看看这篇番外博客,因为我在这一方面栽了一下午的跟头:如何给json文件中存入多个字典并读取
不过博主强力推荐,大家看看这篇番外博客,因为我在这一方面栽了一下午的跟头:如何给json文件中存入多个字典并读取
不过博主强力推荐,大家看看这篇番外博客,因为我在这一方面栽了一下午的跟头:如何给json文件中存入多个字典并读取

下一节,我们做一个小demo,给大家讲解怎么爬取高清图片。
欲知后事如何,且听下回分解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值