## 導(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í)和探索。謝謝你的閱讀惋嚎!