成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

本篇文章給大家分享的是有關(guān)Python如何一鍵爬取你所關(guān)心的書(shū)籍信息,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

成都創(chuàng)新互聯(lián)公司一直通過(guò)網(wǎng)站建設(shè)和網(wǎng)站營(yíng)銷(xiāo)幫助企業(yè)獲得更多客戶資源。 以"深度挖掘,量身打造,注重實(shí)效"的一站式服務(wù),以成都網(wǎng)站建設(shè)、網(wǎng)站制作、移動(dòng)互聯(lián)產(chǎn)品、營(yíng)銷(xiāo)型網(wǎng)站服務(wù)為核心業(yè)務(wù)。十多年網(wǎng)站制作的經(jīng)驗(yàn),使用新網(wǎng)站建設(shè)技術(shù),全新開(kāi)發(fā)出的標(biāo)準(zhǔn)網(wǎng)站,不但價(jià)格便宜而且實(shí)用、靈活,特別適合中小公司網(wǎng)站制作。網(wǎng)站管理系統(tǒng)簡(jiǎn)單易用,維護(hù)方便,您可以完全操作網(wǎng)站資料,是中小公司快速網(wǎng)站建設(shè)的選擇。

前言 

平時(shí)看到的豆瓣爬蟲(chóng)基本都是爬豆瓣top100電影、某電影熱評(píng)、top100圖書(shū)、熱門(mén)圖書(shū)等,最近遇到的一個(gè)需求是根據(jù)一堆書(shū)名的列表(或者書(shū)名Excel文件)爬取對(duì)應(yīng)的書(shū)目信息,也就是豆瓣圖書(shū)頁(yè)面上的出版社、出版時(shí)間、ISBN、定價(jià)、評(píng)分、評(píng)分人數(shù)等信息,再整合到pandas里進(jìn)行處理,最后可以進(jìn)行數(shù)據(jù)分析。

需求來(lái)源 

最近整理書(shū)目的時(shí)候需要根據(jù)幾百本書(shū)的書(shū)名整理出對(duì)應(yīng)的出版社、出版時(shí)間、ISBN、評(píng)分等屬性,書(shū)單Excel如下圖1中的表。批量處理肯定是用爬蟲(chóng)啦,查了一下沒(méi)有發(fā)現(xiàn)相似的文章,并且自己操作時(shí)也遇到了比較有趣的問(wèn)題,于是把自己的操作思路和過(guò)程整理成本文。

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖1,書(shū)單數(shù)據(jù)部分截圖

爬取過(guò)程 

頁(yè)面分析

首先分析豆瓣圖書(shū)首頁(yè):book.douban.com,直接搜索書(shū)名時(shí)可以看到搜索參數(shù)是寫(xiě)在url上的,于是想著直接用https://book.douban.com/subject_search?search_text={0}&cat=1001'.format('書(shū)名'),直接改search_text參數(shù),在這個(gè)頁(yè)面按F12調(diào)出控制臺(tái),失望的是這個(gè)url返回的html是不含數(shù)據(jù)的,如圖2。關(guān)鍵是找了一段時(shí)間還是沒(méi)找到異步返回的數(shù)據(jù)json(如果有人找到了豆瓣subject_search?search_text={0}&cat=1001這類(lèi)頁(yè)面的書(shū)籍?dāng)?shù)據(jù)的位置歡迎告訴我呀),這時(shí)候考慮用Selenium或者查其他接口。

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖2,基于搜索url的html截圖

json分析

注意到豆瓣圖書(shū)的搜索頁(yè)面有一個(gè)搜索提示,于是在控制臺(tái)查Network發(fā)現(xiàn)搜索提示返回的直接是一個(gè)json,例如查“未來(lái)簡(jiǎn)史”,結(jié)果如下:

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖3,未來(lái)簡(jiǎn)史搜索提示

返回json可以用的屬性有:title:書(shū)名、url:對(duì)應(yīng)書(shū)的豆瓣頁(yè)面、pic:書(shū)封面圖資源位置等。如果上面的輸入咱們只有書(shū)名,就根據(jù)書(shū)名和返回的json對(duì)應(yīng),如果有作者、出版年份等屬性,就可以更好的核對(duì)是否是我們要找的書(shū),為了簡(jiǎn)化,下面只用了返回json數(shù)據(jù)的第1條。

基本代碼

根據(jù)返回的url就可以從這個(gè)url去定位我們需要爬的信息。走通了就可以正式寫(xiě)代碼了,以下代碼采用jupyter notebook的組織方式,也就是切分得比較細(xì)。先引入所需庫(kù):

import json
import requests
import pandas as pd
from lxml import etree

讀取書(shū)名Excel數(shù)據(jù),只用了"書(shū)名"列,先不考慮其他列

