⽤python爬取⾖瓣某本书的前n条书评并计算评分(star)的平
均值
这个爬⾍⼩项⽬是中国⼤学MOOC的“”课程的⼀个课后作业,由南京⼤学张莉⽼师主讲,有兴趣的同学可以看⼀看。
虽然⽼师已经给出了参考代码,但由于⾖瓣读书⽹站已经改版,参考代码中的爬取⽅法已经不可⽤,所以我将源代码稍作修改,并使之模块
化,增强代码的可复⽤性。
爬取思路如下:
⾸先我们打开的任何⼀本书的书评页,这⾥以《Python编程从⼊门到实践(第2版)》为例。
在页⾯空⽩处右击⿏标选择“检查”查看⽹页的HTML代码(我⽤的是Edge浏览器,其他浏览器的操作⽅法也应该相似),点击左上⾓的
箭头按钮,可以查看页⾯中模块对应的代码位置,如下图所⽰:
我们可以看到,每⼀条书评都放在⼀个列表模块
也放在模块中,class属性是“ur-starsallstar40rating”,其中的数字40即表⽰评分,⼀颗星表⽰10分,四颗星就是40分。
如下图:
爬取思路是⽤Python的requests库获取⽹页的HTML,再通过BeautifulSoup库解析HTML获取相应的书评和评分信息。
我们再来看看书评页⾯的具体信息,发现每页只能显⽰20条书评,那如果我们想爬取多于20条的书评,是不是要通过爬取⼀个页⾯换⼀个
URL的“笨⽅法”呢?其实也不⽤,通过观察⽹页的URL可以发现,每个页⾯的URL只有"start="后⾯的数字不同,这个数字是控制页⾯从
第⼏条书评开始显⽰,第⼀页就是从第0条书评开始,第⼆页就是从第20条开始,我们可以把这个数字改成其他值,相应的页⾯就会从那⼀
条书评开始显⽰。
我们可以发现URL中还有⼀个参数limit,表⽰每⼀页显⽰的书评数,那我们可不可以把这个参数改成我们想要爬取的书评数⽬呢,这样我
们就能在⼀个页⾯中完成爬取,但很可惜,试了⼀下发现不⾏,⽆论怎么改还是只能显⽰20条书评。
但既然每个页⾯的URL只有start的参数不同,我们就可以通过⼀个while循环(python的for循环好像只能⽤来遍历⼀个迭代器)来爬取多
个页⾯。
为了代码的可复⽤性,我把这个项⽬分成信息获取和结果展⽰两个模块,分别定义两个函数getInfo(url,n)和showRst(),函数getInfo中
的两个参数表⽰要爬取的书评⽹页的URL和书评的数量。
下⾯是具体的代码:
#-*-coding:utf-8-*-
"""
CreatedonThuAug1217:43:452021
@discribe:douban_comments_spider
@author:86150
"""
#定义爬取信息的函数,其中参数url是爬取书评⾸页的地址,n是爬取书评的数量
defgetInfo(url,n):
#导⼊要⽤到的第三⽅库
importrequests
frombs4importBeautifulSoup
importre
importtime
count=0#⽤于记录书评数量的计数器
i=0#⽤于控制翻页的计数器
lis_comments=[]#⽤于存放书评内容的列表
lis_stars=[]#⽤于存放评分的列表
header={'Ur-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/91.0.4472.124Safari/537.36'}
#⽤于向服务器发送请求的头部信息
whilecount
url_n=('?')[0]+'?start='+str(i)+('?')[1]#调⽤字符串的split()⽅法,以'?'为分隔符将URL分成两个字符串,中间加⼊'?start='+str(i)字符串组成新的U
r=(url_n,headers=header)#调⽤requests的get()⽅法获取页⾯信息
soup=BeautifulSoup(,'lxml')#以'xml'格式解析
comments=_all('span','short')#调⽤soup对象的find_all⽅法获取具有“short”属性的所有span标签
pattern=e('
p=l(pattern,)#调⽤re的findall⽅法匹配HTML中的所有评分分数(star)
foritemincomments:
lis_()#调⽤append⽅法将每⼀条书评添加到列表中
forstarinp:
lis_(int(star))#调⽤append⽅法将每⼀条评分添加到列表中
count=len(lis_comments)#获取列表中的书评数⽬
i+=20#star数加上20,爬取下⼀个页⾯
(3)#根据⾖瓣⽹的robot协议,每访问⼀个页⾯停留3秒钟,以免被当作恶意爬⾍
returnlis_comments,lis_stars#返回书评和评分列表,便于被后⾯的函数调⽤
#定义显⽰结果的函数,其中参数num是想要显⽰的书评数量
defshowRst(num):
c,s=getInfo(url,n)#获取getInfo函数的返回值
print("前%d条书评如下:"%n)
foriinrange(num):
print(i+1,c[i])#打印出每⼀条书评及其序号
print('--------------------------------------------------------------')
print("前%d条评分的平均值为:"%len(s),sum(s)/len(s))#调⽤python的内部函数len()和sum(),计算评分的平均值
if__name__=="__main__":#程序的⼊⼝
url='/subject/35196328/comments/?&limit=20&status=P&sort=new_score'
n=100
num=80
getInfo(url,n)#调⽤getInfo函数获取前n条书评和评分,因为有些书评可能没有评分,所以评分数可能少于书评数
showRst(num)#showRst函数显⽰前num条书评和评分的平均值
代码中⽤到正则表达式来匹配字符串,下⾯是常⽤的正则表达式:
爬取结果如下:
Lifeisshort,IuPython.
本文发布于:2023-02-27 22:15:51,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/1677507351121.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:书评网.doc
本文 PDF 下载地址:书评网.pdf
留言与评论(共有 0 条评论) |