豆瓣圖書評分?jǐn)?shù)據(jù)的可視化分析

## 導(dǎo)語

豆瓣是一個提供圖書、電影、音樂等文化產(chǎn)品的社區(qū)平臺,用戶可以在上面發(fā)表自己的評價和評論族奢,形成一個豐富的文化數(shù)據(jù)庫。本文將介紹如何使用爬蟲技術(shù)獲取豆瓣圖書的評分?jǐn)?shù)據(jù)丹鸿,并進(jìn)行可視化分析越走,探索不同類型、不同年代靠欢、不同地區(qū)的圖書的評分特征和規(guī)律廊敌。

## 概述

本文的主要步驟如下:

- 使用scrapy框架編寫爬蟲程序,從豆瓣圖書網(wǎng)站抓取圖書的基本信息和評分?jǐn)?shù)據(jù)门怪,保存為csv格式的文件骡澈。

- 使用億牛云爬蟲代理服務(wù),提高爬蟲效率和穩(wěn)定性掷空,避免被豆瓣網(wǎng)站屏蔽或封禁肋殴。

- 使用pandas庫對爬取的數(shù)據(jù)進(jìn)行清洗和處理,提取出需要的字段和特征坦弟。

- 使用matplotlib庫對處理后的數(shù)據(jù)進(jìn)行可視化分析护锤,繪制各種類型的圖表,展示不同維度的評分分布和關(guān)系减拭。

## 正文

### 爬蟲程序

首先蔽豺,我們需要編寫一個爬蟲程序区丑,從豆瓣圖書網(wǎng)站抓取圖書的基本信息和評分?jǐn)?shù)據(jù)拧粪。我們使用scrapy框架來實現(xiàn)這個功能,scrapy是一個強(qiáng)大而靈活的爬蟲框架沧侥,可以方便地定義爬蟲規(guī)則和處理數(shù)據(jù)可霎。我們需要定義一個Spider類,繼承自scrapy.Spider類宴杀,并重寫以下方法:

- start_requests:該方法返回一個可迭代對象,包含了爬蟲開始時要訪問的請求對象。我們可以從豆瓣圖書首頁開始罢维,獲取所有分類的鏈接奕扣,并構(gòu)造請求對象。

- parse:該方法負(fù)責(zé)處理start_requests返回的請求對象的響應(yīng)扁达,并解析出需要的數(shù)據(jù)或者進(jìn)一步的請求正卧。我們可以使用scrapy自帶的選擇器或者BeautifulSoup等第三方庫來解析HTML文檔,提取出圖書列表頁的鏈接跪解,并構(gòu)造請求對象炉旷。

- parse_book:該方法負(fù)責(zé)處理parse返回的請求對象的響應(yīng),并解析出圖書詳情頁的數(shù)據(jù)。我們可以使用同樣的方式來提取出圖書的基本信息和評分?jǐn)?shù)據(jù)窘行,并將其保存為字典格式饥追。

- close:該方法在爬蟲結(jié)束時被調(diào)用,我們可以在這里將抓取到的數(shù)據(jù)保存為csv格式的文件罐盔。

為了提高爬蟲效率和穩(wěn)定性但绕,我們還需要使用億牛云爬蟲代理服務(wù),該服務(wù)提供了大量高質(zhì)量的代理IP地址惶看,可以幫助我們避免被豆瓣網(wǎng)站屏蔽或封禁壁熄。我們只需要在settings.py文件中設(shè)置代理服務(wù)器的域名、端口碳竟、用戶名和密碼草丧,以及啟用中間件HttpProxyMiddleware即可。

首先配置爬蟲代理莹桅,你可以按照以下步驟在Scrapy項目的settings.py文件中進(jìn)行配置:

確保已經(jīng)安裝了Scrapy以及相關(guān)依賴昌执。然后,打開你的Scrapy項目的settings.py文件诈泼,并添加以下配置:

