300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 用python实现一个豆瓣通用爬虫(登陆 爬取 可视化分析)

用python实现一个豆瓣通用爬虫(登陆 爬取 可视化分析)

时间:2023-07-23 17:47:05

相关推荐

用python实现一个豆瓣通用爬虫(登陆 爬取 可视化分析)

点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

主人下马客在船,举酒欲饮无管弦。

前言

在本人上的一门课中,老师对每个小组有个任务要求,介绍和完成一个小模块、工具知识的使用。然而我所在的组刚好遇到的是python爬虫的小课题。

心想这不是很简单嘛,搞啥呢?想着去搞新的时间精力可能不太够,索性自己就把豆瓣电影的评论(短评)搞一搞吧。

之前有写过哪吒那篇类似的,但今天这篇要写的像姨母般详细。本篇主要实现的是对任意一部电影短评(热门)的抓取以及可视化分析。也就是你只要提供链接和一些基本信息,他就可以

分析

对于豆瓣爬虫,what shold we 考虑?怎么分析呢?豆瓣电影首页

这个首先的话尝试就可以啦,打开任意一部电影,这里以姜子牙为例。打开姜子牙你就会发现它是非动态渲染的页面,也就是传统的渲染方式,直接请求这个url即可获取数据。但是翻着翻着页面你就会发现:未登录用户只能访问优先的界面,登录的用户才能有权限去访问后面的页面。

所以这个流程应该是 登录——> 爬虫——>存储——>可视化分析。

这里提一下环境和所需要的安装装,环境为python3,代码在win和linux可成功跑,如果mac和linux不能跑友字体乱码问题还请私我。其中pip用到包如下,直接用清华 镜像下载不然很慢很慢(够贴心不)。

pipinstallrequests-ihttps://pypi.tuna./simplepipinstallmatplotlib-ihttps://pypi.tuna./simplepipinstallnumpy-ihttps://pypi.tuna./simplepipinstallxlrd-ihttps://pypi.tuna./simplepipinstallxlwt-ihttps://pypi.tuna./simplepipinstallbs4-ihttps://pypi.tuna./simplepipinstalllxml-ihttps://pypi.tuna./simplepipinstallwordcloud-ihttps://pypi.tuna./simplepipinstalljieba-ihttps://pypi.tuna./simple

登录

豆瓣的登录地址

进去后有个密码登录栏,我们要分析在登录的途中发生了啥,打开F12控制台是不够的,我们还要使用Fidder抓包。

打开F12控制台然后点击登录,多次试探之后发现登录接口也很简单:

查看请求的参数发现就是普通请求,无加密,当然这里可以用fidder进行抓包,这里我简单测试了一下用错误密码进行测试。如果失败的小伙伴可以尝试手动登陆再退出这样再跑程序。

这样编写登录模块的代码:

url='/j/mobile/login/basic'header={'user-agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/73.0.3683.86Safari/537.36','Referer':'/passport/login_popup?login_source=anony','Origin':'','content-Type':'application/x-www-form-urlencoded','x-requested-with':'XMLHttpRequest','accept':'application/json','accept-encoding':'gzip,deflate,br','accept-language':'zh-CN,zh;q=0.9','connection':'keep-alive','Host':''}data={'ck':'','name':'','password':'','remember':'false','ticket':''}deflogin(username,password):globaldatadata['name']=usernamedata['password']=passworddata=urllib.parse.urlencode(data)print(data)req=requests.post(url,headers=header,data=data,verify=False)cookies=requests.utils.dict_from_cookiejar(req.cookies)print(cookies)returncookies

这块高清之后,整个执行流程大概为:

爬取

成功登录之后,我们就可以携带登录的信息访问网站为所欲为的爬取信息了。虽然它是传统交互方式,但是每当你切换页面时候会发现有个ajax请求。

这部分接口我们可以直接拿到评论部分的数据,就不需要请求整个页面然后提取这部分的内容了。而这部分的url规律和之前分析的也是一样,只有一个start表示当前的条数在变化,所以直接拼凑url就行。

也就是用逻辑拼凑url一直到不能正确操作为止。

/subject/25907124/comments?percent_type=&start=0&其他参数省略/subject/25907124/comments?percent_type=&start=20&其他参数省略/subject/25907124/comments?percent_type=&start=40&其他参数省略

对于每个url访问之后如何提取信息呢?

我们根据css选择器进行筛选数据,因为每个评论他们的样式相同,在html中就很像一个列表中的元素一样。

再观察我们刚刚那个ajax接口返回的数据刚好是下面红色区域块,所以我们直接根据class搜素分成若干小组进行曹祖就可以。

在这里插入图片描述

在具体的实现上,我们使用requests发送请求获取结果,使用BeautifulSoup去解析html格式文件。

而我们所需要的数据也很容易分析对应部分。

实现的代码为:

