基于python的影评数据分析_[Python] 通过采集两万条数据,对《无名之辈》影评分析...

一、说明

本文主要讲述采集猫眼电影用户评论进行分析,相关爬虫采集程序可以爬取多个电影评论。

运行环境:Win10/Python3.5。

分析工具:jieba、wordcloud、pyecharts、matplotlib。

基本流程:下载内容 ---> 分析获取关键数据 ---> 保存本地文件 ---> 分析本地文件制作图表

注意:本文所有图文和源码仅供学习,请勿他用,转发请注明出处!

本文主要参考:https://mp.weixin.qq.com/s/mTxxkwRZPgBiKC3Sv-jo3g

二、开始采集

2.1、分析数据接口:

为了健全数据样本,数据直接从移动端接口进行采集,连接如下,其中橙色部分为猫眼电影ID,修改即可爬取其他电影。

链接地址:http://m.maoyan.com/mmdb/comments/movie/1208282.json?v=yes&offset=15&startTime=

接口返回的数据如下,主要采集(昵称、城市、评论、评分和时间),用户评论在json['cmts'] 中:

2.2、爬虫程序核心内容(详细可以看后面源代码):

>启动脚本需要的参数如下(脚本名+猫眼电影ID+上映日期+数据保存的文件名):.\myMovieComment.py 1208282 2016-11-16 myCmts2.txt

>下载html内容:download(self, url),通过python的requests模块进行下载,将下载的数据转成json格式

1 defdownload(self, url):2 """下载html内容"""

3

4 print("正在下载URL:"+url)5 #下载html内容

6 response = requests.get(url, headers=self.headers)7

8 #转成json格式数据

9 if response.status_code == 200:10 returnresponse.json()11 else:12 #print(html.status_code)

13 print('下载数据为空!')14 return ""

>然后就是对已下载的内容进行分析,就是取出我们需要的数据:

1 defparse(self, content):2 """分析数据"""

3

4 comments =[]5 try:6 for item in content['cmts']:7 comment ={8 'nickName': item['nickName'], #昵称

9 'cityName': item['cityName'], #城市

10 'content': item['content'], #评论内容

11 'score': item['score'], #评分

12 'startTime': item['startTime'], #时间

13 }14 comments.append(comment)15

16 exceptException as e:17 print(e)18

19 finally:20 return comments

>将分析出来的数据,进行本地保存,方便后续的分析工作:

1 defsave(self, data):2 """写入文件"""

3

4 print("保存数据,写入文件中...")5 self.save_file.write(data)

> 爬虫的核心控制也即爬虫的程序启动入口,管理上面几个方法的有序执行:

1 defstart(self):2 """启动控制方法"""

3

4 print("爬虫开始...\r\n")5

6 start_time =self.start_time7 end_time =self.end_time8

9 num = 1

10 while start_time >end_time:11 print("执行次数:", num)12 #1、下载html

13 content = self.download(self.target_url +str(start_time))14

15 #2、分析获取关键数据

16 comments = ''

17 if content != "":18 comments =self.parse(content)19

20 if len(comments) <=0:21 print("本次数据量为:0,退出爬取!\r\n")22 break

23

24 #3、写入文件

25 res = ''

26 for cmt incomments:27 res += "%s###%s###%s###%s###%s\n" % (cmt['nickName'], cmt['cityName'], cmt['content'], cmt['score'], cmt['startTime'])28 self.save(res)29

30 print("本次数据量:%s\r\n" %len(comments))31

32 #获取最后一条数据的时间 ,然后减去一秒

33 start_time = datetime.strptime(comments[len(comments) - 1]['startTime'], "%Y-%m-%d %H:%M:%S") + timedelta(seconds=-1)34 #start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")

35

36 #休眠3s

37 num += 1

38 time.sleep(3)39

40 self.save_file.close()41 print("爬虫结束...")

2.3 数据样本,最终爬取将近2万条数据,每条记录的每个数据使用 ### 进行分割:

三、图形化分析数据

3.1、制作观众城市分布热点图,(pyecharts-geo):

从图表可以轻松看出,用户主要分布地区,主要以沿海一些发达城市群为主:

1 defcreateCharts(self):2 """生成图表"""

3

4 #读取数据,格式:[{"北京", 10}, {"上海",10}]

5 data =self.readCityNum()6

7 #1 热点图

8 geo1 = Geo("《无名之辈》观众位置分布热点图", "数据来源:猫眼,Fly采集", title_color="#FFF", title_pos="center", width="100%", height=600, background_color="#404A59")9

