Python 爬取猫眼数据分析《无名之辈》为何能逆袭成黑马?

谢谢大家点开这篇文章,话说最近的天气开始冷了,为了避免换季感冒,小编只能裹着大毛毯上班了,大家也要注意保暖呦,这个季节感冒太不好受了,爱你们哟,比心比心。

作者 | 罗昭成

责编 | 唐小引

出品 | CSDN(ID:CSDNNews)

有部国产电影因好评及口碑传播而开始异军突起以黑马之势逆袭,在朋友圈以及微博上都会不时看到相关内容,那便是由陈建斌、任素汐等主演的《无名之辈》。这样一部没有什么特别大牌或流量明星,甚至名称与海报都没有什么特色的国产电影却引起了很多人的注意,更是在评分上直接将同期的如《毒液》、《神奇动物:格林德沃之罪》给 PK 了下去。这部剧从 16 日上映到现在,豆瓣评分 8.3 分,其中 5 星好评占 34.8%,而在猫眼上好评则直接超过了 50%。看这个数据,还是一部不错的国产剧。在一个貌似平常的日子,笔者用着一台低配的 Mac 电脑跑了一下《无名之辈》猫眼的评论数据,来看看这部小成本喜剧片究竟值不值得看。

为什么要用猫眼的数据,而不用豆瓣的?主要还是因为豆瓣是直接渲染的 HTML,而猫眼的数据是 JSON,处理起来比较方便。

获取猫眼接口数据

对各种抓包简直是信手拈来。在 Chrome 中查看原代码的模式,可以很清晰地看到接口,接口地址即为:

http://m.maoyan.com/mmdb/comments/movie/1208282.json?_v_=yes&offset=15

我们可以很方便地使用 request来发送网络请求,进而拿到返回结果:

defgetMoveinfo(url): session = requests.Session() headers = {"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X)" } response = session.get(url, headers=headers)if response.status_code == 200:return response.textreturnNone

我们能拿到此接口的返回数据,数据内容有很多信息,但有很多信息是我们并不需要的,先来总体看看返回的数据:

借钱都要看的一部电影。","filmView":false,"id":1045570589,"isMajor":false,"juryLevel":0,"majorType":0,"movieId":1208282,"nick":"nick","nickName":"nickName","oppose":0,"pro":false,"reply":0,"score":5,"spoiler":0,"startTime":"2018-11-22 23:52:58","supportComment":true,"supportLike":true,"sureViewed":1,"tagList":{"fixed":[ {"id":1,"name":"好评" }, {"id":4,"name":"购票" } ] },"time":"2018-11-22 23:52","userId":1871534544,"userLevel":2,"videoDuration":0,"vipInfo":"","vipType":0 } ]}

我们感兴趣的只有以下这几个字段:

nickName,cityName,content,startTime,score

进行我们比较重要的数据处理,从拿到的JSON 数据中解析出需要的字段:

defparseInfo(data): data = json.loads(html)['cmts']for item in data:yield{'date':item['startTime'],'nickname':item['nickName'],'city':item['cityName'],'rate':item['score'],'conment':item['content'] }

我们就可以开始数据分析了。但是为了避免频繁地去猫眼请求数据,需要将数据存储起来,在这里,笔者使用的是 SQLite3,放到数据库中,更加方便后续的处理。存储数据的代码如下:

defsaveCommentInfo(moveId, nikename, comment, rate, city, start_time)conn = sqlite3.connect('unknow_name.db')conn.text_factory=strcursor = conn.cursor()ins="insertintocommentsvalues(?,?,?,?,?,?)"v = (moveId, nikename, comment, rate, city, start_time)cursor.execute(ins,v)cursor.close()conn.commit()conn.close()

数据处理

因此可以直接使用 SQL 来查询自己想要的结果,比如评论前五的城市都有哪些:

SELECT city, count(*) rate_count FROM comments GROUP BY city ORDER BY rate_count DESC LIMIT 5

结果如下:

我们可以看出来,来自北京的评论数最多。

还可以使用更多的 SQL 语句来查询想要的结果。比如每个评分的人数、所占的比例等。如笔者有兴趣,可以尝试着去查询一下数据,就是如此地简单。

我们使用 Pyecharts 这个库来进行数据可视化展示。

按照地理位置,直接使用 Pyecharts 来在中国地图上展示数据:

data = pd.read_csv(f,sep='{',header=None,encoding='utf-8',names=['date','nickname','city','rate','comment'])city = data.groupby(['city'])city_com = city['rate'].agg(['mean','count'])city_com.reset_index(inplace=True)data_map = [(city_com['city'][i],city_com['count'][i]) for i in range(0,city_com.shape[0])]geo = Geo("GEO 地理位置分析",title_pos = "center",width = 1200,height = 800)whileTrue:try: attr,val = geo.cast(data_map) geo.add("",attr,val,visual_range=[0,300],visual_text_color="#fff", symbol_size=10, is_visualmap=True,maptype='china')except ValueError as e: e = e.message.split("No coordinate is specified for ")[1] data_map = filter(lambda item: item[0] != e, data_map)else :breakgeo.render('geo_city_location.html')