importrequestsfrombs4importBeautifulSoupurl='/subject/25907124/comments?percent_type=&start=0&limit=20&status=P&sort=new_score&comments_only=1&ck=C7di'header={'user-agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/73.0.3683.86Safari/537.36',}req=requests.get(url,headers=header,verify=False)res=req.json()#返回的结果是一个jsonres=res['html']soup=BeautifulSoup(res,'lxml')node=soup.select('.comment-item')forvainnode:name=va.a.get('title')star=va.select_one('.comment-info').select('span')[1].get('class')[0][-2]comment=va.select_one('.short').textvotes=va.select_one('.votes').textprint(name,star,votes,comment)

这个测试的执行结果为:

image-220333519

储存

数据爬取完就要考虑存储,我们将数据储存到cvs中。

使用xlwt将数据写入excel文件中,xlwt基本应用实例:

importxlwt#创建可写的workbook对象workbook=xlwt.Workbook(encoding='utf-8')#创建工作表sheetworksheet=workbook.add_sheet('sheet1')#往表中写内容,第一个参数行,第二个参数列,第三个参数内容worksheet.write(0,0,'bigsai')#保存表为test.xlsxworkbook.save('test.xlsx')

使用xlrd读取excel文件中,本案例xlrd基本应用实例:

importxlrd#读取名称为test.xls文件workbook=xlrd.open_workbook('test.xls')#获取第一张表table=workbook.sheets()[0]#打开第1张表#每一行是个元组nrows=table.nrowsforiinrange(nrows):print(table.row_values(i))#输出每一行

到这里,我们对登录模块+爬取模块+存储模块就可把数据存到本地了,具体整合的代码为:

importrequestsfrombs4importBeautifulSoupimporturllib.parseimportxlwtimportxlrd#账号密码deflogin(username,password):url='/j/mobile/login/basic'header={'user-agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/73.0.3683.86Safari/537.36','Referer':'/passport/login_popup?login_source=anony','Origin':'','content-Type':'application/x-www-form-urlencoded','x-requested-with':'XMLHttpRequest','accept':'application/json','accept-encoding':'gzip,deflate,br','accept-language':'zh-CN,zh;q=0.9','connection':'keep-alive','Host':''}#登陆需要携带的参数data={'ck':'','name':'','password':'','remember':'false','ticket':''}data['name']=usernamedata['password']=passworddata=urllib.parse.urlencode(data)print(data)req=requests.post(url,headers=header,data=data,verify=False)cookies=requests.utils.dict_from_cookiejar(req.cookies)print(cookies)returncookiesdefgetcomment(cookies,mvid):#参数为登录成功的cookies(后台可通过cookies识别用户,电影的id)start=0w=xlwt.Workbook(encoding='ascii')##创建可写的workbook对象ws=w.add_sheet('sheet1')#创建工作表sheetindex=1#表示行的意思,在xls文件中写入对应的行数whileTrue:#模拟浏览器头发送请求header={'user-agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/73.0.3683.86Safari/537.36',}#trycatch尝试,一旦有错误说明执行完成,没错误继续进行try:#拼凑url每次star加20url='/subject/'+str(mvid)+'/comments?start='+str(start)+'&limit=20&sort=new_score&status=P&comments_only=1'start+=20#发送请求req=requests.get(url,cookies=cookies,headers=header)#返回的结果是个json字符串通过req.json()方法获取数据res=req.json()res=res['html']#需要的数据在`html`键下soup=BeautifulSoup(res,'lxml')#把这个结构化html创建一个BeautifulSoup对象用来提取信息node=soup.select('.comment-item')#每组class均为comment-item这样分成20条记录(每个url有20个评论)forvainnode:#遍历评论name=va.a.get('title')#获取评论者名称star=va.select_one('.comment-info').select('span')[1].get('class')[0][-2]#星数好评votes=va.select_one('.votes').text#投票数comment=va.select_one('.short').text#评论文本print(name,star,votes,comment)ws.write(index,0,index)#第index行,第0列写入indexws.write(index,1,name)#第index行,第1列写入评论者ws.write(index,2,star)#第index行,第2列写入评星ws.write(index,3,votes)#第index行,第3列写入投票数ws.write(index,4,comment)#第index行,第4列写入评论内容index+=1exceptExceptionase:#有异常退出print(e)breakw.save('test.xls')#保存为test.xls文件if__name__=='__main__':username=input('输入账号:')password=input('输入密码:')cookies=login(username,password)mvid=input('电影的id为:')getcomment(cookies,mvid)

执行之后成功存储数据:

可视化分析

我们要对评分进行统计、词频统计。还有就是生成词云展示。而对应的就是matplotlibWordCloud库。

实现的逻辑思路:读取xls的文件,将评论使用分词处理统计词频,统计出现最多的词语制作成直方图和词语。将评星????数量做成饼图展示一下,主要代码均有注释,具体的代码为:

其中代码为:

