设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 4519|回复: 0
打印 上一主题 下一主题

我敢打赌,你猜不到去年电影国内票房最高的演员是谁

[复制链接]

169

主题

1

好友

733

积分

版主

Rank: 7Rank: 7Rank: 7

跳转到指定楼层
楼主
发表于 2019-4-12 11:40:58 |只看该作者 |倒序浏览

去年末的时候,我招收了新的“实训生”。本文是其中一位 @齐大圣 同学在实训两个月时完成的项目案例。(码上行动群里同学应该都看过这个名字,现在也是助教之一。)项目最初的想法是,从互联网上的公开信息中采集2018年在国内上映电影的票房、评分、类型、演员等信息,然后做一些数据分析和可视化展示。这样一个项目,除了需要对 python 基本语法和数据结构的掌握之外,还涉及到网页分析、爬虫、文本解析、数据库存储、数据处理、数据分析、数据可视化,并且需要对一个完整项目有整体的模块设计,对于编程学习者来说是从入门到进阶的一个很好案例。经常跟我说学了基础不知道做什么项目的同学们,别光顾着看热闹,回头自己也动手做一做。代码已上传,获取见文末。

项目之初,我们的想法主要是对去年国内上映电影的票房、评分进行一下排行,然后按不同类型对比下,什么片更受欢迎,什么片更赚钱。后来开发过程中,正值《流浪地球》大卖,吴京成为首位国内票房破百亿的演员。于是我们突发奇想,来看一看谁是去年单年累积票房最高的演员。是《我不是药神》的徐峥,还是《唐人街探案2》的王宝强(他俩还合演了《一出好戏》),又或者是《红海行动》中的某位?