10 attr1, value1 =geo1.cast(data)11

12 geo1.add("", attr1, value1, type="heatmap", visual_range=[0, 1000], visual_text_color="#FFF", symbol_size=15, is_visualmap=True, is_piecewise=False, visual_split_number=10)13 geo1.render("files/无名之辈-观众位置热点图.html")14

15 #2 位置图

16 geo2 = Geo("《无名之辈》观众位置分布", "数据来源:猫眼,Fly采集", title_color="#FFF", title_pos="center", width="100%", height=600,17 background_color="#404A59")18

19 attr2, value2 =geo1.cast(data)20 geo2.add("", attr2, value2, visual_range=[0, 1000], visual_text_color="#FFF", symbol_size=15,21 is_visualmap=True, is_piecewise=False, visual_split_number=10)22 geo2.render("files/无名之辈-观众位置图.html")23

24 #3、top20 柱状图

25 data_top20 = data[:20]26 bar = Bar("《无名之辈》观众来源排行 TOP20", "数据来源:猫眼,Fly采集", title_pos="center", width="100%", height=600)27 attr, value =bar.cast(data_top20)28 bar.add('', attr, value, is_visualmap=True, visual_range=[0, 3500], visual_text_color="#FFF", is_more_utils=True, is_label_show=True)29 bar.render("files/无名之辈-观众来源top20.html")30

31 print("图表生成完成")

3.2、制作观众人数TOP20的柱形图,(pyecharts-bar):

3.3、制作评论词云,(jieba、wordcloud):

生成词云核心代码:

1 defcreateWordCloud(self):2 """生成评论词云"""

3 comments = self.readAllComments() #19185

4

5 #使用 jieba 分词

6 commens_split = jieba.cut(str(comments), cut_all=False)7 words = ''.join(commens_split)8

9 #给词库添加停止词

10 stopwords =STOPWORDS.copy()11 stopwords.add("电影")12 stopwords.add("一部")13 stopwords.add("无名之辈")14 stopwords.add("一部")15 stopwords.add("一个")16 stopwords.add("有点")17 stopwords.add("觉得")18

19 #加载背景图片

20 bg_image = plt.imread("files/2048_bg.png")21

22 #初始化 WordCloud

23 wc = WordCloud(width=1200, height=600, background_color='#FFF', mask=bg_image, font_path='C:/Windows/Fonts/STFANGSO.ttf', stopwords=stopwords, max_font_size=400, random_state=50)24

25 #生成,显示图片

26 wc.generate_from_text(words)27 plt.imshow(wc)28 plt.axis('off')29 plt.show()

四、修改pyecharts源码

4.1、样本数据的城市简称与数据集完整城市名匹配不上:

使用位置热点图时候,由于采集数据城市是一些简称,与pyecharts的已存在数据的城市名对不上,所以对源码进行一些修改,方便匹配一些简称。

黔南 => 黔南布依族苗族自治州

模块自带的全国主要市县经纬度在:[python安装路径]\Lib\site-packages\pyecharts\datasets\city_coordinates.json

由于默认情况下,一旦城市名不能完全匹配就会报异常,程序会停止,所以对源码修改如下(报错方法为 Geo.add()),其中添加注析为个人修改部分:

1 def get_coordinate(self, name, region="中国", raise_exception=False):2 """

3 Return coordinate for the city name.4

5 :param name: City name or any custom name string.6 :param raise_exception: Whether to raise exception if not exist.7 :return: A list like [longitude, latitude] or None8 """

9 if name inself._coordinates:10 returnself._coordinates[name]11

12

13 coordinate = get_coordinate(name, region=region)14

15 #[ 20181204 添加

16 #print(name, coordinate)

17 if coordinate isNone:18 #如果字典key匹配不上,尝试进行模糊查询

19 search_res =search_coordinates_by_region_and_keyword(region, name)20 #print("###",search_res)

21 ifsearch_res:22 coordinate =sorted(search_res.values())[0]23 #20181204 添加 ]

24

25 if coordinate is None andraise_exception:26 raise ValueError("No coordinate is specified for {}".format(name))27

28 return coordinate

相应的需要对 __add()方法进行如下修改:

五、附录-源码

*说明:源码为本人所写,数据来源为猫眼,全部内容仅供学习,拒绝其他用途!转发请注明出处!

5.1 采集源码

1 #-*- coding:utf-8 -*-

2

3 importrequests4 from datetime importdatetime, timedelta5 importos6 importtime7 importsys8