importmatplotlib.pyplotaspltimportmatplotlibimportjiebaimportjieba.analyseimportxlwtimportxlrdfromwordcloudimportWordCloudimportnumpyasnpfromcollectionsimportCounter#设置字体有的linux字体有问题matplotlib.rcParams['font.sans-serif']=['SimHei']matplotlib.rcParams['axes.unicode_minus']=False#类似comment为评论的一些数据[['1','名称','star星','赞同数','评论内容'],['2','名称','star星','赞同数','评论内容']]元组defanylasescore(comment):score=[0,0,0,0,0,0]#分别对应012345分出现的次数count=0#评分总次数forvaincomment:#遍历每条评论的数据['1','名称','star星','赞同数','评论内容']try:score[int(va[2])]+=1#第3列为star星要强制转换成int格式count+=1exceptExceptionase:continueprint(score)label='1分','2分','3分','4分','5分'color='blue','orange','yellow','green','red'#各类别颜色size=[0,0,0,0,0]#一个百分比数字合起来为100explode=[0,0,0,0,0]# explode :(每一块)离开中心距离;foriinrange(1,5):#计算size[i]=score[i]*100/countexplode[i]=score[i]/count/10pie=plt.pie(size,colors=color,explode=explode,labels=label,shadow=True,autopct='%1.1f%%')forfontinpie[1]:font.set_size(8)fordigitinpie[2]:digit.set_size(8)plt.axis('equal')#该行代码使饼图长宽相等plt.title(u'各个评分占比',fontsize=12)#标题plt.legend(loc=0,bbox_to_anchor=(0.82,1))#图例#设置legend的字体大小leg=plt.gca().get_legend()ltext=leg.get_texts()plt.setp(ltext,fontsize=6)plt.savefig("score.png")#显示图plt.show()defgetzhifang(map):#直方图二维,需要x和y两个坐标x=[]y=[]fork,vinmap.most_common(15):#获取前15个最大数值x.append(k)y.append(v)Xi=np.array(x)#转成numpy的坐标Yi=np.array(y)width=0.6plt.rcParams['font.sans-serif']=['SimHei']#用来正常显示中文标签plt.figure(figsize=(8,6))#指定图像比例:8:6plt.bar(Xi,Yi,width,color='blue',label='热门词频统计',alpha=0.8,)plt.xlabel("词频")plt.ylabel("次数")plt.savefig('zhifang.png')plt.show()returndefgetciyun_most(map):#获取词云#一个存对应中文单词,一个存对应次数x=[]y=[]fork,vinmap.most_common(300):#在前300个常用词语中x.append(k)y.append(v)xi=x[0:150]#截取前150个xi=''.join(xi)#以空格``将其分割为固定格式(词云需要)print(xi)#backgroud_Image=plt.imread('')#如果需要个性化词云#词云大小,字体等基本设置wc=WordCloud(background_color="white",width=1500,height=1200,#min_font_size=40,#mask=backgroud_Image,font_path="simhei.ttf",max_font_size=150,#设置字体最大值random_state=50,#设置有多少种随机生成状态,即有多少种配色方案)#字体这里有个坑,一定要设这个参数。否则会显示一堆小方框wc.font_path="simhei.ttf"#黑体#wc.font_path="simhei.ttf"my_wordcloud=wc.generate(xi)#需要放入词云的单词,这里前150个单词plt.imshow(my_wordcloud)#展示my_wordcloud.to_file("img.jpg")#保存xi=''.join(x[150:300])#再次获取后150个单词再保存一张词云my_wordcloud=wc.generate(xi)my_wordcloud.to_file("img2.jpg")plt.axis("off")defanylaseword(comment):#这个过滤词,有些词语没意义需要过滤掉list=['这个','一个','不少','起来','没有','就是','不是','那个','还是','剧情','这样','那样','这种','那种','故事','人物','什么']print(list)commnetstr=''#评论的字符串c=Counter()#python一种数据集合,用来存储字典index=0forvaincomment:seg_list=jieba.cut(va[4],cut_all=False)##jieba分词index+=1forxinseg_list:iflen(x)>1andx!='\r\n':#不是单个字并且不是特殊符号try:c[x]+=1#这个单词的次数加一except:continuecommnetstr+=va[4]for(k,v)inc.most_common():#过滤掉次数小于5的单词ifv<5orkinlist:c.pop(k)continue#print(k,v)print(len(c),c)getzhifang(c)#用这个数据进行画直方图getciyun_most(c)#词云#print(commnetstr)defanylase():data=xlrd.open_workbook('test.xls')#打开xls文件table=data.sheets()[0]#打开第i张表nrows=table.nrows#若干列的一个集合comment=[]foriinrange(nrows):comment.append(table.row_values(i))#将该列数据添加到元组中#print(comment)anylasescore(comment)anylaseword(comment)if__name__=='__main__':anylase()

我们再来查看一下执行的效果:

这里我选了姜子牙和千与千寻电影的一些数据,两个电影评分比例对比为:

从评分可以看出明显千与千寻好评度更高,大部分人愿意给他五分。基本算是最好看的动漫之一了,再来看看直方图的词谱:

很明显千与千寻的作者更出名,并且有很大的影响力,以至于大家纷纷提起他。再看看两者词云图:

白龙、婆婆,真的是满满的回忆,好了不说了,有啥想说的欢迎讨论!

-------------------End-------------------

往期精彩文章推荐:

手把手教你使用Flask搭建ES搜索引擎(实战篇)

手把手教你用Python进行SSH暴力破解

手把手教你用Python网络爬虫获取壁纸图片

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。