bsdf=pd.read_excel('booklistfortest.xlsx')
blst=list(bsdf['書(shū)名'])  #書(shū)名列表
#bsdf.head(3)

對(duì)書(shū)名列表進(jìn)行循環(huán),得到的屬性用字典裝著,每本書(shū)的屬性是一個(gè)字典,用列表裝各個(gè)字典。

通過(guò)requests.get('https://book.douban.com/j/subject_suggest?q={0}'.format(bn))獲取搜索建議返回的json數(shù)據(jù),其中bn是書(shū)名字符串。
爬蟲(chóng)的一般解析是用BeautifulSoup或xpath,我更喜歡用xpath,因此下面的代碼主要基于xpath解析文本。
以評(píng)分為例,鼠標(biāo)點(diǎn)擊評(píng)分部分,然后按Ctrl+Shift+I,或者右鍵點(diǎn)擊檢查元素,反正就是定位到評(píng)分對(duì)應(yīng)的HTML上,定位到評(píng)分的代碼部分后,右鍵,選擇Copy->Copy XPath,例如對(duì)于評(píng)分來(lái)說(shuō)有://*[@id="interest_sectl"]/div/div[2]/strong。

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖4,復(fù)制評(píng)分的xpath

通過(guò)con.xpath('//*[@id="interest_sectl"]/div/div[2]/strong/text()')就可以得到評(píng)分?jǐn)?shù)據(jù),返回的是列表,一般就是第0個(gè)值。同樣,其他地方也是這樣,而作者、出版社那幾個(gè)屬性是結(jié)構(gòu)比較散的,需要特殊處理。

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖5,自由度較大的書(shū)目信息部分

通過(guò)//*[@id="info"]/span[2]可以確定 出版社 這個(gè)屬性,但是屬性的值,具體是哪個(gè)出版社不能確定,這些文字是在info這個(gè)節(jié)點(diǎn)上的。對(duì)于這種長(zhǎng)度不定的一個(gè)html區(qū)域,不能寫(xiě)死xpath解析式,需要理清其HTML樹(shù)結(jié)構(gòu),建立info的樹(shù)結(jié)構(gòu)。通過(guò)分析幾個(gè)具體的頁(yè)面的info部分,建立樹(shù)結(jié)構(gòu)如下:

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖6,info部分的HTML樹(shù)