```python

# 啟用HttpProxyMiddleware中間件

DOWNLOADER_MIDDLEWARES = {

? ? 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,

}

# 設(shè)置億牛云 爬蟲代理服務(wù)器的配置

HTTPPROXY_AUTH_ENCODING = 'utf-8'? # 編碼格式

# 億牛云 爬蟲代理服務(wù)器的域名懂拾、端口、用戶名和密碼

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/']

? ? # 定義保存數(shù)據(jù)的列表

? ? 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:

? ? ? ? ? ? # 構(gòu)造分類頁面的請求對象

? ? ? ? ? ? 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:

? ? ? ? ? ? # 構(gòu)造圖書詳情頁的請求對象

? ? ? ? ? ? url = book.xpath('./div[@class="info"]/h2/a/@href').get()

? ? ? ? ? ? yield scrapy.Request(url=url, callback=self.parse_detail)

? ? ? ? # 獲取下一頁的鏈接,如果存在則繼續(xù)爬取

? ? ? ? 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):

? ? ? ? # 解析圖書詳情頁瓮孙,獲取圖書的基本信息和評分?jǐn)?shù)據(jù)

? ? ? ? item = {}

? ? ? ? item['title'] = response.xpath('//h1/span/text()').get() # 標(biāo)題

? ? ? ? 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() # 評分人數(shù)

? ? ? ? item['tags'] = response.xpath('//div[@id="db-tags-section"]/div[@class="indent"]/span/a/text()').getall() # 標(biāo)簽

? ? ? ? # 將數(shù)據(jù)添加到列表中

? ? ? ? self.data.append(item)

? ? def close(self, spider, reason):

? ? ? ? # 爬蟲結(jié)束時唐断,將數(shù)據(jù)保存為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)

```

### 數(shù)據(jù)清洗和處理

接下來,我們需要對爬取的數(shù)據(jù)進(jìn)行清洗和處理杭抠,提取出需要的字段和特征脸甘。我們使用pandas庫來實現(xiàn)這個功能,pandas是一個強(qiáng)大而靈活的數(shù)據(jù)分析和處理庫偏灿,可以方便地讀取丹诀、操作和轉(zhuǎn)換數(shù)據(jù)。我們需要做以下幾個步驟:

- 讀取csv文件翁垂,將數(shù)據(jù)轉(zhuǎn)換為DataFrame對象铆遭。

- 去除空值和重復(fù)值,保證數(shù)據(jù)的完整性和唯一性沿猜。

- 對部分字段進(jìn)行類型轉(zhuǎn)換枚荣,如將評分和評分人數(shù)轉(zhuǎn)換為數(shù)值類型,將出版年轉(zhuǎn)換為日期類型邢疙。

- 對部分字段進(jìn)行拆分或合并棍弄,如將作者拆分為中文作者和外文作者望薄,將標(biāo)簽合并為一個字符串。

- 對部分字段進(jìn)行分組或分類呼畸,如根據(jù)評分區(qū)間劃分為高分痕支、中等、低分三類蛮原,根據(jù)出版年劃分為不同的年代卧须。

以下是數(shù)據(jù)清洗和處理的代碼:

```python

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

import pandas as pd

# 讀取csv文件,將數(shù)據(jù)轉(zhuǎn)換為DataFrame對象

df = pd.read_csv('douban_books.csv')

# 去除空值和重復(fù)值儒陨,保證數(shù)據(jù)的完整性和唯一性

df.dropna(inplace=True)

df.drop_duplicates(inplace=True)

# 對部分字段進(jìn)行類型轉(zhuǎn)換花嘶,如將評分和評分人數(shù)轉(zhuǎn)換為數(shù)值類型,將出版年轉(zhuǎn)換為日期類型

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'])

# 對部分字段進(jìn)行拆分或合并蹦漠,如將作者拆分為中文作者和外文作者椭员,將標(biāo)簽合并為一個字符串

df[‘tags’] = df[‘tags’].apply(lambda x: ‘,’.join(x))

# 對部分字段進(jìn)行分組或分類,如根據(jù)評分區(qū)間劃分為高分笛园、中等隘击、低分三類,根據(jù)出版年劃分為不同的年代

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

#數(shù)據(jù)清洗和處理完成研铆,保存為新的csv文件

df.to_csv(‘douban_books_cleaned.csv’, index=False)

```