9

10 classMaoyanFilmReviewSpider:11 """猫眼影评爬虫"""

12

13 def __init__(self, url, end_time, filename):14 #头部

15 self.headers ={16 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'

17 }18

19 #目标URL

20 self.target_url =url21

22 #数据获取时间段,start_time:截止日期,end_time:上映时间

23 now =datetime.now()24

25 #获取当天的 零点

26 self.start_time = now + timedelta(hours=-now.hour, minutes=-now.minute, seconds=-now.second)27 self.start_time = self.start_time.replace(microsecond=0)28 self.end_time = datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")29

30 #打开写入文件, 创建目录

31 self.save_path = "files/"

32 if notos.path.exists(self.save_path):33 os.makedirs(self.save_path)34 self.save_file = open(self.save_path + filename, "a", encoding="utf-8")35

36 defdownload(self, url):37 """下载html内容"""

38

39 print("正在下载URL:"+url)40 #下载html内容

41 response = requests.get(url, headers=self.headers)42

43 #转成json格式数据

44 if response.status_code == 200:45 returnresponse.json()46 else:47 #print(html.status_code)

48 print('下载数据为空!')49 return ""

50

51 defparse(self, content):52 """分析数据"""

53

54 comments =[]55 try:56 for item in content['cmts']:57 comment ={58 'nickName': item['nickName'], #昵称

59 'cityName': item['cityName'], #城市

60 'content': item['content'], #评论内容

61 'score': item['score'], #评分

62 'startTime': item['startTime'], #时间

63 }64 comments.append(comment)65

66 exceptException as e:67 print(e)68

69 finally:70 returncomments71

72 defsave(self, data):73 """写入文件"""

74

75 print("保存数据,写入文件中...")76 self.save_file.write(data)77

78 defstart(self):79 """启动控制方法"""

80

81 print("爬虫开始...\r\n")82

83 start_time =self.start_time84 end_time =self.end_time85

86 num = 1

87 while start_time >end_time:88 print("执行次数:", num)89 #1、下载html

90 content = self.download(self.target_url +str(start_time))91

92 #2、分析获取关键数据

93 comments = ''

94 if content != "":95 comments =self.parse(content)96

97 if len(comments) <=0:98 print("本次数据量为:0,退出爬取!\r\n")99 break

100

101 #3、写入文件

102 res = ''

103 for cmt incomments:104 res += "%s###%s###%s###%s###%s\n" % (cmt['nickName'], cmt['cityName'], cmt['content'], cmt['score'], cmt['startTime'])105 self.save(res)106

107 print("本次数据量:%s\r\n" %len(comments))108

109 #获取最后一条数据的时间 ,然后减去一秒

110 start_time = datetime.strptime(comments[len(comments) - 1]['startTime'], "%Y-%m-%d %H:%M:%S") + timedelta(seconds=-1)111 #start_time = datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")

112

113 #休眠3s

114 num += 1

115 time.sleep(3)116

117 self.save_file.close()118 print("爬虫结束...")119

120

121 if __name__ == "__main__":122 #确保输入参数

123 if len(sys.argv) != 4:124 print("请输入相关参数:[moveid]、[上映日期]和[保存文件名],如:xxx.py 42962 2018-11-09 text.txt")125 exit()126

127 #猫眼电影ID

128 mid = sys.argv[1] #"1208282" # "42964"

129 #电影上映日期

130 end_time = sys.argv[2] #"2018-11-16" # "2018-11-09"

131 #每次爬取条数

132 offset = 15

133 #保存文件名

134 filename = sys.argv[3]135

136 spider = MaoyanFilmReviewSpider(url="http://m.maoyan.com/mmdb/comments/movie/%s.json?v=yes&offset=%d&startTime=" % (mid, offset), end_time="%s 00:00:00" % end_time, filename=filename)137 #spider.start()

138

139 spider.start()140 #t1 = "2018-11-09 23:56:23"

141 #t2 = "2018-11-25"

142 #143 #res = datetime.strptime(t1, "%Y-%m-%d %H:%M:%S") + timedelta(days=-1)

144 #print(type(res))

MaoyanFilmReviewSpider.py

5.2 分析制图源码

1 #-*- coding:utf-8 -*-

2 from pyecharts importGeo, Bar, Bar3D3 importjieba4 from wordcloud importSTOPWORDS, WordCloud5 importmatplotlib.pyplot as plt6

7

8 classACoolFishAnalysis:9 """无名之辈 --- 数据分析"""

10 def __init__(self):11 pass

