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

## 导语

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

## 概述

本文的主要步骤如下:

- 使用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文件,并添加以下配置:

```python

# 启用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'

```

以下是爬虫程序的代码:

```python

# -*- 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)

```

### 数据清洗和处理

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

- 读取csv文件,将数据转换为DataFrame对象。

- 去除空值和重复值,保证数据的完整性和唯一性。

- 对部分字段进行类型转换,如将评分和评分人数转换为数值类型,将出版年转换为日期类型。

- 对部分字段进行拆分或合并,如将作者拆分为中文作者和外文作者,将标签合并为一个字符串。

- 对部分字段进行分组或分类,如根据评分区间划分为高分、中等、低分三类,根据出版年划分为不同的年代。

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

```python

# -*- 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)

```

### 数据可视化分析

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

- 导入matplotlib库,并设置中文显示和风格。

- 读取清洗后的csv文件,将数据转换为DataFrame对象。

- 使用matplotlib的子模块pyplot来绘制各种图表,如直方图、饼图、箱线图、散点图等。

- 使用matplotlib的子模块axes来调整图表的标题、标签、刻度、图例等属性。

- 使用matplotlib的子模块figure来保存图表为图片文件。

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

```python

# -*- 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') # 保存图片

```

## 结语

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

- 如何使用scrapy框架编写爬虫程序,从豆瓣图书网站抓取图书的基本信息和评分数据,保存为csv格式的文件。

- 如何使用亿牛云爬虫代理服务,提高爬虫效率和稳定性,避免被豆瓣网站屏蔽或封禁。

- 如何使用pandas库对爬取的数据进行清洗和处理,提取出需要的字段和特征。

- 如何使用matplotlib库对处理后的数据进行可视化分析,绘制各种类型的图表,展示不同维度的评分分布和关系。

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容