需要得到的是{'出版社’:'中信出版集團(tuán)'}這樣的數(shù)據(jù),通過(guò)HTML樹(shù)結(jié)構(gòu)可以看到的特征是鍵(如出版社)在span里,值可能在text里,也可能封裝在span里的子元素里,反正每個(gè)鍵值對(duì)之后都有一個(gè)br去切分??紤]這些情況寫(xiě)出的代碼如下:

def getBookInfo(binfo,cc):
   i=0
   rss={}
   k=''
   v=''
   f=0
   clw=[]
   for c in cc:
       if '\n' in c:
           if '\xa0' in c:
               clw.append(c)
       else:
           clw.append(c)
   
   for m in binfo[0]:
       if m.tag=='span':
           mlst=m.getchildren()
           if len(mlst)==0:
               k=m.text.replace(':','')
               if '\xa0' in clw[i]:
                   f=1#需要m.tag=='a'下的值
               else:
                   v=clw[i].replace('\n','').replace(' ','')
               i+=1
           elif len(mlst)>0:#下面有子span 一種判斷是m.attrib=={} 不夠精確
               for n in mlst:
                   if n.tag=='span':
                       k=n.text.replace('\n','').replace(' ','') #不至于下面還有span,懶得用遞歸了
                   elif n.tag=='a':
                       v=n.text.replace('\n','').replace(' ','')
       
       elif m.tag=='a':
           if f==1: #是否可以不用這個(gè)if
               v=m.text.replace('\n','').replace(' ','')
               f=0
       elif m.tag=='br':
           if k=='':
               print(i,'err')
           else:
               rss[k]=v
       else:
           print(m.tag,i)
   return rss

為了在大循環(huán)里好調(diào)用,上面的部分封裝成函數(shù),調(diào)用getBookInfo()返回的是一個(gè)字典,要整合到已有的字典里。涉及字典的組合,查了一下可以用d=dict(d,**dw),其中d是舊字典,dw是要加到d里的新字典,更簡(jiǎn)便的方式是用d.update(dw)函數(shù),下面的代碼就是用的update的。

主循環(huán)代碼:

rlst=[]
for bn in blst:
   res={}
   r=requests.get('https://book.douban.com/j/subject_suggest?q={0}'.format(bn))
   rj=json.loads(r.text)
   #對(duì)rj進(jìn)行一下驗(yàn)證和篩選
   html=requests.get(rj[0]['url']) #之后再考慮多個(gè)返回值的驗(yàn)證
   con = etree.HTML(html.text)
   bname=con.xpath('//*[@id="wrapper"]/h2/span/text()')[0] #和bn比較
   res['bname_sq']=bn
   res['bname']=bname
   res['dbid']=rj[0]['id'] #不需要存url,存id就夠了
   #這部分取到info就夠了,之后再用高級(jí)方法去匹配需要的元素,目前對(duì)應(yīng)不對(duì)
   binfo=con.xpath('//*[@id="info"]')
   cc=con.xpath('//*[@id="info"]/text()')
   res.update(getBookInfo(binfo,cc))  #調(diào)用上面的函數(shù)處理binfo
   bmark=con.xpath('//*[@id="interest_sectl"]/div/div[2]/strong/text()')[0]
   if bmark=='  ':
       bits=con.xpath('//*[@id="interest_sectl"]/div/div[2]/div/div[2]/span/a/text()')[0]
       if bits=='評(píng)價(jià)人數(shù)不足':
           res['評(píng)分']=''
           res['評(píng)價(jià)人數(shù)']='評(píng)價(jià)人數(shù)不足'
       else:
           res['評(píng)分']=''
           res['評(píng)價(jià)人數(shù)']=''
   else:
       res['評(píng)分']=bmark.replace(' ','')
       bmnum=con.xpath('//*[@id="interest_sectl"]/div/div[2]/div/div[2]/span/a/span/text()')[0]
       res['評(píng)價(jià)人數(shù)']=bmnum
   rlst.append(res)
得到的數(shù)據(jù)可以進(jìn)行一定的標(biāo)準(zhǔn)化然后進(jìn)行分析再輸出。上面得到的列表rlst=[{'書(shū)名':'a','出版社':'b'},{'','','':''}],可以直接變成dataframe,

outdf=pd.DataFrame(rlst) #轉(zhuǎn)dataframe
outdf.to_excel('out_douban_binfo.xlsx',index=False) #輸出數(shù)據(jù)

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖7,爬到的數(shù)據(jù)概覽

基礎(chǔ)數(shù)據(jù)統(tǒng)計(jì)分析

我們開(kāi)始時(shí)讀入的bsdf有書(shū)名、作者、閱讀時(shí)間等屬性,因?yàn)榕老聛?lái)的數(shù)據(jù)可能會(huì)有缺失值,將兩個(gè)表合并起來(lái)進(jìn)行分析。分析的維度有書(shū)名、作者、閱讀時(shí)間、出版社、頁(yè)數(shù)等。首先是用merge整合兩表然后看一些基本的統(tǒng)計(jì)量。