12

13 defreadCityNum(self):14 """读取观众城市分布数量"""

15 d ={}16

17 with open("files/myCmts2.txt", "r", encoding="utf-8") as f:18 row =f.readline()19

20 while row != "":21 arr = row.split('###')22

23 #确保每条记录长度为 5

24 while len(arr) < 5:25 row +=f.readline()26 arr = row.split('###')27

28 #记录每个城市的人数

29 if arr[1] ind:30 d[arr[1]] += 1

31 else:32 d[arr[1]] = 1 #首次加入字典,为 1

33

34 row =f.readline()35

36

37 #print(len(comments))

38 #print(d)

39

40 #字典 转 元组数组

41 res =[]42 for ks ind.keys():43 if ks == "":44 continue

45 tmp =(ks, d[ks])46 res.append(tmp)47

48 #按地点人数降序

49 res = sorted(res, key=lambda x: (x[1]),reverse=True)50 returnres51

52 defreadAllComments(self):53 """读取所有评论"""

54 comments =[]55

56 #打开文件读取数据

57 with open("files/myCmts2.txt", "r", encoding="utf-8") as f:58 row =f.readline()59

60 while row != "":61 arr = row.split('###')62

63 #每天记录长度为 5

64 while len(arr) < 5:65 row +=f.readline()66 arr = row.split('###')67

68 if len(arr) == 5:69 comments.append(arr[2])70

71 #if len(comments) > 20:

72 #break

73 row =f.readline()74

75 returncomments76

77 defcreateCharts(self):78 """生成图表"""

79

80 #读取数据,格式:[{"北京", 10}, {"上海",10}]

81 data =self.readCityNum()82

83 #1 热点图

84 geo1 = Geo("《无名之辈》观众位置分布热点图", "数据来源:猫眼,Fly采集", title_color="#FFF", title_pos="center", width="100%", height=600, background_color="#404A59")85

86 attr1, value1 =geo1.cast(data)87

88 geo1.add("", attr1, value1, type="heatmap", visual_range=[0, 1000], visual_text_color="#FFF", symbol_size=15, is_visualmap=True, is_piecewise=False, visual_split_number=10)89 geo1.render("files/无名之辈-观众位置热点图.html")90

91 #2 位置图

92 geo2 = Geo("《无名之辈》观众位置分布", "数据来源:猫眼,Fly采集", title_color="#FFF", title_pos="center", width="100%", height=600,93 background_color="#404A59")94

95 attr2, value2 =geo1.cast(data)96 geo2.add("", attr2, value2, visual_range=[0, 1000], visual_text_color="#FFF", symbol_size=15,97 is_visualmap=True, is_piecewise=False, visual_split_number=10)98 geo2.render("files/无名之辈-观众位置图.html")99

100 #3、top20 柱状图

101 data_top20 = data[:20]102 bar = Bar("《无名之辈》观众来源排行 TOP20", "数据来源:猫眼,Fly采集", title_pos="center", width="100%", height=600)103 attr, value =bar.cast(data_top20)104 bar.add('', attr, value, is_visualmap=True, visual_range=[0, 3500], visual_text_color="#FFF", is_more_utils=True, is_label_show=True)105 bar.render("files/无名之辈-观众来源top20.html")106

107 print("图表生成完成")108

109 defcreateWordCloud(self):110 """生成评论词云"""

111 comments = self.readAllComments() #19185

112

113 #使用 jieba 分词

114 commens_split = jieba.cut(str(comments), cut_all=False)115 words = ''.join(commens_split)116

117 #给词库添加停止词

118 stopwords =STOPWORDS.copy()119 stopwords.add("电影")120 stopwords.add("一部")121 stopwords.add("无名之辈")122 stopwords.add("一部")123 stopwords.add("一个")124 stopwords.add("有点")125 stopwords.add("觉得")126

127 #加载背景图片

128 bg_image = plt.imread("files/2048_bg.png")129

130 #初始化 WordCloud

131 wc = WordCloud(width=1200, height=600, background_color='#FFF', mask=bg_image, font_path='C:/Windows/Fonts/STFANGSO.ttf', stopwords=stopwords, max_font_size=400, random_state=50)132

133 #生成,显示图片

134 wc.generate_from_text(words)135 plt.imshow(wc)136 plt.axis('off')137 plt.show()138

139

140

141 if __name__ == "__main__":142 demo =ACoolFishAnalysis()143 demo.createWordCloud()

View Code

你可能感兴趣的:(基于python的影评数据分析)