点击上方“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     def download(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             return response.json()11         else:12             # print(html.status_code)13             print('下载数据为空!')14             return ""

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

 1     def parse(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         except Exception as e:17             print(e)18 19         finally:20             return comments

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

1  def save(self, data):2         """写入文件"""3 4         print("保存数据,写入文件中...")5         self.save_file.write(data)

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

 1     def start(self): 2         """启动控制方法""" 3  4         print("爬虫开始...\r\n") 5  6         start_time = self.start_time 7         end_time = self.end_time 8  9         num = 110         while start_time > end_time:11             print("执行次数:", num)12             # 1、下载html13             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                 break23 24             # 3、写入文件25             res = ''26             for cmt in comments: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             # 休眠3s37             num += 138             time.sleep(3)39 40         self.save_file.close()41         print("爬虫结束...")
2.3 数据样本,最终爬取将近2万条数据,每条记录的每个数据使用 ### 进行分割:

三、图形化分析数据

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

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

 1     def createCharts(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     def createWordCloud(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         # 初始化 WordCloud23         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 None 8         """ 9         if name in self._coordinates:10             return self._coordinates[name]11 12 13         coordinate = get_coordinate(name, region=region)14 15         # [ 20181204 添加16         # print(name, coordinate)17         if coordinate is None:18             # 如果字典key匹配不上,尝试进行模糊查询19             search_res = search_coordinates_by_region_and_keyword(region, name)20             # print("###",search_res)21             if search_res:22                 coordinate = sorted(search_res.values())[0]23         # 20181204 添加 ]24 25         if coordinate is None and raise_exception:26             raise ValueError("No coordinate is specified for {}".format(name))27 28         return coordinate

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

五、附录-源码

5.1 采集源码
  1 # -*- coding:utf-8 -*-  2   3 import requests  4 from datetime import datetime, timedelta  5 import os  6 import time  7 import sys  8   9  10 class MaoyanFilmReviewSpider: 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 = url 21  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 not os.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     def download(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             return response.json() 46         else: 47             # print(html.status_code) 48             print('下载数据为空!') 49             return "" 50  51     def parse(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         except Exception as e: 67             print(e) 68  69         finally: 70             return comments 71  72     def save(self, data): 73         """写入文件""" 74  75         print("保存数据,写入文件中...") 76         self.save_file.write(data) 77  78     def start(self): 79         """启动控制方法""" 80  81         print("爬虫开始...\r\n") 82  83         start_time = self.start_time 84         end_time = self.end_time 85  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                 break100 101             # 3、写入文件102             res = ''103             for cmt in comments: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             # 休眠3s114             num += 1115             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     # 猫眼电影ID128     mid = sys.argv[1] # "1208282"  # "42964"129     # 电影上映日期130     end_time = sys.argv[2]  # "2018-11-16"  # "2018-11-09"131     # 每次爬取条数132     offset = 15133     # 保存文件名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))
5.2 分析制图源码
  1 # -*- coding:utf-8 -*-  2 from pyecharts import Geo, Bar, Bar3D  3 import jieba  4 from wordcloud import STOPWORDS, WordCloud  5 import matplotlib.pyplot as plt  6   7   8 class ACoolFishAnalysis:  9     """无名之辈 --- 数据分析""" 10     def __init__(self): 11         pass 12  13     def readCityNum(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] in d: 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 in d.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         return res 51  52     def readAllComments(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         return comments 76  77     def createCharts(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     def createWordCloud(self):110         """生成评论词云"""111         comments = self.readAllComments()  # 19185112 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         # 初始化 WordCloud131         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()

本文作者:蜗牛噢,原文链接:https://www.cnblogs.com/reader/p/10070629.html

 推荐阅读

Python人体肤色检测

【Python】动手分析天猫内衣售卖数据,得到你想知道的信息

python爬虫实战:利用scrapy,短短50行代码下载整站短视频

5 多数据save_[Python] 通过采集两万条数据,对无名之辈影评分析相关推荐

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

    一.说明 本文主要讲述采集猫眼电影用户评论进行分析,相关爬虫采集程序可以爬取多个电影评论. 运行环境:Win10/Python3.5. 分析工具:jieba.wordcloud.pyecharts.m ...

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

    一.说明 本文主要讲述采集猫眼电影用户评论进行分析,相关爬虫采集程序可以爬取多个电影评论. 运行环境:Win10/Python3.5. 分析工具:jieba.wordcloud.pyecharts.m ...

  3. 两万条数据需要做个数据图_第3关:基于Excel对电商母婴数据进行分析

    对于新手,拿到数据往往不知如何下手.那就按图索骥,依照以下五部一步步来 step1:明确问题 目标必须明确,基于当前业务出发.如一千个读者有一千个哈姆雷特一样,数据可以被解读出不同样子,必须集中目标, ...

  4. python多线程插入1万条数据

    前言 在业务中,经常碰到需要从外部批量读取数据然后导入到mysql等数据库的操作,通常情况下,我们使用一个insert语句就可以完成,但在数据量为上万甚至百万的时候,这样做是不是太耗时了呢? 下面我们 ...

  5. 利用python处理两千万条数据的一些经验(仅供自己记录)

    5.3老板交给我一个任务,简单处理一些数据,三个CSV文件,每个都是2.3G大小,以下是要求 看着觉得很easy,兴冲冲地去搞了,当时还是用的notepad++写python代码,对于python来说 ...

  6. 我们用Python分析了B站4万条数据评论,揭秘本山大叔《念诗之王》大热原因!...

    来源:恋习Python 本文约2000字,建议阅读10分钟. 我们通过Python大法通过获取B站:[春晚鬼畜]赵本山:我就是念诗之王!4万条数据评论,与大家一起看看其背后火起来的原因. 1990年本 ...

  7. Python 分析 9 万条数据告诉你复仇者联盟谁才是绝对 C 位!

    <复联 4>国内上映第十天,程序员的江湖里开始流传这样一个故事,即: 漫威宇宙,其实就讲了一件事情.整个宇宙就好比一个项目组.其中有一群叫作美国队长.钢铁侠.惊奇队长.浩克.索尔等人在维护 ...

  8. 爬取网易云音乐两万条评论储存在MySQL服务器上

    爬取网易云音乐两万条评论储存在MySQL服务器上 最近在公司实习,无聊时看看别人的博客,发现平时学习写写博客是一个很好的学习方法,报平时一些自己写的代码保存下来,遇到的错误踩到的坑也拿出来分享也可也帮 ...

  9. Python看春运,万条拼车数据背后的春节迁徙地图

    Python看春运,万条拼车数据背后的春节迁徙地图 今天是正月初九,春运返程也已过半.这篇文章,作者对北京.上海.广州.深圳.杭州等地 1万多条出行数据进行分析,得出了一些有意思的结论,并且绘制了这几 ...

最新文章

  1. android中PreferencesActivity的使用(一)
  2. T-SQL中的随机数
  3. block之--- 基本使用
  4. Cannot open D:\Program Files\Anaconda3\Scripts\pip-script.py 错误解决办法
  5. 迷你世界电锯机器人_迷你世界:会旋转的机器人,安装多个火箭炮,全方位轰炸敌人...
  6. linux清理内存命令
  7. AgileEAS.NET平台应用开发教程-案例计划
  8. redis通过expire设置存活期注意问题
  9. 前端笔记-JavaScript中放json数组要注意的地方(构造灵活的echarts)
  10. poj 1039 Pipe (判断 直线和 线段 是否相交 并 求交点)
  11. 【AD】PCB设计知识整理(持续更新)
  12. python代码中怎么增加数据_python 实现数据库中数据添加、查询与更新的示例代码...
  13. 吴恩达机器学习学习笔记第一章:绪论初识机器学习
  14. linux下目录简介——/proc
  15. 携程android app插件化
  16. 谈谈ILDasm的功能限制与解除
  17. csdn博客修改名字,不需要重新注册的。
  18. Excel:INDEX与MATCH函数
  19. win10打印机无法打印(怎样使用打印机打印)
  20. 1153: 简易版最长序列 C语言

热门文章

  1. 瑞幸咖啡 CEO 和 COO 被暂停职务;快手起诉抖音索赔 500 万元;Wine 5.8 发布 | 极客头条...
  2. 终于有人对语音技术来了次彻头彻尾的批判!
  3. “手把手撕LeetCode题目,扒各种算法套路的裤子”
  4. 罗永浩宣布进军电商直播;微博回应用户数据泄露;Android 11 开发者预览版 2 发布 | 极客头条...
  5. JavaScript 造就年薪超过 10 万美元的开发者们!
  6. 召唤新一代超参调优开源新神器,集十大主流模块于一身
  7. 百行代码解读阿里 AloT 芯片平台无剑 100!
  8. 别样的1024程序员节“无Bug市集”
  9. 作为新手程序员,掉过的那些坑!
  10. 阿里 90 后科学家研发,达摩院开源新一代 AI 算法模型