豆瓣影评分析
任务具体描述如下:
1)豆瓣电影(https://movie.douban.com/)评论情感分类,要求爬取豆瓣电影中不同电影的评论及其评分(星星数),以评论作为输入,评论分类别作为输出,进行情感分类实验(1-2颗星为“负面”、3颗星为“中性”、4-6颗星为“正面”),最后以合适的方式展示结果。
模型分两步1.爬虫2.模型搭建
1.爬虫
这里爬的是热门的电影(评论更具有代表性,能得到的种类更平衡)爬虫具体也分两块,先来看看怎么从一部电影中爬取影评
https://movie.douban.com/subject/26871906/comments?status=P
以上面这部电影为例
谷歌浏览器F12打开审查,然后可以看到评论在,是在下面所以这里就直接使用python的requests,和BeautifulSoup可以完成对网页的爬取。代码如下这里要记得加入header因为豆瓣是反爬的,具体的header根据每个浏览器不同而不同,大家可以网上自行查找。
import requests
from bs4 import BeautifulSoup as bs4
url="https://movie.douban.com/subject/26871906/comments?status=P"
re = requests.get(url)
print(re)
re.encoding='utf-8'
soup = bs4(re.text,'lxml')
k=soup.find_all('div','comment-item')
for i in k:
comment = i.find('span',class_='short')
print(comment)
爬取成功后是这样的,但是这里只有20条(每页都只有20条),所以我们要翻页去查看下面的评论。
https://movie.douban.com/subject/26871906/comments?start=20&limit=20&sort=new_score&status=P (这个是第二页的网址)
https://movie.douban.com/subject/26871906/comments?start=0&limit=20&sort=new_score&status=P
这个是第一页的网址
显而易见只有start不一样,所以我们只要更改start就好了,给上面的爬虫加一段循环。如下所示
import requests
from bs4 import BeautifulSoup as bs4
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
l=[]
for i in range(20):
url="https://movie.douban.com/subject/26871906/comments?start="+str(i*20)+"&limit=20&sort=new_score&status=P"
re = requests.get(url,headers=header)#后续的cooikes加入后即可允许。
re.encoding='utf-8'
soup = bs4(re.text,'lxml')
k=soup.find_all('div','comment-item')
for j in k:
comment = j.find('span',class_='short')
l.append(comment.string)
print(len(l))#输出以下我们爬了多少评论(会发现只有220条)
我们循环了20页应该有400条评论,但实际上只有220,是因为豆瓣只允许没登陆下用户看前11页评论,所以我们需要记录以下我们的登陆状态,这个简单,给我们的爬虫加一个cookies。具体方法可以自行搜索,添加后可以正常访问任意页码的评论。
这里来到了第二部分的问题,我们只爬取了一部电影的代码,远远不够,还要别的电影。我们去首页上看。有一点先提前说一下,每部电影的网址都只有ID号是不一样的,所以我们只需要获取每部电影的ID即可。
这里在首页上我们该如何获取每部电影的ID呢?因为ID是动态加载的,所以我们没有办法像上面一样直接爬这样爬下来都是空的。动态链接获取方式:
我们切换到network中,然后看一下这几个文件,都打开他们发现我们要的数据都在第三个文件中
这个图中就有数据的ID,等等,所以这个网页就很关键了,观察一下,有一个page_start=0所以我们就可以像上次一样的方法来控制想要爬取的页数。解决这个问题之后,代码实现就简单了
#获取电影ID,并且储存在l1中
l1=[]
for i in range(0,10):
value=i*20
ur='https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start='+str(value)
res=requests.get(ur,headers=header).json()
for j in range(0,20):
dic=res['subjects'][j]['id']
l1.append(dic)
print(l1)
取出电影ID后问题就简单了,我们还需要爬取电影的星星作为训练的标签。这里用正则筛选一下即可,直接给代码。
import requests
from bs4 import BeautifulSoup
import re
str1='allstar[5|4|3|2|1]0 rating'
p=re.compile(str1)
header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
f=open(r"H:\desktop\data\new_comment.txt","r+")
cookies={'cookie':'这里加上你自己的cookies'}
#获取电影ID,并且储存在l1中
l1=[]
for i in range(0,10):
value=i*20
ur='https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start='+str(value)
res=requests.get(ur,headers=header).json()
for j in range(0,20):
dic=res['subjects'][j]['id']
l1.append(dic)
for k in range(0,30):
j=k*20#每页20个评论
for i in range(len(l1)):
#根据电影ID获得电影评论网址
url = 'https://movie.douban.com/subject/'+str(l1[i])+'/comments?start=%s&limit=20&sort=new_score&status=P'%str(j)
req = requests.get(url,cookies = cookies,headers=header)
req.encoding='utf-8'
soup = BeautifulSoup(req.text,'lxml')
comment_set=soup.find_all('div','comment-item')
for item in comment_set:
judge = item.find('span',{'class':p})
m=re.search(r'[1|2|3|4|5]',str(judge))#使用正则表达式匹配星星评分数
comment = item.find('span',{'class':'short'})
if(comment):
pattern = re.compile(r'[\u4e00-\u9fa5]+')#使用正则筛选出中文的评论
filterdata = re.findall(pattern,comment.string)
clean_data= ''.join(filterdata)
if(m and clean_data!=''):
score=int(m.group(0)) #将星星转化为情感标签
if score==5 or score==4:
str1="正面"
elif score==3:
str1="中性"
elif score==1 or score==2:
str1="负面"
tmp = str1+"\t"+clean_data#这里最好用\t制表符隔开,不要用空格,这样之后读也方便
tmp=tmp+"\n"
f.write(tmp) #写入到文件中
f.close()
爬取结束后我们的数据就被存到了文件中。爬出来大概是这个样子(我这里就没爬了使用了之前的数据集)
2.模型搭建
模型搭建上使用了三个模型(贝叶斯,keras,和逻辑回归)别问我为什么用,就是不求甚解。
贝叶斯
概念就不说了,上一下代码实现。
首先贝叶斯需要特征值,那么特征值的来源就是评论,我们需要将评论转化为特征值,这里其实也没有特别的需要用到一个包(jieba)没下载的同学可以自行pip 下载(用国内得镜像可能会快一点),这个分词本质上就是把句子拆成一个个词语,那么显而易见得一个问题来了,就是有些词是没有真实含义得,我们就得把他剔除掉,所以还需要一个停词包,有了停词包之后我们就完成了特征值得转换,但是于此同时我们还得筛选掉一些无用得特征值比如说出现过高和过低得词语,删除之后才算完成了特征值提取。
简而言两个步骤:1.分词;2.剔词(停用词,词频过高或者过低得词)得到特征值之后直接可以调用sklearn中得贝叶斯模型进行训练。(注意这里有三个贝叶斯模型:选取得是多项式贝叶斯-适用于离散多元得情况)
Bert句向量和keras结合
这个参考了一个简书上一个博主得文章
首先说一下Bert就是将一个句子转化成一个向量,向量可以被计算机模型识别所以就可以用来训练了类似于word2vec。可以去下载中文训练过的模型,然后打开服务器就可以使用了,使用keras的时候需要一些下载一下包tensorflow之类的网上都有教程(不过跑得挺慢得)
逻辑回归模型
这个和贝叶斯干的差不多,也需要提取出所有得特征值,然后构造一个词袋使用逻辑模型进行训练预测得到结果。
从老师那儿得到得意见就是,贝叶斯得特征值还可以接着筛选,不止停用词可以剔除,一些名词也可以剔除,从而得到和情感分析相关,准确率会更高。关于Bert的话需要自己根据自己得语料训练之后才能得到提升准确率。逻辑回归模型的话同贝叶斯对词袋筛选仍然有问题。
还有一点是自己得问题,爬取得评论有些就是牛头不对马嘴得注水评论,所以在爬取得时候可以看一下评论得质量,对质量进行一个筛选再来使用,还有就是数据集得到得话还可以再多点,可以考虑对数据进行加强,增加数据得信息表示。留几个坑,等自己有能力了再来解决。
这几个模型代码就不给了,准确率不高有点丢人现眼(实在需要得可以留邮箱或者私信我看到了会发得=.=)and网上有很多文章可以用来参考,放一下几个模型得准确率。
贝叶斯:
Keras:
逻辑回归:
这次实验大概做了2~3天(应付一下课设作业),需要完善得等有机会再来!!