### 數(shù)據(jù)可視化分析

最后埋同,我們需要對處理后的數(shù)據(jù)進(jìn)行可視化分析,繪制各種類型的圖表棵红,展示不同維度的評分分布和關(guān)系凶赁。我們使用matplotlib庫來實現(xiàn)這個功能,matplotlib是一個強(qiáng)大而靈活的數(shù)據(jù)可視化庫逆甜,可以方便地創(chuàng)建各種風(fēng)格和格式的圖表虱肄。我們需要做以下幾個步驟:

- 導(dǎo)入matplotlib庫,并設(shè)置中文顯示和風(fēng)格忆绰。

- 讀取清洗后的csv文件浩峡,將數(shù)據(jù)轉(zhuǎn)換為DataFrame對象。

- 使用matplotlib的子模塊pyplot來繪制各種圖表错敢,如直方圖、餅圖缕粹、箱線圖稚茅、散點(diǎn)圖等。

- 使用matplotlib的子模塊axes來調(diào)整圖表的標(biāo)題平斩、標(biāo)簽亚享、刻度、圖例等屬性绘面。

- 使用matplotlib的子模塊figure來保存圖表為圖片文件欺税。

以下是數(shù)據(jù)可視化分析的代碼:

```python

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

import matplotlib.pyplot as plt

import pandas as pd

# 導(dǎo)入matplotlib庫侈沪,并設(shè)置中文顯示和風(fēng)格

plt.rcParams['font.sans-serif'] = ['SimHei'] # 設(shè)置中文顯示

plt.rcParams['axes.unicode_minus'] = False # 設(shè)置負(fù)號顯示

plt.style.use('ggplot') # 設(shè)置風(fēng)格

# 讀取清洗后的csv文件,將數(shù)據(jù)轉(zhuǎn)換為DataFrame對象

df = pd.read_csv('douban_books_cleaned.csv')

# 繪制直方圖晚凿,顯示不同評分區(qū)間的圖書數(shù)量

plt.figure(figsize=(8, 6)) # 設(shè)置畫布大小

plt.hist(df['rating'], bins=20, color='steelblue', edgecolor='k') # 繪制直方圖

plt.xlabel('評分') # 設(shè)置x軸標(biāo)簽

plt.ylabel('數(shù)量') # 設(shè)置y軸標(biāo)簽

plt.title('豆瓣圖書評分直方圖') # 設(shè)置標(biāo)題

plt.savefig('rating_hist.png') # 保存圖片

# 繪制餅圖亭罪,顯示不同評分等級的圖書占比

plt.figure(figsize=(8, 6)) # 設(shè)置畫布大小

rating_level_counts = df['rating_level'].value_counts() # 計算不同評分等級的圖書數(shù)量

plt.pie(rating_level_counts, labels=rating_level_counts.index, autopct='%.2f%%', colors=['limegreen', 'gold', 'tomato']) # 繪制餅圖

plt.title('豆瓣圖書評分等級餅圖') # 設(shè)置標(biāo)題

plt.savefig('rating_level_pie.png') # 保存圖片

# 繪制箱線圖,顯示不同年代的圖書評分分布

plt.figure(figsize=(8, 6)) # 設(shè)置畫布大小

decades = df['pub_decade'].unique() # 獲取不同年代的列表

decades.sort() # 對年代進(jìn)行排序

ratings_by_decade = [df[df['pub_decade'] == decade]['rating'] for decade in decades] # 獲取每個年代對應(yīng)的評分列表

plt.boxplot(ratings_by_decade, labels=decades) # 繪制箱線圖

plt.xlabel('年代') # 設(shè)置x軸標(biāo)簽

plt.ylabel('評分') # 設(shè)置y軸標(biāo)簽

plt.title('豆瓣圖書不同年代評分箱線圖') # 設(shè)置標(biāo)題

plt.savefig('rating_by_decade_box.png') # 保存圖片

# 繪制散點(diǎn)圖歼秽,顯示評分和評分人數(shù)的關(guān)系

plt.figure(figsize=(8, 6)) # 設(shè)置畫布大小

plt.scatter(df['rating'], df['rating_num'], color='steelblue', alpha=0.5) # 繪制散點(diǎn)圖

plt.xlabel('評分') # 設(shè)置x軸標(biāo)簽

plt.ylabel('評分人數(shù)') # 設(shè)置y軸標(biāo)簽

plt.title('豆瓣圖書評分和評分人數(shù)散點(diǎn)圖') # 設(shè)置標(biāo)題

plt.savefig('rating_num_scatter.png') # 保存圖片

```