在往下看之前,你也可以大胆猜一下。但我打赌你是猜不到的。如果没猜对,记得帮忙转发点赞。
基本数据情况:票房数据来自中国票房网(http://cbooo.cn)评分数据来自豆瓣电影(http://movie.douban.com)、猫眼(http://maoyan.com)、时光网(http://mtime.com)、IMDB(http://imdb.com)导演、演员信息来自豆瓣电影共 522 部电影,4723 位影人由于从几个不同网站抓取数据,有些名称会不一致,或者出现部分数据缺失的情况。因此这个数据并不是绝对完整的,但不影响整体结论影片所属类型没有严格定义,且会有多个类型。实际选取方式我们在下面会有具体说明。电影总排行:
这个排名大家都不陌生,没啥好多说的,好玩的在后面。
票房分布
我们将所有电影按评分和票房做成散点分布图,得到上述图片。此图是动态可交互的,这里我截几张有代表性的(点击图片后可放大):

依次是动作、喜剧、剧情、动画四类电影分布。粗略一看,动作片是比较受市场欢迎的,毕竟选择去观看大屏幕,很大程度也是为了享受特效和视听感受。喜剧和剧情也还不错,但高票房的动画片就很少了。
类型片
这张图是不同影片类型的数量和评分情况。剧情、喜剧、动作是三大主流类型。

从评分上看,动画片最高,我很早就发现了这个现象,我觉得可能是因为动画片类型明确,会观看并评价的人本身对其接受度高,而不喜欢的人压根儿就不会去看。剧情片整体评分也不错,可见能把一个故事说好,观众就挺满意了。爱情片、惊悚片则是一向是烂片的高发地带。

说明下:这里的类型是重复计算的,一部片会既是动作片,又是喜剧片。另外由于豆瓣上一些电影评分数量太少而不显示,所以这里的电影数量会和票房数量有所差异。

从票房上看,动作片不管是总量还是平均,都很强势。值得注意的是科幻片,虽然一般认为这是个小众类型,但与广义科幻沾边的影片平均票房却不低(这里面Marvel贡献了不少),今年的小破球更是创造了新的纪录。战争片则是被《红海行动》一片之力拉高了平均值。
月度票房
将类型片的票房按月划分,得到了这张图。春节档无疑是一年最抢钱的档期,而喜剧片又是此档期的绝对主力。暑期档则是另一个票房小高峰。动作片一年四季都不错。

这里的月度划分是按首映日期,所以会有一些提前,比如国庆档的票房都记在了九月份。

以上面几组数据来看,如果哪位土豪读者想投资拍电影,选择动作片是比较保险的,记得要把故事说好,最好再加点科幻元素,在春节前上映。
评分对比
这里做了 IMDB、时光网、猫眼分别和豆瓣评分的关系对比。

按理说,如果两个网站的评分基本一致的话,这些点应当分布在对角线上。IMDB、时光网和豆瓣还是差不多的(豆瓣其实是5星制,最低2分)。再细分一下,时光网和豆瓣的相关性要比 IMDB 更大(文化差异),好片比烂片的相关性更大(好片都说好,烂片则口味不同)。

有意思的是猫眼(最右侧图),它的评分普遍要比豆瓣高,相信很多人都有直观感受。当然这也有它的原因:猫眼买了票的人才会评分,那一般总归会选个自己爱看的吧。

【彩蛋】图上右下角有个令人瞩目的孤点,这部电影是个例外,它猫眼评分2.9,豆瓣却有6.9,你知道是哪部吗?(可以留言猜一下,我待会儿在留言中公布答案)如果你了解此片背后的故事,定会一拍大腿恍然大悟。
演员
好了,到了公布最终结果的时候。

第一名:王成思

参演电影:《西红柿首富》25亿;《唐人街探案2》34亿;《李茶的姑妈》6亿

这……是谁啊,演的谁……

斯坦·李凭借各种客串,位列第3。而另一位能在Marvel、DC两道均能跑龙套的约翰·盖蒂尔,也跻身前十,同样也不知道他演的角色……

怎么样,有没有出乎你的意料?现在你可以拿这个去问别人了


所有图表在网页上都是动态可交互的,访问地址请在我们公众号(Crossin的编程教室)里回复关键字 票房

代码也已上传,并附带有说明文档,大致说明了实现思路、文件说明、技术细节。同样回复关键字 票房


如果你想要跟着实现或运行相关代码,我这里再简单说几点。

项目整体思路:
通过 中国票房网 获得2018年大陆上映电影和每部电影票房数据根据已有的票房数据,通过豆瓣 api 和详细页面,获得每部电影的导演,演员和豆瓣评分等详细数据分别通过 猫眼、时光网 和 imdb,获取这三个网站的电影评分数据新建影人条目,利用豆瓣获得的影人数据,对2018年每个演员年参演电影进行统计根据已有数据作图,分析2018年电影票房排名、不同网站评分差异、电影票房-评分关系等
开发环境及所需库:
python 3.6(3.5以上版本应该都没啥问题)jupyter notebook - 这个之前介绍过多次,数据分析好帮手requests - 网页抓取bs4 - 网页文本分析pymongo - 本项目用了 mongodb 数据库numpy - 数据计算必备pyecharts - 绘图工具包 ECharts 的封装
有几点值得注意的是:
因为豆瓣的搜索结果是模糊匹配,根据电影名会搜出多部电影,因此匹配豆瓣信息时增加了人工干预的步骤。这部分代码可以再优化。项目使用 MongoDB 作为数据存储,这不是必须的,你可以把这部分代码改成文件保存。另外如果你只是想做数据分析,也可以拿我们抓取好导出的数据,免除抓取之苦。(附带在项目中,仅供学习,请勿商用,否则后果自负)
部分代码(仅演示,完整代码见项目仓库):

抓取并保存
  1. client = pymongo.MongoClient()
  2. db = client.chinamovies # 获取或新建名为 chinamovies 的 database
  3. collections = db.movies # 获取或者新建了一个表
  4. url_origin = 'http://www.cbooo.cn/Mdata/getMdata_movie?area={area}&type=0&year=2018&initial=%E5%85%A8%E9%83%A8&pIndex={page}'
  5. url = url_origin.format(area=area, page=page)
  6. req = requests.get(url, headers=headers)
  7. data = req.json()
  8. collections.insert_many(data['pData'])
复制代码
获取豆瓣信息
  1. url_api = 'https://api.douban.com/v2/movie/search?q={}'.format(moviename)
  2. req = requests.get(url_api, headers=headers)
  3. data_total = req.json()['subjects']
  4. if not data_total:
  5.     print('你搜索的不存在:', moviename)
  6. else:
  7.     print(data_total[0])
复制代码
计算影人参演票房总和
  1. for i in col_casts.find():
  2.     total_box = 0
  3.     for j in i['movie_id']:
  4.         movie = collections_detail.find_one({'id': j})
  5.         if movie['boxoffice']:
  6.             total_box += int(movie['boxoffice'])
  7.     col_casts.update_one({'_id': i['_id']}, {'$set': {'total_box': total_box}}, upsert=True)
复制代码
输出票房/评分分布散点图
  1. scatter = Scatter("电影评分-票房")
  2. total_num = 0
  3. for i in genre:
  4.     total_num += len(genre[i]['rate'])
  5.     scatter.add(i, genre[i]['boxoffice'], genre[i]['rate'], **other_setting, extra_name=genre[i]['title'],
  6.                 xaxis_name='票房(亿)', yaxis_name='评分', yaxis_name_gap=20,yaxis_min=2, symbol_size=5,
  7.                 label_formatter='{c}', is_label_emphasis=True, is_toolbox_show=False)
  8. scatter.render('电影评分-票房.html')
复制代码
查看交互图表和代码地址,请在公众号(Crossin的编程教室)回复关键字 票房


════

其他文章及回答:

学编程:如何自学Python | 新手引导 | 一图学Python

开发案例:智能防挡弹幕 | 红包提醒 | 流浪地球

欢迎搜索及关注:Crossin的编程教室

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-11-25 17:15 , Processed in 0.015987 second(s), 21 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部