• 豆瓣图书评分数据的可视化分析


    亿牛云代理.jpg

    导语

    豆瓣是一个提供图书、电影、音乐等文化产品的社区平台,用户可以在上面发表自己的评价和评论,形成一个丰富的文化数据库。本文将介绍如何使用爬虫技术获取豆瓣图书的评分数据,并进行可视化分析,探索不同类型、不同年代、不同地区的图书的评分特征和规律。

    概述

    本文的主要步骤如下:

    • 使用scrapy框架编写爬虫程序,从豆瓣图书网站抓取图书的基本信息和评分数据,保存为csv格式的文件。
    • 使用亿牛云爬虫代理服务,提高爬虫效率和稳定性,避免被豆瓣网站屏蔽或封禁。
    • 使用pandas库对爬取的数据进行清洗和处理,提取出需要的字段和特征。
    • 使用matplotlib库对处理后的数据进行可视化分析,绘制各种类型的图表,展示不同维度的评分分布和关系。

    正文

    爬虫程序

    首先,我们需要编写一个爬虫程序,从豆瓣图书网站抓取图书的基本信息和评分数据。我们使用scrapy框架来实现这个功能,scrapy是一个强大而灵活的爬虫框架,可以方便地定义爬虫规则和处理数据。我们需要定义一个Spider类,继承自scrapy.Spider类,并重写以下方法:

    • start_requests:该方法返回一个可迭代对象,包含了爬虫开始时要访问的请求对象。我们可以从豆瓣图书首页开始,获取所有分类的链接,并构造请求对象。
    • parse:该方法负责处理start_requests返回的请求对象的响应,并解析出需要的数据或者进一步的请求。我们可以使用scrapy自带的选择器或者BeautifulSoup等第三方库来解析HTML文档,提取出图书列表页的链接,并构造请求对象。
    • parse_book:该方法负责处理parse返回的请求对象的响应,并解析出图书详情页的数据。我们可以使用同样的方式来提取出图书的基本信息和评分数据,并将其保存为字典格式。
    • close:该方法在爬虫结束时被调用,我们可以在这里将抓取到的数据保存为csv格式的文件。

    为了提高爬虫效率和稳定性,我们还需要使用亿牛云爬虫代理服务,该服务提供了大量高质量的代理IP地址,可以帮助我们避免被豆瓣网站屏蔽或封禁。我们只需要在settings.py文件中设置代理服务器的域名、端口、用户名和密码,以及启用中间件HttpProxyMiddleware即可。

    首先配置爬虫代理,你可以按照以下步骤在Scrapy项目的settings.py文件中进行配置:
    确保已经安装了Scrapy以及相关依赖。然后,打开你的Scrapy项目的settings.py文件,并添加以下配置:

    # 启用HttpProxyMiddleware中间件
    DOWNLOADER_MIDDLEWARES = {
        'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,
    }
    
    # 设置亿牛云 爬虫代理服务器的配置
    HTTPPROXY_AUTH_ENCODING = 'utf-8'  # 编码格式
    
    # 亿牛云 爬虫代理服务器的域名、端口、用户名和密码
    HTTPPROXY_HOST = 'www.16yun.cn'
    HTTPPROXY_PORT = 12345
    HTTPPROXY_USER = '16YUN'
    HTTPPROXY_PASS = '16IP'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    以下是爬虫程序的代码:

    # -*- coding: utf-8 -*-
    import scrapy
    import csv
    
    class DoubanSpider(scrapy.Spider):
        name = 'douban'
        allowed_domains = ['book.douban.com']
        start_urls = ['https://book.douban.com/']
    
        # 定义保存数据的列表
        data = []
    
        def start_requests(self):
            # 从豆瓣图书首页开始
            yield scrapy.Request(url=self.start_urls[0], callback=self.parse)
    
        def parse(self, response):
            # 解析首页,获取所有分类的链接
            categories = response.xpath('//div[@class="article"]/div[@class="indent"]/table//a')
            for category in categories:
                # 构造分类页面的请求对象
                url = category.xpath('./@href').get()
                yield scrapy.Request(url=url, callback=self.parse_book)
    
        def parse_book(self, response):
            # 解析分类页面,获取图书列表
            books = response.xpath('//li[@class="subject-item"]')
            for book in books:
                # 构造图书详情页的请求对象
                url = book.xpath('./div[@class="info"]/h2/a/@href').get()
                yield scrapy.Request(url=url, callback=self.parse_detail)
    
            # 获取下一页的链接,如果存在则继续爬取
            next_page = response.xpath('//span[@class="next"]/a/@href')
            if next_page:
                url = next_page.get()
                yield scrapy.Request(url=url, callback=self.parse_book)
    
        def parse_detail(self, response):
            # 解析图书详情页,获取图书的基本信息和评分数据
            item = {}
            item['title'] = response.xpath('//h1/span/text()').get() # 标题
            item['author'] = response.xpath('//span[contains(text(),"作者")]/following-sibling::a/text()').get() # 作者
            item['publisher'] = response.xpath('//span[contains(text(),"出版社")]/following-sibling::text()').get() # 出版社
            item['pub_date'] = response.xpath('//span[contains(text(),"出版年")]/following-sibling::text()').get() # 出版年
            item['price'] = response.xpath('//span[contains(text(),"定价")]/following-sibling::text()').get() # 定价
            item['rating'] = response.xpath('//strong/text()').get() # 评分
            item['rating_num'] = response.xpath('//a[contains(@href,"rating")]/span/text()').get() # 评分人数
            item['tags'] = response.xpath('//div[@id="db-tags-section"]/div[@class="indent"]/span/a/text()').getall() # 标签
    
            # 将数据添加到列表中
            self.data.append(item)
    
        def close(self, spider, reason):
            # 爬虫结束时,将数据保存为csv格式的文件
            with open('douban_books.csv', 'w', encoding='utf-8', newline='') as f:
                writer = csv.DictWriter(f, fieldnames=self.data[0].keys())
                writer.writeheader()
                writer.writerows(self.data)
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    数据清洗和处理

    接下来,我们需要对爬取的数据进行清洗和处理,提取出需要的字段和特征。我们使用pandas库来实现这个功能,pandas是一个强大而灵活的数据分析和处理库,可以方便地读取、操作和转换数据。我们需要做以下几个步骤:

    • 读取csv文件,将数据转换为DataFrame对象。
    • 去除空值和重复值,保证数据的完整性和唯一性。
    • 对部分字段进行类型转换,如将评分和评分人数转换为数值类型,将出版年转换为日期类型。
    • 对部分字段进行拆分或合并,如将作者拆分为中文作者和外文作者,将标签合并为一个字符串。
    • 对部分字段进行分组或分类,如根据评分区间划分为高分、中等、低分三类,根据出版年划分为不同的年代。

    以下是数据清洗和处理的代码:

    # -*- coding: utf-8 -*-
    import pandas as pd
    
    # 读取csv文件,将数据转换为DataFrame对象
    df = pd.read_csv('douban_books.csv')
    
    # 去除空值和重复值,保证数据的完整性和唯一性
    df.dropna(inplace=True)
    df.drop_duplicates(inplace=True)
    
    # 对部分字段进行类型转换,如将评分和评分人数转换为数值类型,将出版年转换为日期类型
    df['rating'] = pd.to_numeric(df['rating'])
    df['rating_num'] = pd.to_numeric(df['rating_num'])
    df['pub_date'] = pd.to_datetime(df['pub_date'])
    
    # 对部分字段进行拆分或合并,如将作者拆分为中文作者和外文作者,将标签合并为一个字符串 
    df[‘tags’] = df[‘tags’].apply(lambda x:,.join(x))
    
    # 对部分字段进行分组或分类,如根据评分区间划分为高分、中等、低分三类,根据出版年划分为不同的年代
    df[‘rating_level’] = pd.cut(df[‘rating’], bins=[0, 7, 8.5, 10], labels=[‘低分’, ‘中等’, ‘高分’]) 
    df[‘pub_year’] = df[‘pub_date’].dt.year 
    df[‘pub_decade’] = (df[‘pub_year’] // 10) * 10
    #数据清洗和处理完成,保存为新的csv文件
    df.to_csv(‘douban_books_cleaned.csv’, index=False)
    
    
    • 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

    数据可视化分析

    最后,我们需要对处理后的数据进行可视化分析,绘制各种类型的图表,展示不同维度的评分分布和关系。我们使用matplotlib库来实现这个功能,matplotlib是一个强大而灵活的数据可视化库,可以方便地创建各种风格和格式的图表。我们需要做以下几个步骤:

    • 导入matplotlib库,并设置中文显示和风格。
    • 读取清洗后的csv文件,将数据转换为DataFrame对象。
    • 使用matplotlib的子模块pyplot来绘制各种图表,如直方图、饼图、箱线图、散点图等。
    • 使用matplotlib的子模块axes来调整图表的标题、标签、刻度、图例等属性。
    • 使用matplotlib的子模块figure来保存图表为图片文件。

    以下是数据可视化分析的代码:

    # -*- coding: utf-8 -*-
    import matplotlib.pyplot as plt
    import pandas as pd
    
    # 导入matplotlib库,并设置中文显示和风格
    plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文显示
    plt.rcParams['axes.unicode_minus'] = False # 设置负号显示
    plt.style.use('ggplot') # 设置风格
    
    # 读取清洗后的csv文件,将数据转换为DataFrame对象
    df = pd.read_csv('douban_books_cleaned.csv')
    
    # 绘制直方图,显示不同评分区间的图书数量
    plt.figure(figsize=(8, 6)) # 设置画布大小
    plt.hist(df['rating'], bins=20, color='steelblue', edgecolor='k') # 绘制直方图
    plt.xlabel('评分') # 设置x轴标签
    plt.ylabel('数量') # 设置y轴标签
    plt.title('豆瓣图书评分直方图') # 设置标题
    plt.savefig('rating_hist.png') # 保存图片
    
    # 绘制饼图,显示不同评分等级的图书占比
    plt.figure(figsize=(8, 6)) # 设置画布大小
    rating_level_counts = df['rating_level'].value_counts() # 计算不同评分等级的图书数量
    plt.pie(rating_level_counts, labels=rating_level_counts.index, autopct='%.2f%%', colors=['limegreen', 'gold', 'tomato']) # 绘制饼图
    plt.title('豆瓣图书评分等级饼图') # 设置标题
    plt.savefig('rating_level_pie.png') # 保存图片
    
    # 绘制箱线图,显示不同年代的图书评分分布
    plt.figure(figsize=(8, 6)) # 设置画布大小
    decades = df['pub_decade'].unique() # 获取不同年代的列表
    decades.sort() # 对年代进行排序
    ratings_by_decade = [df[df['pub_decade'] == decade]['rating'] for decade in decades] # 获取每个年代对应的评分列表
    plt.boxplot(ratings_by_decade, labels=decades) # 绘制箱线图
    plt.xlabel('年代') # 设置x轴标签
    plt.ylabel('评分') # 设置y轴标签
    plt.title('豆瓣图书不同年代评分箱线图') # 设置标题
    plt.savefig('rating_by_decade_box.png') # 保存图片
    
    # 绘制散点图,显示评分和评分人数的关系
    plt.figure(figsize=(8, 6)) # 设置画布大小
    plt.scatter(df['rating'], df['rating_num'], color='steelblue', alpha=0.5) # 绘制散点图
    plt.xlabel('评分') # 设置x轴标签
    plt.ylabel('评分人数') # 设置y轴标签
    plt.title('豆瓣图书评分和评分人数散点图') # 设置标题
    plt.savefig('rating_num_scatter.png') # 保存图片
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    结语

    本文介绍了如何使用爬虫技术获取豆瓣图书的评分数据,并进行可视化分析,探索不同类型、不同年代、不同地区的图书的评分特征和规律。通过本文,我们可以学习到以下几点:

    • 如何使用scrapy框架编写爬虫程序,从豆瓣图书网站抓取图书的基本信息和评分数据,保存为csv格式的文件。
    • 如何使用亿牛云爬虫代理服务,提高爬虫效率和稳定性,避免被豆瓣网站屏蔽或封禁。
    • 如何使用pandas库对爬取的数据进行清洗和处理,提取出需要的字段和特征。
    • 如何使用matplotlib库对处理后的数据进行可视化分析,绘制各种类型的图表,展示不同维度的评分分布和关系。

    希望本文能够对你有所帮助,如果你对爬虫技术或者数据可视化有兴趣,可以继续深入学习和探索。谢谢你的阅读!

  • 相关阅读:
    Python图像处理算法实战【1】超详细整理 | 新手入门实用指南 | 图像处理基础
    代码随想录算法训练营day52 | 300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组
    测试概念第三篇—注册登陆测试用例
    图论|684.冗余连接 685. 冗余连接 II
    微服务架构笔记
    Simulink 自动代码生成:手写代码替换生成代码Code Replacement Tool使用
    电机无位置控制方法研究
    正点原子lwIP学习笔记——NTP实时时间实验
    React学习之路-目录结构
    有限元编程示例
  • 原文地址:https://blog.csdn.net/ip16yun/article/details/132836044