## 結(jié)語

本文介紹了如何使用爬蟲技術(shù)獲取豆瓣圖書的評分?jǐn)?shù)據(jù)应役,并進(jìn)行可視化分析,探索不同類型燥筷、不同年代箩祥、不同地區(qū)的圖書的評分特征和規(guī)律。通過本文肆氓,我們可以學(xué)習(xí)到以下幾點(diǎn):

- 如何使用scrapy框架編寫爬蟲程序袍祖,從豆瓣圖書網(wǎng)站抓取圖書的基本信息和評分?jǐn)?shù)據(jù),保存為csv格式的文件谢揪。

- 如何使用億牛云爬蟲代理服務(wù)盲泛,提高爬蟲效率和穩(wěn)定性,避免被豆瓣網(wǎng)站屏蔽或封禁键耕。

- 如何使用pandas庫對爬取的數(shù)據(jù)進(jìn)行清洗和處理寺滚,提取出需要的字段和特征。

- 如何使用matplotlib庫對處理后的數(shù)據(jù)進(jìn)行可視化分析屈雄,繪制各種類型的圖表村视,展示不同維度的評分分布和關(guān)系。

希望本文能夠?qū)δ阌兴鶐椭颇蹋绻銓ε老x技術(shù)或者數(shù)據(jù)可視化有興趣蚁孔,可以繼續(xù)深入學(xué)習(xí)和探索。謝謝你的閱讀惋嚎!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杠氢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子另伍,更是在濱河造成了極大的恐慌鼻百,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摆尝,死亡現(xiàn)場離奇詭異温艇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)堕汞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門勺爱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人讯检,你說我怎么就攤上這事琐鲁∥篮担” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵围段,是天一觀的道長顾翼。 經(jīng)常有香客問我,道長蒜撮,這世上最難降的妖魔是什么暴构? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮段磨,結(jié)果婚禮上取逾,老公的妹妹穿的比我還像新娘。我一直安慰自己苹支,他們只是感情好砾隅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著债蜜,像睡著了一般晴埂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寻定,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天儒洛,我揣著相機(jī)與錄音,去河邊找鬼狼速。 笑死琅锻,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的向胡。 我是一名探鬼主播恼蓬,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼僵芹!你這毒婦竟也來了处硬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拇派,失蹤者是張志新(化名)和其女友劉穎荷辕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體攀痊,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桐腌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了苟径。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡躬审,死狀恐怖棘街,靈堂內(nèi)的尸體忽然破棺而出蟆盐,到底是詐尸還是另有隱情,我是刑警寧澤遭殉,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布石挂,位于F島的核電站,受9級特大地震影響险污,放射性物質(zhì)發(fā)生泄漏痹愚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一蛔糯、第九天 我趴在偏房一處隱蔽的房頂上張望拯腮。 院中可真熱鬧,春花似錦蚁飒、人聲如沸动壤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琼懊。三九已至,卻和暖如春爬早,著一層夾襖步出監(jiān)牢的瞬間哼丈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工筛严, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留醉旦,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓脑漫,卻偏偏與公主長得像髓抑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子优幸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容