有一些猫眼数据中的城市找不到对应的从标,所以在代码中,GEO 添加出错的城市,我们将其直接删除,过滤掉了不少的数据。

就是如此简单地生成了如下地图:

既看电影又评论的人群主要分布在中国东部,又以北京、上海、成都、深圳最多。虽然能从图上看出来很多数据,但还是不够直观,如果想看到每个省/市的分布情况,我们还需要进一步处理数据。

城市包含数据中具备县城的数据,所以需要将拿到的数据做一次转换,将所有的县城转换到对应省市里去,然后再将同一个省市的评论数量相加,得到最后的结果。

defgetRealName(name, jsonObj):for item in jsonObj:if item.startswith(name) :return jsonObj[item]return namedefrealKeys(name):return name.replace(u"省", "").replace(u"市", "") .replace(u"回族自治区", "").replace(u"维吾尔自治区", "") .replace(u"壮族自治区", "").replace(u"自治区", "")

使用 Pyecharts 提供的 map 来生成一个按省/市来展示的地图:

defgenerateMap(data_map): map = Map("城市评论数", width= 1200, height = 800, title_pos="center")whileTrue:try: attr,val = geo.cast(data_map) map.add("",attr,val,visual_range=[0,800], visual_text_color="#fff",symbol_size=5, is_visualmap=True,maptype='china', is_map_symbol_show=False,is_label_show=True,is_roam=False, )except ValueError as e: e = e.message.split("No coordinate is specified for ")[1] data_map = filter(lambda item: item[0] != e, data_map)else :break map.render('city_rate_count.html')

我们还可以来可视化一下每一个评分的人数,这个地方采用柱状图来显示:

data = pd.read_csv(f,sep='{',header=None,encoding='utf-8',names=['date','nickname','city','rate','comment'])# 按评分分类rateData = data.groupby(['rate'])rateDataCount = rateData["date"].agg([ "count"])rateDataCount.reset_index(inplace=True)count = rateDataCount.shape[0] - 1attr = [rateDataCount["rate"][count - i] for i in range(0, rateDataCount.shape[0])] v1 = [rateDataCount["count"][count - i] for i in range(0, rateDataCount.shape[0])]bar = Bar("评分数量")bar.add("数量",attr,v1,is_stack=True,xaxis_rotate=30,yaxix_min=4.2, xaxis_interval=0,is_splitline_show=True)bar.render("html/rate_count.html")

如下所示,在猫眼的数据中,五星好评的占比超过了 50%,比豆瓣上 34.8% 的五星数据好很多。

这一部剧,观众朋友还是非常地喜欢。前面,从猫眼拿到了观众的评论数据。现在,笔者将通过 jieba 把评论进行分词,然后通过 Wordcloud 制作词云,来看看,观众朋友们对《无名之辈》的整体评价:

data = pd.read_csv(f,sep='{',header=None,encoding='utf-8',names=['date','nickname','city','rate','comment'])comment = jieba.cut(str(data['comment']),cut_all=False)wl_space_split = " ".join(comment)backgroudImage = np.array(Image.open(r"./unknow_3.png"))stopword = STOPWORDS.copy()wc = WordCloud(width=1920,height=1080,background_color='white', mask=backgroudImage, font_path="./Deng.ttf", stopwords=stopword,max_font_size=400, random_state=50)wc.generate_from_text(wl_space_split)plt.imshow(wc)plt.axis("off")wc.to_file('unknow_word_cloud.png')

导出:

历来能够称得上黑马的都是小成本并且反映小人物的荒诞喜剧为多,从这四个关键词中我们似乎看出了这部电影究竟为什么会收获众多好评。一如豆瓣上的一条短评所言:“不是爱情,胜似爱情。丧的刚刚好,黑的刚刚好,暖的刚刚好。有人说,中国没有‘治愈系’的电影。从此片起,就有了。看这片,我们笑着流泪。刻画底层人物的现实主义题材的电影不在少数,但此片是我近年来看过的,最具诚意、三观最正,也最‘哀而不伤’的一部。你将充分感受到什么叫‘真正的演技’,你将看到陈建斌任素汐章宇王砚辉等‘顶级演技天团’如何飙戏。真心期盼,从此片起,国产片将真正迎来‘好演员+好电影的春天’。”

【完】

点击“设为星标”就可以啦!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181127A0FFUS00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券