爬取猫眼电影《一出好戏》数据并分析
一、获取数据
1. 简介
本次获取的是猫眼APP的评论数据,如图所示:
通过分析发现猫眼APP的评论数据接口为:
http://m.maoyan.com/mmdb/comments/movie/1203084.json?_v_=yes&offset=0&startTime=2018-08-23%2014%3A25%3A03
通过对评论数据进行分析,得到如下信息:
-
返回的是json格式数据
-
1203084表示电影的专属id;offset表示偏移量;startTime表示获取评论的起始时间,从该时间向前取数据,即获取最新的评论 -
cmts表示评论,每次获取15条,offset偏移量是指每次获取评论时的起始索引,向后取15条
-
hcmts表示热门评论前10条
- total表示总评论数
2. 代码实现
这里先定义一个函数,用来根据指定url获取数据,且只能获取到指定的日期向前获取到15条评论数据
# coding=utf-8
__author__ = 'likx'from urllib import request
import json
import time
from datetime import datetime
from datetime import timedelta# 获取数据,根据url获取
def get_data(url):headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36'}req = request.Request(url, headers=headers)response = request.urlopen(req)if response.getcode() == 200:return response.read()return None# 处理数据
def parse_data(html):data = json.loads(html)['cmts'] # 将str转换为jsoncomments = []for item in data:comment = {'id': item['id'],'nickName': item['nickName'],'cityName': item['cityName'] if 'cityName' in item else '', # 处理cityName不存在的情况'content': item['content'].replace('\n', ' ', 10), # 处理评论内容换行的情况'score': item['score'],'startTime': item['startTime']}comments.append(comment)return comments# 存储数据,存储到文本文件
def save_to_txt():start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 获取当前时间,从当前时间向前获取end_time = '2018-08-10 00:00:00'while start_time > end_time:url = 'http://m.maoyan.com/mmdb/comments/movie/1203084.json?_v_=yes&offset=0&startTime=' + start_time.replace(' ', '%20')html = None'''问题:当请求过于频繁时,服务器会拒绝连接,实际上是服务器的反爬虫策略解决:1.在每个请求间增加延时0.1秒,尽量减少请求被拒绝2.如果被拒绝,则0.5秒后重试'''try:html = get_data(url)except Exception as e:time.sleep(0.5)html = get_data(url)else:time.sleep(0.1)comments = parse_data(html)print(comments)start_time = comments[14]['startTime'] # 获得末尾评论的时间start_time = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') + timedelta(seconds=-1) # 转换为datetime类型,减1秒,避免获取到重复数据start_time = datetime.strftime(start_time, '%Y-%m-%d %H:%M:%S') # 转换为strfor item in comments:with open('comments.txt', 'a', encoding='utf-8') as f:f.write(str(item['id'])+','+item['nickName'] + ',' + item['cityName'] + ',' + item['content'] + ',' + str(item['score'])+ ',' + item['startTime'] + '\n')if __name__ == '__main__':# html = get_data('http://m.maoyan.com/mmdb/comments/movie/1203084.json?_v_=yes&offset=0&startTime=2018-07-28%2022%3A25%3A03')# comments = parse_data(html)# print(comments)save_to_txt()
三、存储数据
为了能够获取到所有评论数据,方法是:从当前时间开始,向前获取数据,根据url每次获取15条,然后得到末尾评论的时间,从该时间继续向前获取数据,直到影片上映日期(2018-08-10)为止,获取这之间的所有数据。
有两点需要说明:
- 服务器一般都有反爬虫策略,当请求过于频繁时,服务器会拒绝部分连接,我这里是通过增加每个请求间延时来解决,只是一种简单的解决方案,还望各位看客理解包涵
- 根据数据量的多少,抓取数据所需时间会有所不同,我抓取的是2018-8-23到2018-8-10(上映当天)之间的数据,大概花了1个小时,共抓取十多万条评论数据
四、数据可视化
这里使用的是pyecharts,pyecharts是一个用于生成Echarts图表的类库,便于在Python中根据数据生成可视化的图表。
Echarts是百度开源的一个数据可视化JS库,主要用于数据可视化。
参考:http://pyecharts.org/
# coding=utf-8
__author__ = 'likx'# 导入Style类,用于定义样式风格
from pyecharts import Style
# 导入Geo组件,用于生成地理坐标类图
from pyecharts import Geo
import json
# 导入Geo组件,用于生成柱状图
from pyecharts import Bar
# 导入Counter类,用于统计值出现的次数
from collections import Counter
# 处理地名数据,解决坐标文件中找不到地名的问题
def handle(cities):# print(len(cities), len(set(cities)))# 获取坐标文件中所有地名data = Nonewith open('C:/Users/Administrator/PycharmProjects/Likexin/venv/lib/site-packages/pyecharts/datasets/city_coordinates.json',mode='r', encoding='utf-8') as f:data = json.loads(f.read()) # 将str转换为json# 循环判断处理data_new = data.copy() # 拷贝所有地名数据for city in set(cities): # 使用set去重# 处理地名为空的数据if city == '':while city in cities:cities.remove(city)count = 0for k in data.keys():count += 1if k == city:breakif k.startswith(city): # 处理简写的地名,如 达州市 简写为 达州# print(k, city)data_new[city] = data[k]breakif k.startswith(city[0:-1]) and len(city) >= 3: # 处理行政变更的地名,如县改区 或 县改市等data_new[city] = data[k]break# 处理不存在的地名if count == len(data):while city in cities:cities.remove(city)# print(len(data), len(data_new))# 写入覆盖坐标文件with open('C:/Users/Administrator/PycharmProjects/Likexin/venv/lib/site-packages/pyecharts/datasets/city_coordinates.json',mode='w', encoding='utf-8') as f:f.write(json.dumps(data_new, ensure_ascii=False)) # 将json转换为str# 数据可视化
def render():# 获取评论中所有城市cities = []with open('comments.txt', mode='r', encoding='utf-8') as f:rows = f.readlines()for row in rows:print(row)city = row.split(',')[2]if city != '': # 去掉城市名为空的值cities.append(city)# 对城市数据和坐标文件中的地名进行处理handle(cities)# 统计每个城市出现的次数# data = []# for city in set(cities):# data.append((city, cities.count(city)))data = Counter(cities).most_common() # 使用Counter类统计出现的次数,并转换为元组列表# print(data)# 定义样式style = Style(title_color='#fff',title_pos='center',width=1200,height=600,background_color='#404a59')# 根据城市数据生成地理坐标图geo = Geo('《一出好戏》粉丝位置分布', '数据来源:猫眼电影-likx采集', **style.init_style)attr, value = geo.cast(data)geo.add('', attr, value, visual_range=[0, 3500],visual_text_color='#fff', symbol_size=15,is_visualmap=True, is_piecewise=True, visual_split_number=10)geo.render('粉丝位置分布-地理坐标图.html')# 根据城市数据生成柱状图data_top20 = Counter(cities).most_common(20) # 返回出现次数最多的20条bar = Bar('《一出好戏》粉丝来源排行TOP20', '数据来源:猫眼电影-likx采集', title_pos='center', width=1200, height=600)attr, value = bar.cast(data_top20)bar.add('', attr, value, is_visualmap=True, visual_range=[0, 3500], visual_text_color='#fff', is_more_utils=True,is_label_show=True)bar.render('粉丝来源排行-柱状图.html')if __name__ == '__main__':render()
可视化结果:
粉丝人群主要集中在沿海一带
从上图可以看出,《一出好戏》的观影人群主要集中在沿海一带,这些地方经济相对发达,城市人口基数庞大,极多的荧幕数量和座位、极高密度的排片场次,让观众便捷观影,活跃的观众评论也多,自然也就成为票房的主要贡献者。
粉丝来源排名前20的城市依次为:北京、上海、深圳、成都、西安、武汉、广州、南京、郑州、沈阳、天津、重庆、长沙、青岛、哈尔滨、杭州、东莞、合肥、无锡、
电影消费是城市消费的一部分,从某种角度来看,可以作为考察一个城市购买力的指标。这些城市在近年的GDP排行中大都居上游,消费水平较高。
2. 词云图
jieba是一个基于Python的分词库,完美支持中文分词,功能强大
# coding=utf-8
__author__ = 'likx'# 导入Pie组件,用于生成饼图
from pyecharts import Pie# 获取评论中所有评分
rates = []
with open('comments.txt', mode='r', encoding='utf-8') as f:rows = f.readlines()for row in rows:rates.append(row.split(',')[4])
# print(rates)# 定义星级,并统计各星级评分数量
attr = ['五星', '四星', '三星', '二星', '一星']
value = [rates.count('5') + rates.count('4.5'),rates.count('4') + rates.count('3.5'),rates.count('3') + rates.count('2.5'),rates.count('2') + rates.count('1.5'),rates.count('1') + rates.count('0.5')
]
# print(value)pie = Pie('《一出好戏》评分星级比例', title_pos='center', width=900)
pie.add('7-17', attr, value, center=[75, 50], is_random=True,radius=[30, 75], rosetype='area',is_legend_show=False, is_label_show=True)
pie.render('评分.html')
可视化结果:
四、五星级影评合计高达83%

从图中可以看出,五星比例接近62%,四星比例为21%,两者合计高达83%,可见口碑还是相当不错的,一星占比不足6%
《一出好戏》作为黄渤第一次执导的作品,在拍摄过程中导演渤哥对自己的要求也是很严格的,所以有这样的成绩,也是理所当然。

http://blog.51cto.com/12402007/2161698?wx=
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
