一、爬取豆瓣影评
基本思路:先获取每个电影的评论区链接,然后依次进入其评论区爬取评论。选取10部电影,每部200条评论。
用到的包为:BeautifulSoup,urllib
这里选取的链接为:豆瓣电影,打开后内容如下:
直接审查元素,找到每部电影的标签位置,如下图:
因此,找到此标签的代码为:
lists = bsobj.find('ul', {'class': 'lists'}).findAll('li', {'class': 'list-item'})
其中bsobj是该网页的bs对象。
接下来我们需要找到这部电影短评的链接,如下:
/subject/26985127/comments?status=P
这是短评首页,翻页观察其变化:
/subject/26985127/comments?start=20&limit=20&sort=new_score&status=P(第2页)
/subject/26985127/comments?start=40&limit=20&sort=new_score&status=P(第3页)
唯一变化的是start后的数字,一页有20条评论,subject后的数字是电影的id号,只要获取电影的id号,就可构造它的短评网页的url。
评论区的位置:
获取评论区标签的代码为:
comments=reviewBSobj.findAll('div',{'class':'comment-item'})
由于之后要对评论进行朴素贝叶斯,所以要给评论打上标签 。这里方便起见,对评分三星以上的为积极,标记为0,二星以下为消极,标记为1。
评分位置如图:
allstar后的数字30表示三星,爬取代码如下:
star=comment.find('span',{'class':pile(r'^allstar(.*?)')})
这里用到了正则表达式。另外,有的评论没有星级评分,打不了标签,因而直接丢弃。
if star is None:continue
if int(star['class'][0][7])>2:target=0else:target=1
target是标签,取值0或1。
在保存之前,先对数据进行简单的清洗:去掉标点符号以及特殊符号,只保留汉字。
content=comment.p.get_text().strip()pattern = pile(r'[\u4e00-\u9fa5]+')filterdata = re.findall(pattern, content)cleaned_comments = ''.join(filterdata)
content是评论的内容,pattern是正则表达式,cleaned_comments是清洗完的数据。
f = open('review.txt', 'w', encoding='utf-8')
数据保存在review.txt文件中。
1、代码解析
getbs4函数:返回bs对象
def getbs4(url):''':param url:网址:return: 返回BeautifulSoup对象'''try:html=urlopen(url)bsobj=BeautifulSoup(html,'html.parser')html.close()except (HTTPError,URLError):return Nonereturn bsobj
getFilmList函数:返回电影id列表
def getFilmList(url):''':param url:网址:return: 返回电影id的列表'''bsobj = getbs4(url)if bsobj == None: returnlists = bsobj.find('ul', {'class': 'lists'}).findAll('li', {'class': 'list-item'})return lists
getReview函数:爬取影评的主函数
def getReview(url,n):''':param n:需要爬取的爬取页数:return:爬取影评'''lists = getFilmList(url)print('电影总数:'+str(len(lists)))f = open('review.txt', 'w', encoding='utf-8')for i in range(1):print('开始爬取第%d电影,电影名为%s'%(i+1,lists[i]['data-title']))reviewUrl='/subject/'+lists[i]['id']+'/comments?status=P'text=[]for j in range(n):reviewBSobj = getbs4(reviewUrl)if reviewBSobj == None: returncomments=reviewBSobj.findAll('div',{'class':'comment-item'})print('-----第%d页-----' % (j+1))for comment in comments:star=comment.find('span',{'class':pile(r'^allstar(.*?)')})if star is None:continueprint(star)if int(star['class'][0][7])>2:target=0else:target=1content=comment.p.get_text().strip()pattern = pile(r'[\u4e00-\u9fa5]+')filterdata = re.findall(pattern, content)cleaned_comments = ''.join(filterdata)text.append(str(target)+' '+cleaned_comments+'\n')print('-------------')reviewUrl='/subject/'+lists[i]['id']+'/comments?start='+str(20*j+20)+'&limit=20&sort=new_score&status=P'f.writelines(text)f.close()