Python利用lxml模塊爬取豆瓣讀書排行榜的方法與分析
前言
上次使用了BeautifulSoup庫(kù)爬取電影排行榜,爬取相對(duì)來(lái)說(shuō)有點(diǎn)麻煩,爬取的速度也較慢。本次使用的lxml庫(kù),我個(gè)人是最喜歡的,爬取的語(yǔ)法很簡(jiǎn)單,爬取速度也快。
本次爬取的豆瓣書籍排行榜的首頁(yè)地址是:
https://www.douban.com/doulist/1264675/?start=0&sort=time&playable=0&sub_type=
該排行榜一共有22頁(yè),且發(fā)現(xiàn)更改網(wǎng)址的 start=0 的 0 為25、50就可以跳到排行榜的第二、第三頁(yè),所以后面只需更改這個(gè)數(shù)字然后通過(guò)遍歷就可以爬取整個(gè)排行榜的書籍信息。
本次爬取的內(nèi)容有書名、評(píng)分、評(píng)價(jià)數(shù)、出版社、出版年份以及書籍封面圖,封面圖保存為圖片,其他數(shù)據(jù)存為csv文件,方面后面讀取分析。
本次的項(xiàng)目步驟:一、分析網(wǎng)頁(yè),確定爬取數(shù)據(jù)
二、使用lxml庫(kù)爬取內(nèi)容并保存
三、讀取數(shù)據(jù)并選擇部分內(nèi)容進(jìn)行分析
步驟一:

分析網(wǎng)頁(yè)源代碼可以看到,書籍信息在屬性為的div標(biāo)簽中,打開(kāi)發(fā)現(xiàn),我們需要爬取的信息都在標(biāo)簽內(nèi)部,通過(guò)xpath語(yǔ)法我們可以很簡(jiǎn)便的爬取所需內(nèi)容。

(書籍各類信息所在標(biāo)簽)
所需爬取的內(nèi)容在 class為post、title、rating、abstract的div標(biāo)簽中。
步驟二:
先定義爬取函數(shù),爬取所需內(nèi)容執(zhí)行函數(shù),并存入csv文件
具體代碼如下:
import requests
from lxml import etree
import time
import csv
#信息頭
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
}
#定義爬取函數(shù)
def douban_booksrank(url):
res = requests.get(url, headers=headers)
selector = etree.HTML(res.text)
contents = selector.xpath('//div[@class="article"]/div[contains(@class,"doulist-item")]') #循環(huán)點(diǎn)
for content in contents:
try:
title = content.xpath('div/div[2]/div[3]/a/text()')[0] #書名
scores = content.xpath('div/div[2]/div[4]/span[2]/text()') #評(píng)分
scores.append('9.0') #因?yàn)橛幸恍鴽](méi)有評(píng)分,導(dǎo)致列表為空,此處添加一個(gè)默認(rèn)評(píng)分,若無(wú)評(píng)分則默認(rèn)為9.0
score = scores[0]
comments = content.xpath('div/div[2]/div[4]/span[3]/text()')[0] #評(píng)論數(shù)量
author = content.xpath('div/div[2]/div[5]/text()[1]')[0] #作者
publishment = content.xpath('div/div[2]/div[5]/text()[2]')[0] #出版社
pub_year = content.xpath('div/div[2]/div[5]/text()[3]')[0] #出版時(shí)間
img_url = content.xpath('div/div[2]/div[2]/a/img/@src')[0] #書本圖片的網(wǎng)址
img = requests.get(img_url) #解析圖片網(wǎng)址,為下面下載圖片
img_name_file = 'C:/Users/lenovo/Desktop/douban_books/{}.png'.format((title.strip())[:3]) #圖片存儲(chǔ)位置,圖片名只取前3
#寫入csv
with open('C:\\Users\lenovo\Desktop\\douban_books.csv', 'a+', newline='', encoding='utf-8')as fp: #newline 使不隔行
writer = csv.writer(fp)
writer.writerow((title, score, comments, author, publishment, pub_year, img_url))
#下載圖片,為防止圖片名導(dǎo)致格式錯(cuò)誤,加入try...except
try:
with open(img_name_file, 'wb')as imgf:
imgf.write(img.content)
except FileNotFoundError or OSError:
pass
time.sleep(0.5) #睡眠0.5s
except IndexError:
pass
#執(zhí)行程序
if __name__=='__main__':
#爬取所有書本,共22頁(yè)的內(nèi)容
urls = ['https://www.douban.com/doulist/1264675/?start={}&sort=time&playable=0&sub_type='.format(str(i))for i in range(0,550,25)]
#寫csv首行
with open('C:\\Users\lenovo\Desktop\\douban_books.csv', 'a+', newline='', encoding='utf-8')as f:
writer = csv.writer(f)
writer.writerow(('title', 'score', 'comment', 'author', 'publishment', 'pub_year', 'img_url'))
#遍歷所有網(wǎng)頁(yè),執(zhí)行爬取程序
for url in urls:
douban_booksrank(url)
爬取結(jié)果截圖如下:


步驟三:
本次使用Python常用的數(shù)據(jù)分析庫(kù)pandas來(lái)提取所需內(nèi)容。pandas的read_csv()函數(shù)可以讀取csv文件并根據(jù)文件格式轉(zhuǎn)換為Series、DataFrame或面板對(duì)象。
此處我們提取的數(shù)據(jù)轉(zhuǎn)變?yōu)镈ataFrame(數(shù)據(jù)幀)對(duì)象,然后通過(guò)Matplotlib繪圖庫(kù)來(lái)進(jìn)行繪圖。
具體代碼如下:
from matplotlib import pyplot as plt
import pandas as pd
import re
plt.rcParams['font.sans-serif']=['SimHei'] #用來(lái)正常顯示中文標(biāo)簽
plt.rcParams['axes.unicode_minus']=False #用來(lái)正常顯示負(fù)號(hào)
plt.subplots_adjust(wsapce=0.5, hspace=0.5) #調(diào)整subplot子圖間的距離
pd.set_option('display.max_rows', None) #設(shè)置使dataframe 所有行都顯示
df = pd.read_csv('C:\\Users\lenovo\Desktop\\douban_books.csv') #讀取csv文件,并賦為dataframe對(duì)象
comment = re.findall('\((.*?)人評(píng)價(jià)', str(df.comment), re.S) #使用正則表達(dá)式獲取評(píng)論人數(shù)
#將comment的元素化為整型
new_comment = []
for i in comment:
new_comment.append(int(i))
pub_year = re.findall(r'\d{4}', str(df.pub_year),re.S) #獲取書籍出版年份
#同上
new_pubyear = []
for n in pub_year:
new_pubyear.append(int(n))
#繪圖
#1、繪制書籍評(píng)分范圍的直方圖
plt.subplot(2,2,1)
plt.hist(df.score, bins=16, edgecolor='black')
plt.title('豆瓣書籍排行榜評(píng)分分布', fontweight=700)
plt.xlabel('scores')
plt.ylabel('numbers')
#繪制書籍評(píng)論數(shù)量的直方分布圖
plt.subplot(222)
plt.hist(new_comment, bins=16, color='green', edgecolor='yellow')
plt.title('豆瓣書籍排行榜評(píng)價(jià)分布', fontweight=700)
plt.xlabel('評(píng)價(jià)數(shù)')
plt.ylabel('書籍?dāng)?shù)量(單位/本)')
#繪制書籍出版年份分布圖
plt.subplot(2,2,3)
plt.hist(new_pubyear, bins=30, color='indigo',edgecolor='blue')
plt.title('書籍出版年份分布', fontweight=700)
plt.xlabel('出版年份/year')
plt.ylabel('書籍?dāng)?shù)量/本')
#尋找關(guān)系
plt.subplot(224)
plt.bar(new_pubyear,new_comment, color='red', edgecolor='white')
plt.title('書籍出版年份與評(píng)論數(shù)量的關(guān)系', fontweight=700)
plt.xlabel('出版年份/year')
plt.ylabel('評(píng)論數(shù)')
plt.savefig('C:\\Users\lenovo\Desktop\\douban_books_analysis.png') #保存圖片
plt.show()
這里需要注意的是,使用了正則表達(dá)式來(lái)提取評(píng)論數(shù)和出版年份,將其中的符號(hào)和文字等剔除。
分析結(jié)果如下:

本次分析的內(nèi)容也較為簡(jiǎn)單,從上面的幾個(gè)圖形中我們也能得出一些結(jié)論。
這些高分書籍中絕大多數(shù)的評(píng)論數(shù)量都在50000以下;多數(shù)排行榜上的高分書籍都出版在2000年以后;出版年份在2000年后的書籍有更多的評(píng)論數(shù)量。
以上數(shù)據(jù)也見(jiàn)解的說(shuō)明了在進(jìn)入二十世紀(jì)后我國(guó)的圖書需求量更大了,網(wǎng)絡(luò)更發(fā)達(dá),更多人愿意發(fā)表自己的看法。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Python list和str互轉(zhuǎn)的實(shí)現(xiàn)示例
這篇文章主要介紹了Python list和str互轉(zhuǎn)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
pytorch 在網(wǎng)絡(luò)中添加可訓(xùn)練參數(shù),修改預(yù)訓(xùn)練權(quán)重文件的方法
今天小編就為大家分享一篇pytorch 在網(wǎng)絡(luò)中添加可訓(xùn)練參數(shù),修改預(yù)訓(xùn)練權(quán)重文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08
Python中動(dòng)態(tài)創(chuàng)建類實(shí)例的方法
在Java中我們可以通過(guò)反射來(lái)根據(jù)類名創(chuàng)建類實(shí)例,那么在Python我們?cè)趺磳?shí)現(xiàn)類似功能呢?其實(shí)在Python有一個(gè)builtin函數(shù)import,我們可以使用這個(gè)函數(shù)來(lái)在運(yùn)行時(shí)動(dòng)態(tài)加載一些模塊2017-03-03
python 通過(guò)可變參數(shù)計(jì)算n個(gè)數(shù)的乘積方法
今天小編就為大家分享一篇python 通過(guò)可變參數(shù)計(jì)算n個(gè)數(shù)的乘積方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
python實(shí)現(xiàn)應(yīng)用程序在右鍵菜單中添加打開(kāi)方式功能
這篇文章主要介紹了python實(shí)現(xiàn)應(yīng)用程序在右鍵菜單中添加打開(kāi)方式功能,本文分步驟給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-01-01
Python 3.x 連接數(shù)據(jù)庫(kù)示例(pymysql 方式)
這篇文章主要介紹了Python 3.x 連接數(shù)據(jù)庫(kù)示例(pymysql 方式),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
關(guān)于命令行執(zhí)行Python腳本的傳參方式
這篇文章主要介紹了關(guān)于命令行執(zhí)行Python腳本的傳參方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09

