摘要
伴随着当代社会物质水平的不断提高,人们越来越注重精神享受,看电影成为人们日常生活中重要的组成成分。本文将针对豆瓣上热门电影评论进行爬取,应用可视化分析更为形象地了解该电影的动态。该系统可以使得人们实时了解到有关该热门电影的部分信息。该系统基于python的各种库来实现,分为获取热点电影评分排名,评论获取,词云显示,可视化分析等模块。
1 系统开发背景
电影,在当今社会,作为人们在日常生活中重要的娱乐方式,已经发展出多种多样的形式,供人们体验电影所带来的乐趣。但是,人们在看完电影之后,往往会生出许多的感慨,或许是同情主人公的遭遇,或许是对于故事的情节十分感动,或许是对电影特效精彩的赞叹,总之,人们在看完一部电影后或多或少都会将自己的感触告诉他人,或者是想了解他人是否同自己一样对于相同的影片有同样的感受,因此,为了让更多的人可以方便地通过互联网相互之间交流对于电影的感想或是发布一些影评,或者可以从他人的影评中了解这部电影是否值得去看,于是,建立一个对于影评的搜索系统就显得很有必要了。
基于网络爬虫的搜索引擎研究与实现,在当今网络中已非常普及。目前比较流行的搜索引擎代表有谷歌,百度,搜狗等。合理地使用好算法抓取页面,才是网络爬虫实现的核心。
爬虫又被称为网页蜘蛛,网络机器人,是一种按照一定的规则,自动的抓取互联网中网页或者脚本,而影评搜索需要特定的收集,使得数据更加具有目的性。传统的爬虫是从一个或者多个初始url开始,不断的从当前页面抽取新的url进行搜索,直到满足一定条件才会停止。而聚集爬虫是根据一定的网页分析算法过滤于主体无关的链接,并将其放入等待抓取的url队列中,然后进行一定的分析,过滤,并建立索引,以便之后的查询和检索。网页的抓取策略可以分为深度优先,广度优先和最近优先三种。
2 系统相关技术介绍
本文主要是基于python语法和其强大的库来实现系统的多种功能。
2.1 Python语言
Python是一种计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。
Python在设计上坚持了清晰划一的风格,这使得Python成为一门易读、易维护,并且被大量用户所欢迎的、用途广泛的语言。
2.2 request库
Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库,是网络爬虫中及其重要的组成成分。
2.3 BeautifulSoup
BeautifulSoup是用来从HTML或XML中提取数据的Python库。
对于不具备良好格式的 HTML 内容,lxml 提供了两个有用的包:lxml.html 模块和 BeautifulSoup 解析器。
2.4 Matplotlib库
matplotlib是一个python的绘图库,它以各种硬拷贝格式和跨平台的交互式环境出版生成质量级别的图形,它能输出的图形包括折线图,散点图,直方图等,在数据可视化方面,matplotlib强悍的绘图能力能够帮助我们对数据形成非常清晰直观的认知。
2.5 numpy库
numpy是Python数值计算最重要的基础包,大多数提供科学计算的包都是用numpy的数组作为构建基础。numpy本身并没有提供多么高级的数据分析功能,理解numpy数组以及面向数组的计算,将有助于你更加高效地使用诸如Pandas之类的工具。
2.6 WordCloud库
wordcloud库,可以说是python非常优秀的词云展示第三方库。词云以词语为基本单位更加直观和艺术的展示文本。
wordcloud把词云当作一个对象,它可以将文本中词语出现的频率作为一个参数绘制词云,而词云的大小、颜色、形状等都是可以设定的。
2.7 pandas库
pandas是基于numpy的一种工具,该工具是为了解决数据分析任务而创建的。Pandas纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
2.8 csv库
CSV(Comma Separated Values)格式比较常见,python提供了csv模块去以csv格式读取和写入表格数据。
2.9 jieba库
Jieba库作用:
1、利用中文词库,分析汉字与汉字之间的关联几率
2、还有分析汉字词组的关联几率
3、还可以根据用户自定义的词组进行分析。是做词云图的关键。
3 系统分析与设计
3.1系统功能模块组成
本系统主要由热门电影排名、影评内容词云、观众满意度饼图等模块组成。
图1 系统功能模块图
3.2 获取每一部电影链接以及电影名、评分、评论数模块需求和设计
图2 豆瓣top250电影链接获取并获取电影名、评分和评论数等数据
如图2,页面中的每个电影名的信息都放在了< li>标签里,利用request库获取网页源代码,并且采用BeautifulSoup切割有用的信息,通过提取a标签中的href属性来获取每一部电影链接,得到该部电影特定的网页,使得下一步可以继续进行,提取电影名和评分、评论数等数据。
3.3 影评词云模块需求和设计
选择其中你想要获取的电影信息,通过id进入该页面。
词云模块的需求和分析分为两大部分:
(1)获取用户评论信息
获取用户评论先要了解用户评论在哪,点进去发现链接发生改变,所以我们要构造一个爬评论的链接,由上图可以发现,这个评论链接只要用前面的电影链接加上固定的后缀即可。
图3 获取用户评论信息
其次电影评论链接确定了之后,由图3可知,用户的评论信息都保存在了< p>标签中的< span>标签的class="short"属性中,通过request库进入该电影的评论界面,同时通过BeautifulSoup的简单处理获取评论的内容,同时保存用户名和评论时间,使其在列表中的位置能够一一对应,通过遍历在界面中展示出来。
(2)将用户评论利用词云表示出来
图4 实现词云展示分析
面对如此多的影评(图4),一些人自然想要知道观影者提及最多的词语是什么,这就自然需要充分发挥词云的作用。
要实现词云,则需使用python中常用的WordCloud、jieba、matplotlib.pyplot这三种库,其中前两者主要用于文字的获取处理,后者主要用于词云的显示。
通过这三类库的基本语法知识的有机结合,一个.png文件就由此生成了。
满意度饼图模块需求和设计
如今,选择一个电影的最简单直接的办法就是选择别人更喜欢看的,由此,满意度饼图可以清晰的表示出来观众对于某个电影的满意程度。
图5 满意度饼图分析
观众满意度显示和源代码如图5所示,通过BeautifulSoup获取某星和所占百分比将其提取成文本格式,然后用replace替换掉%,转换成浮点数,存为csv,通过pandas中DataFrame将读取csv数据,以文字作为label,数字作为values,在matplotlib.pyplot库的作用下使其在以饼图的形式显示出来。
3.4 不同类型电影不同年代嵌套饼图模块需求和设计
想知道目前电影那个年代、哪个时间段、哪种类型的电影最受欢迎,可以通过处理top250的电影数据,对数据按年代按类型进行分组统计,就能知道哪个年代的电影哪个类型的电影观众最喜欢。所以做一个不同年代不同类型的电影占比,就能解决。
图5-1类型及年代分析
类型及年代显示和源代码如图5-1所示,通过BeautifulSoup获取类型和上映年代将其提取成文本格式,然后用截取年份,转换成整型,存为csv,通过pandas中DataFrame将读取csv数据,使用pandas的groupby分组对其进行统计,以文字作为label,数字作为values,在matplotlib.pyplot库的作用下使其在以饼图的形式显示出来。
4系统实现
本部分将对系统每个模块的实现界面和核心代码进行介绍。……
4.1 获取电影排名模块实现
4.1.1 获取电影评分模块实现界面
电影评分的效果如图6所示:
图6 电影评分排名显示
4.1.2 获取电影评分排名模块实现代码
实现电影评分(图6)的源代码如下:
def top_neirong(list):
for k in list:
r1 = requests.get (k, headers=headers,proxies=proxy).text
soup1 = BeautifulSoup (r1, 'lxml')
movie_name1 = soup1.find ('h1').find ('span').text
movie_name= re.findall(findch,movie_name1)[0]
movie_pf = float(soup1.find ('strong', class_="ll rating_num").text)
movie_pls = int(soup1.find ('span', property="v:votes").text)
#柱形图
data3=data.values.tolist()
# 自定义每根柱子的颜色
colors = ["#4E79A7", "#A0CBE8", "#F28E2B", "#FFBE7D", "#59A14F", "#8CD17D", "#B6992D", "#F1CE63", "#499894", "#86BCB6"]
namedata=[]
datapf=[]
n=0
for i in data3:
if n>10:break
namedata.append(i[0])
datapf.append(i[1])
n+=1
x=namedata
y=datapf
plt.bar(range(len(namedata)), datapf, tick_label=namedata,color=colors)
plt.xlabel("影片名")
plt.ylabel("评分")
plt.show()
plt.savefig('电影排名评分前十柱形图.png',format="png")
4.2 影评词云模块实现
4.2.1 影评模块实现界面
观众影评词云由图7所示:
图7 词云影评显示
4.2.2 影评词云模块实现代码
影评词云(图7)源码如下所示:
def tcg(texts):
cut = jieba.cut(texts) #分词
string = ' '.join(cut)
return string
text = (open(path+r'肖申克的救赎.txt','r',encoding='utf-8')).read()
string=tcg(text)
img = Image.open('五角星.jpg') #打开图片
img_array = np.array(img) #将图片装换为数组
wc = WordCloud(
font_path='simhei.ttf', #字体路劲
background_color='white', #背景颜色
width=500,
height=300,
max_font_size=50, #字体大小
min_font_size=10,
mask=img_array, #背景图片
max_words=200
)
wc.generate_from_text(string)#绘制图片
plt.imshow(wc)
plt.axis('off')#隐藏坐标轴
plt.show() #显示图片
wc.to_file('豆瓣词云图.png') #保存图片
4.3 满意度饼图模块实现
4.2.1 满意度饼图模块实现界面
观众满意度饼图如图8所示:
图8 满意度饼图
4.2.2 满意度饼图模块实现代码
满意度饼图(图8)的源码可表示如下:
for k in list:
r1 = requests.get (k, headers=headers,proxies=proxy).text
soup1 = BeautifulSoup (r1, 'lxml')
movie_name1 = soup1.find ('h1').find ('span').text
movie_name= re.findall(findch,movie_name1)[0]
movie_pf = float(soup1.find ('strong', class_="ll rating_num").text)
movie_pls = int(soup1.find ('span', property="v:votes").text)
movie_time = int (soup1.find ('span', property="v:initialReleaseDate").text[:4])
movie_leixing = soup1.find ('span', property="v:genre").text
movie_starts5 = float(soup1.find_all ('span', class_="rating_per")[0].text.replace('%',''))
movie_starts4 = float(soup1.find_all ('span', class_="rating_per")[1].text.replace('%',''))
movie_starts3 = float(soup1.find_all ('span', class_="rating_per")[2].text.replace('%',''))
movie_starts2 = float(soup1.find_all ('span', class_="rating_per")[3].text.replace('%',''))
movie_starts1 = float(soup1.find_all ('span', class_="rating_per")[4].text.replace('%',''))
labels = ['5星','4星','3星','2星','1星']#转换成列表数据类型
data1=data.drop(columns=['电影名称','评分','评论数','上映时间','类型'])
data2=data1.iloc[0:1].values.tolist()[0]
explode=[0,0,0.3,0,0]
plt.pie(data2,explode=explode,labels=labels, radius=1,autopct='%.2f%%')
plt.title("观众满意度",fontsize = 10)
plt.show()
plt.savefig('观众满意度.png',format="png")
4.3.1 不同年代不同类型占比模块实现界面
4.3.2 不同年代不同类型占比模块实现
#嵌套饼图
data4=data.groupby(by=['类型'])['电影名称'].count().reset_index()
labels1 = data4['类型'].to_list()#转换成列表数据类型
data5=data[data['上映时间']<=1995]['电影名称'].count()
data6=data[data['上映时间']<=2000]['电影名称'].count()
data7=data[data['上映时间']<=2005]['电影名称'].count()
data8=data[data['上映时间']<=2010]['电影名称'].count()
data9=data[data['上映时间']<2015]['电影名称'].count()
data10=data[data['上映时间']>=2015]['电影名称'].count()
p1=data4['电影名称']
p2=[data5,data6-data5,data7-data6,data8-data7,data9-data8,data10]
plt.figure(figsize=(10,8))
#绘制外圆
plt.pie(p1, radius=1,autopct='%.2f%%',pctdistance=0.85,wedgeprops={'linewidth':5,'width':0.3,'edgecolor':'white'})
#绘制内圆
plt.pie(p2, radius=0.7,autopct='%.2f%%',pctdistance=0.85,wedgeprops={'linewidth':5,'width':0.3,'edgecolor':'white'})
plt.legend(labels1,
loc="center left",
bbox_to_anchor=(1, 0.2, 1, 1),
fontsize=20)
plt.title("不同上映时间不同类型的电影受欢迎程度",fontsize = 10)
plt.show()
plt.savefig('不同上映时间不同类型的受欢迎程度.png',format="png")
5 系统开发总结
该系统从观众和影片自身考虑,较为全面的向人们展示出该部影片的全部内容。从三个层面分析,结构简单,脉络清晰。在开发过程中自然遇到很多问题,通过查阅书籍,向同学求助,网上查询,这些问题都能够逐一解决。
当然,此系统还存在诸多不足之处,涉及反爬措施不足等,后续会加以完善。
参考文献
[1] 崔庆才.python3网络爬虫实战演练[M].北京:人民邮电出版社,2018: 4-7.
[2] 刘瑜.python零基础到项目实战[M].北京:中国水利水电出版社,2018: 10-1.
[3] 明日科技.python项目开发样例集锦[M].吉林:吉林大学出版社,2019: 3-1.
[4] 连晓峰.python强化实战[M].北京:机械工业出版社,2019: 1-1.
[5] 包永帅.python应用开发实战[M].北京:人民邮电出版社,2018: 6-1.
[6] 王国辉.python从入门到项目实战[M].吉林:吉林大学出版社,2018: 8-1.
备注:其中[D]指硕博士论文,[M]指杂志或书籍,[J]指学术期刊论文,[C]代表学术会议论文。