bdf=bsdf.merge(outdf,on='書(shū)名',how='left') # 數(shù)據(jù)合并
# 基本統(tǒng)計(jì)值
print('一共有{0}本書(shū),{1}個(gè)作者,{2}個(gè)出版社;'.format(len(bdf),len(set(list(bdf['作
者']))),len(set(list(bdf['出版社'])))))

輸出是一共有421本書(shū),309個(gè)作者,97個(gè)出版社;
我們就來(lái)看看前幾位的作者和出版社,通過(guò)bdf['作者'].value_counts().head(7)可以輸出前7位書(shū)單里出現(xiàn)最多的作者,出版社同理,結(jié)果如下:

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖8,出版社和作者統(tǒng)計(jì)

從作者出現(xiàn)次數(shù)來(lái)看,前6位都是小說(shuō)類(lèi)型的書(shū),可以看一下吳軍的是哪些書(shū):

bdf.loc[bdf['作者']=='吳軍',['書(shū)名','閱讀時(shí)間','閱讀情況','出版社']]
#output:
'''
                 書(shū)名       閱讀時(shí)間 閱讀情況      出版社
103             數(shù)學(xué)之美 2016-10-20   P5  人民郵電出版社
233             智能時(shí)代 2017-06-22   P4    中信出版社
237             硅谷之謎 2017-07-01   P4  人民郵電出版社
383  見(jiàn)識(shí)--商業(yè)的本質(zhì)和人生的智慧 2018-10-21   P4    中信出版社
'''
對(duì)每月閱讀數(shù)量進(jìn)行統(tǒng)計(jì):

import matplotlib.pyplot as plt #繪圖用到matplotlib庫(kù)
%matplotlib inline

bdf['閱讀年月']=bdf['閱讀時(shí)間'].apply(lambda x : x.strftime('%Y-%m'))
read_date=bdf['閱讀年月'].value_counts() #每月閱讀量,按月計(jì)數(shù)
read_date=pd.DataFrame(read_date,columns=['閱讀年月']) #從Series變?yōu)镈ataFrame
read_date=read_date.sort_index()

plt.figure(figsize=(15,5))
plt.xticks(rotation=90)#設(shè)置時(shí)間標(biāo)簽顯示格式
plt.plot(read_date) #因?yàn)閖upyter里寫(xiě)了 %matplotlib inline 不用寫(xiě) plt.show()

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖9,每月閱讀數(shù)量_時(shí)間軸折線圖.png

好奇不同年份每個(gè)月是否有一定規(guī)律呢。要統(tǒng)計(jì)這個(gè)比較方便的就是用數(shù)據(jù)透視表了,pandas里的pivot_table出場(chǎng)。

import numpy as np
bdf['閱讀年']=bdf['閱讀時(shí)間'].apply(lambda x : x.strftime('%Y'))
bdf['閱讀月']=bdf['閱讀時(shí)間'].apply(lambda x : x.strftime('%m')) #這里也可以用.month .year
r_dd=bdf.loc[:,['閱讀年','閱讀月']]
r_dd['val']=1 #用以初始化
r_dd=pd.pivot_table(r_dd,values='val',index=['閱讀月'],columns=['閱讀年'],aggfunc=np.sum).fillna(value=0)
#這部分代碼的細(xì)節(jié)可以看本人github里jupyter notebook文件的輸出
r_dd=r_dd.loc[:,['2016','2017','2018']] #因?yàn)槠渌攴菰路莶蝗蝗∵@3年來(lái)看
plt.figure()
r_dd.plot(xticks=range(1,13),figsize=(12,5))

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖10,每月閱讀數(shù)量_按年統(tǒng)計(jì)

可以看到這3年在2月和7月閱讀普遍數(shù)量更多,在7月份之前每月閱讀量是逐年上漲的,而從8月到12月則是遞減的規(guī)律,2016年11月閱讀的書(shū)籍最多,達(dá)到40本以上。
評(píng)分是一個(gè)數(shù)值型變量,用箱線圖[圖片上傳中...(圖12_書(shū)單內(nèi)數(shù)據(jù)相關(guān)的書(shū)籍.png-5352ab-1551272966564-0)]
展現(xiàn)其特征:

b_rank=pd.DataFrame(bdf['評(píng)分']) #評(píng)分分布(箱線圖)
b_rank.boxplot()

#另,評(píng)分 top 10:
#bdf.sort_values(by='評(píng)分',ascending=False).head(10).loc[:,['書(shū)名','作者','閱讀時(shí)間'
,'閱讀情況','出版社','評(píng)分']]

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖11,書(shū)籍評(píng)分箱線圖

從箱線圖來(lái)看,書(shū)單有評(píng)分的書(shū)籍的豆瓣平均分在7.8左右,75%的書(shū)評(píng)分在7.2以上,也有一些書(shū)是在4分一下的。

Python如何一鍵爬取你所關(guān)心的書(shū)籍信息

圖12,書(shū)單內(nèi)數(shù)據(jù)相關(guān)的書(shū)籍

書(shū)單里書(shū)名直接包含數(shù)據(jù)的書(shū)有37本,數(shù)據(jù)科學(xué)相關(guān)的書(shū)籍?dāng)?shù)量應(yīng)該大于這個(gè)值。

可以進(jìn)一步分析的有:

  • 看的書(shū)的書(shū)名詞云、作者的詞云

  • 出版社省份

  • 把字?jǐn)?shù)統(tǒng)計(jì)和爬下來(lái)的頁(yè)數(shù)進(jìn)行擬合,把字?jǐn)?shù)和頁(yè)數(shù)一起處理

  • 把含有多國(guó)貨幣的價(jià)格屬性按匯率換算后看價(jià)格的分布

數(shù)據(jù)輸出

上面通過(guò)一個(gè)具體的需求實(shí)踐了能解決問(wèn)題的爬蟲(chóng),豆瓣還是比較容易爬的,上面解析書(shū)目信息的做法還是很有意義的,當(dāng)然我是用xpath做的,如果用BeautifulSoup又會(huì)是另一種實(shí)現(xiàn)方式,但分析問(wèn)題->建立HTML樹(shù)的過(guò)程是通用的。上面的代碼還是比較簡(jiǎn)略的,沒(méi)有考慮過(guò)多的驗(yàn)證和異常處理,有任何意見(jiàn)或建議歡迎交流。

以上就是Python如何一鍵爬取你所關(guān)心的書(shū)籍信息,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

當(dāng)前名稱:Python如何一鍵爬取你所關(guān)心的書(shū)籍信息
分享路徑:http://jinyejixie.com/article38/gdgjpp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)品牌網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、面包屑導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開(kāi)發(fā)