Python语言流行到现在,目前最受开发者喜爱的功能莫过于它的爬虫功能,以至于很多人以为Python的英语发音也是“爬虫”,其实它是读作“啪善”[‘paɪθɑn] 。而爬取网络信息,只是它的一个功能,它同时也涉及其它领域,比如说现在比较流行的人工智能、科学计算、网络开发等。而在爬取网络信息这个任务中,常用的是使用urllib库和bs4库打开网站并解析页面信息并分析,本文所要介绍的爬取豆瓣影评也是使用这两个库。另外,为了能形象的展示爬取的结果,在项目最后,使用了WordCloud词云对爬取的关键字进行了显示,在显示前,用jieba分词工具提取了影评中常用的关键字。
项目开始前,要做一些必要的准备,比如Python环境的安装,库的下载等。本项目是在Windows下运行,所以首先要在Windows下安装Python。由于这个过程比较简单,在本文中就不做介绍。Python安装完后,需要安装本项目所用的第三方库。如果python的基本环境安装完了,第三方库安装也很简单,直接使用pip工具即可下载安装(前提是机器必须能够连网):
由于本机已经在写文章之前安装过库,所以系统提示已经存在;如果没有安装过,运行“pip install xxx”的命令时可以看到下载和安装的过程及进度。其它所需的第三方库都可以使用此方法下载。环境和库准备完成后,就可以进行代码的实现了。
本项目的主要实现过程分为两个阶段,第一部分先获取豆瓣上某个电影的影评信息;第二部分通过jieba分词和WordCloud把结果用词云的方式展示出来。
Step:获取豆瓣影评,放到文本文件中:
使用python爬取网络信息,最基本的概念就是用urllib等工具打开网站,获取网页信息,然后对所需的信息进行解析并提取感兴趣的内容。在这个过程中,难点在于解析网页内容并获取感兴趣的内容。由于不同的网站页面结构是不一样的,所以需要针对特定的网页结构实现特定的解析代码。在代码实现之前,需要分析网页的内容。
从上面的图片可以看出,爬取之前首先要获取网页的url,通过url才能获得特定的网页内容用于解析。幸运的是,豆瓣上对于特定影片的影评的获取地址格式是固定的,比如:
https://movie.douban.com/subject/4920389/comments?start=1&limit=20&sort=new_score&status=P
这个网址中,https://movie.douban.com/subject/是固定的,后面的“26787574”是影片的ID,是豆瓣给定的编号,它对于特定的影片也是固定的,比如这个网址中的ID对应的就是最近得分比较高的《头号玩家》,我们可以通过打开特定的页面提前获得这个ID;对于网址后的start参数,很明显能分析出,它是对应的影评的编号是从第一条影评开始,limit表示一页显示的影评条数,这是默认值,不可修改;sort表示按照最新的热门评论排序;status表示显示看过这个电影的网友的评论,没有看过这个电影的网友写的评论就不显示了。
网址分析完成后,就要开始解析网页结构了,我们需要通过分析网页结构,得到页面上图片中红色方框标出的影评内容,忽略所有其它内容。这个过程需要一定的html的知识。
我们首先借助chrome浏览器的开发者工具功能分析一下这个网页的html代码,然后找到影评所对应的项:
通过分析页面html代码,可以知道,评论内容在comment目录下对应的’p’字段中,所以我们后面解析的代码就要提取这部分的内容。
由于每部电影可能会有很多页的影评,我们不打算提取所有内容,只抓取最新的200条就可以,所以在处理网址的时候可以做循环处理,一次抓取20条,抓10页就可以。
每条影评的内容得到后,我们把它放到一个特定的文本文件中,比如content.txt中,便于后面使用jieba分词并用词云显示。
Step:从文本文件读取内容,分词后并显示
内容抓取后,剩下的就是解析并显示了。这部分代码对任何文本文件都是适用的。比如,我们不光可以分析影评,也可以分析歌词,新闻关键字等。
Jieba分词库的功能非常强大,其中常用的就是它的cut函数,它可以把给定的文本中整句或整段的文章,按照中文常用的单词进行切分,便于后续对关键字进行分析。另外WordCloud也是一个很棒的功能,能够以好看的样式显示出词云的形状,并根据每个词出现的频率,以不同的文字大小显示。词云图轮廓有’circle’, ‘cardioid’, ‘diamond’, triangle-forward’, ‘triangle’, ‘pentagon’, ‘star’可选,分别代表‘圆形’,‘心形’,‘菱形’,‘向前三角形’,‘向上三角形’,‘五边形’,‘星形’。
在获取到每个词的词频后,显示词云之前,有一个对词频进行排序的过程。由于关键词和词频是由字典组成的,所以排序时用到了sorted函数,把关键字按照词频由大到小进行排列。具体的实现过程,请参考下面的代码:
#-----------------------------------------------------------------------------
# Name: douban.py
# Purpose: 读取豆瓣上关于某个电影的评论,并用词云显示出来
#
# Author: ISS-XiangjianChen
#
# Created: 16/04/2018
# Copyright: (c) ISS 2018
#-------------------------------------------------------------------------------
import urllib.request
import jieba
from bs4 import BeautifulSoup as bs
import re
from pyecharts import WordCloud
#获取评论放一个文本文件中
#名 ID
#阿甘正传 1292720
#无问西东 6874741
#红海行动 26861685
#捉妖记2 26575103
def GetTxt(start):
eachCommentList = []
requrl = 'https://movie.douban.com/subject/26787574/comments?start='+ \
str(start) + '&limit=20&sort=new_score&status=P'
resp = urllib.request.urlopen(requrl)
html_data = resp.read().decode('utf-8')
soup = bs(html_data, 'html.parser')
comment_div_lits = soup.find_all('div', class_='comment')
for item in comment_div_lits:
if item.find_all('p')[0].string is not None:
eachCommentList.append(item.find_all('p')[0].string)
#写到文本文件中
f = open('content.txt','a',encoding='utf-8')
for comment in eachCommentList:
f.write(comment)
f.close()
#从文本文件中生成词云
def Generator():
with open('content.txt', 'r', encoding='utf-8') as f:
text_body = f.read()
f.close()
#使用jieba进行分词
words_lst = jieba.cut(text_body.replace('\n', '').replace(' ', ''))
#统计词频
total = {}
for i in words_lst:
total[i] = total.get(i, 0) + 1
#按词频进行排序,只选取包含两个或两个以上字的词
data = dict(sorted({k: v for k, v in total.items() if len(k) >= 2}.items(),\
key=lambda x: x[1], reverse=True)[:200])
name = data.keys()
value = [i for i in data.values()]#获取列表对象
#构造一个词云对象,把所有的词放进去
word_cloud = WordCloud(width=1600, height=1024)
#pentagon表示用五角星的形状显示词云
word_cloud.add("", name, value, word_size_range=[20, 100], shape='triangle')
#把词云显示到一个html网页中
word_cloud.render('content.html')
def main():
for i in range(1,201,20):
GetTxt(i)
Generator()
if __name__ == '__main__':
main()
最终的词云显示效果如下图:
Created by 陈祥俭