豆瓣电影数据分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了豆瓣电影数据分析相关的知识,希望对你有一定的参考价值。

参考技术A 这篇报告是我转行数据分析后的第一篇报告,当时学完了Python,SQL,BI以为再做几个项目就能找工作了,事实上……分析思维、业务,这两者远比工具重要的多。一个多月后回过头来看,这篇报告虽然写得有模有样,但和数据分析报告还是有挺大差别的,主要原因在于:a.只是针对豆瓣电影数据分析太过宽泛了,具体关键指标到底是哪些呢?;b.没有一个确切有效的分析模型/框架,会有种东一块西一块的拼接感。
即便有着这些缺点,我还是想把它挂上来,主要是因为:1.当做Pandas与爬虫(Selenium+Request)练手,总得留下些证明;2.以豆瓣电影进行分析确实很难找到一条业务逻辑线支撑,总体上还是描述统计为主;3.比起网上能搜到的其他豆瓣电影数据分析,它更为详细,可视化效果也不错;

本篇报告旨在针对豆瓣电影1990-2020的电影数据进行分析,首先通过编写Python网络爬虫爬取了51375条电影数据,采集对象包括:电影名称、年份、导演、演员、类型、出品国家、语言、时长、评分、评论数、不同评价占比、网址。经过去重、清洗,最后得到29033条有效电影数据。根据电影评分、时长、地区、类型进行分析,描述了评分与时长、类型的关系,并统计了各个地区电影数量与评分。之后,针对演员、导演对数据进行聚合,给出产量与评分最高的名单。在分析过程中,还发现电影数量今年逐步增加,但评分下降,主要原因是中国地区今年低质量影视作品的增加。

另外,本篇报告还爬取了电影票房网( http://58921.com/ )1995-2020年度国内上映的影片票房,共采集4071条数据,其中3484条有效。进一步,本文分析了国内院线电影票房年度变化趋势,票房与评分、评价人数、时长、地区的关系,票房与电影类型的关联,并给出了票房最高的导演、演员与电影排名。

清洗、去重后,可以看到29033条数据长度、评分、评论数具有以下特点:

结合图1(a)(b)看,可以看到电影数据时长主要集中在90-120分钟之间,向两极呈现阶梯状递减,将数据按照短(60-90分钟),中(90-120分钟),长(120-150分钟),特长(>150分钟)划分,各部分占比为21.06%, 64.15%, 11.95%, 2.85%。

结合图2(a)看,可以看到我们采集到的电影数据评分主要集中在6.0-8.0之间,向两极呈现阶梯状递减,在此按照评分划分区间:2.0-4.0为口碑极差,4.0-6.0为口碑较差,6.0-7.0为口碑尚可,7.0-8.0为口碑较好,8.0-10.0为口碑极佳。

这5种电影数据的占比分别为:5.78%, 23.09%, 30.56%, 29.22%, 11.34%

再将评分数据细化到每年进行观察,可以发现,30年内电影数量与年度电影均分呈反相关,年度均分整体呈现下降趋势,2016年电影均分最低,电影数量最多。

进一步做出每个年份下不同评级等级的电影数据占比,可以发现,近年来,评分在[2.0,6.0)的电影数据占比有着明显提升,评分在[6.0,7.0)的数据占比不变,评分在[7.0,10.0)的数据占比减少,可能原因有:

对照图5,可以发现,评分与时长、评论人数的分布大致呈现漏斗状,高分电影位于漏斗上部,低分电影位于漏斗下部。这意味着,如果一部电影的评论人数很多(特别是超过30w人观影),时长较长(大于120min),那么它大概率是一部好电影。

根据各个国家的电影数量作图,可以得到图6,列出电影数量前十的国家可得表格2,发现美国在电影数量上占第一,达到8490部,中国其次,达6222部。此外,法国,英国,日本的电影数量也超过1000,其余各国电影数量相对较少。这可以说明美国电影有着较大的流量输入,在中国产生了较大的影响。

进一步分析各国电影的质量,依据评分绘制评分箱线图可得图7,在电影数量排名前20的国家中:

接着我们可以探索,哪个国家的电影对豆瓣评分随年份下降的贡献最大,考虑到电影数量对应着评分的权重。根据上述各国的电影评分表现,我们可以猜测电影数量较多的国家可能对年度均分的下降有较大影响。于是,我们再计算出这些国家的年度电影均分,并与整体均分进行比较分析。

再作出中国大陆,中国台湾,中国香港的均分箱线图图9(a),可以看到,大陆电影均分低于港台电影,且存在大量低分电影拉低了箱体的位置。

分析相关性可得,大陆、香港、台湾电影年度均分与全部评分关联度分别为R=0.979,0.919,0.822,说明滤去台湾和香港电影,大陆电影年度均分的变化趋势与全部评分变化更接近。图9(b)可以进一步反映这一点。

可以看到,大部分类型集中在X×Y=[10000,30000]×[6.00,7.50]的区间范围内,剧情、喜剧、爱情、犯罪、动作类电影数量上较多,说明这些题材的电影是近三十年比较热门的题材,其中剧情类电影占比最多,音乐、传记类电影平均得分更高,但在数量上较少,动作、惊悚类电影评论人数虽多,但评价普遍偏低。

除此之外,还有两块区域值得关注:

根据类型对电影数据进行聚合,整理得到各类型电影评分的时间序列,计算它们与整体均分时间序列的相关性,可得表格4与图11,可以看到剧情,喜剧,悬疑这三种类型片与总分趋势变化相关性最强,同时剧情、喜剧类电影在电影数量上也最多,因此可以认为这两类电影对于下跌趋势影响最大,但其余类别电影的相关性也达到了0.9以上,说明几种热门的电影得分的变化趋势与总体均分趋势一致。

前面已经得知,中美两国电影占比最高,且对于均分时间序列的影响最大。在此,进一步对两国电影进行类型分析,选取几种主要的类型(数量上较多,且相关性较高)进行分析,分别是剧情,喜剧,爱情,惊悚,动作,悬疑类电影,绘制近年来几类电影的数量变化柱状图与评分箱线图可得图12,13,14,15。

对导演与演员进行聚合,得到数据中共有15011名导演,46223名演员。按照作品数量在(0,2], (2,5], (5,10], (10,20], (20,999]进行分组统计导演数量,可以发现,15009名导演中有79.08%只拍过1-2部作品,46220名演员中有75.93%只主演过1-2部作品。忽略那些客串、跑龙套的演员,数据总体符合二八定律,即20%的人占据了行业内的大量资源。

在此,可以通过电影得分、每部电影评论人数以及电影数目寻找优秀的电影导演与演员。这三项指标分别衡量了导演/演员的创作水平,人气以及产能。考虑到电影数据集中可能有少量影视剧/剧场版动画,且影视剧/剧场版动画受众少于电影,但得分普遍要高于电影,这里根据先根据每部电影评论数量、作品数量来筛选导演/演员,再根据电影得分进行排名,并取前30名进行作图,可得图17,18。

结合电影票房网( http://58921.com/ )采集到的3353条票房数据,与豆瓣数据按照电影名称进行匹配,可以得到1995-2020年在中国大陆上映的电影信息,分别分析中国内地电影的数量、票房变化趋势,票房与评分、评价人数、时长、地区以及类型的关系,此外还给出了不同导演与演员的票房表现以及影片票房排名。

如图19所示,国内票房数据与上映的电影数量逐年递增,2020年记录的只是上半年的数据,且由于受疫情影响,票房与数量骤减。这说明在不发生重大事件的情况下,国内电影市场规模正在不断扩大。

对电影数据根据类型进行聚合,绘制散点图21,可以发现:

提取导演/演员姓名,对导演/演员字段进行聚合,计算每个导演/演员的票房总和,上映电影均分、以及执导/参与电影数目进行计算,作出票房总和前30名的导演/演员,可得图22,23,图中导演/演员标号反映了票房排名,具体每位导演/演员的上映影片数量、均分、每部电影评价人数、平均时长与总票房在表5、表6中给出。

最后根据电影票房进行排名,得到票房排名前20的电影如表格7所示,可以看到绝大部分上榜电影都是中国电影,索引序号为3、10、12、14、18、19为美国电影,这也反映了除国产电影之外,好莱坞大片占据较大的市场。

本篇报告采集了1990-2020年间豆瓣电影29033组有效数据,从豆瓣电影的评分、时长、地区、类型、演员、导演以及票房等信息进行分析评价,主要有以下结论:

Java豆瓣电影爬虫——抓取电影详情和电影短评数据

  一直想做个这样的爬虫:定制自己的种子,爬取想要的数据,做点力所能及的小分析。正好,这段时间宝宝出生,一边陪宝宝和宝妈,一边把自己做的这个豆瓣电影爬虫的数据采集部分跑起来。现在做一个概要的介绍和演示。

 

动机

  采集豆瓣电影数据包括电影详情页数据和电影的短评数据。

  电影详情页如下图所示

  需要保存这些详情字段如导演、编剧、演员等还有图中右下方的标签。

 

  短评页面如下图所示

  需要保存的字段有短评所属的电影名称,每条评论的详细信息如评论人名称、评论内容等。

  

数据库设计

  有了如上的需求,需要设计表,其实很简单,只需要一张电影详情表movie和一张电影短评表comments,另外还需要一张存储网页提取的超链接的记录表record。

  movie表

  • movieId:主键,自增长
  • Name:电影名
  • Director:导演
  • Scenarist:编剧
  • Actors:主演
  • Type:类型
  • Country:制片国家/地区
  • Language:语言
  • releaseData: 上映日期
  • Runtime: 片长
  • ratingNum:豆瓣评分
  • Tags:标签

 

  comments表

  • commentId:主键,自增长
  • commentInfo:评论内容
  • commentAuthor:评论者
  • commentAuthorImgUrl:评论者头像链接
  • commentVote:评论点赞数
  • commentForMovie:评论的电影名
  • recordId:链接record表,暂时未用到

 

  record表

  • recordId:主键,自增长
  • URL:爬取解析的超链接
  • Crawled:是否被爬过

 

  注意:数据库设计是在不断调整的,比如之前设计了一张tags表,用于存储每部电影的标签,经过调整发现直接放到movie中作为一个字段更加方便,又比如comments表中,commentForMovie是后来加上的,方便查找当前的评论针对哪部电影。

 

使用的技术

  语言:Java(语言是一门工具,网上用python,java,nodejs比较多)

  数据库:Mysql(轻便易用)

  解析页面:Jsoup(比较熟悉httpparser,虽然功能强大,但是稍显繁琐,这里用Jsoup,因为其为类javascript语法)、正则表达式(对于一些结构比较奇怪的dom结构,采用了正则表达式的方式来提取信息,其实也可以用xpath,但是xpath极易受dom结构变化而失效)

  比如对于网页源码如下

<!DOCTYPE html>
<html lang="zh-cmn-Hans" class="ua-windows ua-webkit">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="renderer" content="webkit">
    <meta name="referrer" content="always">
    <title>
        肖申克的救赎 (豆瓣)
</title>
    
    .....
    
    <meta name="keywords" content="肖申克的救赎,The Shawshank Redemption,肖申克的救赎影评,剧情介绍,电影图片,预告片,影讯,在线购票,论坛,肖申克的救赎在线观看,肖申克的救赎高清,肖申克的救赎在线播放">
    <meta name="description" content="肖申克的救赎电影简介和剧情介绍,肖申克的救赎影评、图片、预告片、影讯、论坛、在线购票、肖申克的救赎在线观看、高清、在线播放">
   
.........                   


<div id="info">
        <span ><span class=\'pl\'>导演</span>: <span class=\'attrs\'><a href="/celebrity/1047973/" rel="v:directedBy">弗兰克·德拉邦特</a></span></span><br/>
        <span ><span class=\'pl\'>编剧</span>: <span class=\'attrs\'><a href="/celebrity/1047973/">弗兰克·德拉邦特</a> / <a href="/celebrity/1049547/">斯蒂芬·金</a></span></span><br/>
        <span class="actor"><span class=\'pl\'>主演</span>: <span class=\'attrs\'><a href="/celebrity/1054521/" rel="v:starring">蒂姆·罗宾斯</a> / <a href="/celebrity/1054534/" rel="v:starring">摩根·弗里曼</a> / <a href="/celebrity/1041179/" rel="v:starring">鲍勃·冈顿</a> / <a href="/celebrity/1000095/" rel="v:starring">威廉姆·赛德勒</a> / <a href="/celebrity/1013817/" rel="v:starring">克兰西·布朗</a> / <a href="/celebrity/1010612/" rel="v:starring">吉尔·贝罗斯</a> / <a href="/celebrity/1054892/" rel="v:starring">马克·罗斯顿</a> / <a href="/celebrity/1027897/" rel="v:starring">詹姆斯·惠特摩</a> / <a href="/celebrity/1087302/" rel="v:starring">杰弗里·德曼</a> / <a href="/celebrity/1074035/" rel="v:starring">拉里·布兰登伯格</a> / <a href="/celebrity/1099030/" rel="v:starring">尼尔·吉恩托利</a> / <a href="/celebrity/1343305/" rel="v:starring">布赖恩·利比</a> / <a href="/celebrity/1048222/" rel="v:starring">大卫·普罗瓦尔</a> / <a href="/celebrity/1343306/" rel="v:starring">约瑟夫·劳格诺</a> / <a href="/celebrity/1315528/" rel="v:starring">祖德·塞克利拉</a></span></span><br/>
        <span class="pl">类型:</span> <span property="v:genre">剧情</span> / <span property="v:genre">犯罪</span><br/>
        
        <span class="pl">制片国家/地区:</span> 美国<br/>
        <span class="pl">语言:</span> 英语<br/>
        <span class="pl">上映日期:</span> <span property="v:initialReleaseDate" content="1994-09-10(多伦多电影节)">1994-09-10(多伦多电影节)</span> / <span property="v:initialReleaseDate" content="1994-10-14(美国)">1994-10-14(美国)</span><br/>
        <span class="pl">片长:</span> <span property="v:runtime" content="142">142 分钟</span><br/>
        <span class="pl">又名:</span> 月黑高飞(港) / 刺激1995(台) / 地狱诺言 / 铁窗岁月 / 消香克的救赎<br/>
        <span class="pl">IMDb链接:</span> <a href="http://www.imdb.com/title/tt0111161" target="_blank" rel="nofollow">tt0111161</a><br>

</div>




                </div>
                    


<div id="interest_sectl">
    <div class="rating_wrap clearbox" rel="v:rating">
        <div class="rating_logo">豆瓣评分</div>
        <div class="rating_self clearfix" typeof="v:Rating">
            <strong class="ll rating_num" property="v:average">9.6</strong>
            <span property="v:best" content="10.0"></span>
            <div class="rating_right ">
                <div class="ll bigstar50"></div>
                <div class="rating_sum">
                    <a href="collections" class="rating_people"><span property="v:votes">740373</span>人评价</a>
                </div>
            </div>
        </div>
            
                
                <span class="stars5 starstop" title="力荐">
                    5星 
                </span>
                <div class="power" style="width:64px"></div>
                <span class="rating_per">81.5%</span>
                <br />
                
                <span class="stars4 starstop" title="推荐">
                    4星 
                </span>
                <div class="power" style="width:12px"></div>
                <span class="rating_per">16.2%</span>
                <br />
                
                <span class="stars3 starstop" title="还行">
                    3星 
                </span>
                <div class="power" style="width:1px"></div>
                <span class="rating_per">2.1%</span>
                <br />
                
                <span class="stars2 starstop" title="较差">
                    2星 
                </span>
                <div class="power" style="width:0px"></div>
                <span class="rating_per">0.1%</span>
                <br />
                
                <span class="stars1 starstop" title="很差">
                    1星 
                </span>
                <div class="power" style="width:0px"></div>
                <span class="rating_per">0.1%</span>
                <br />
            
    </div>
        <div class="rating_betterthan">
            好于 <a href="/typerank?type_name=剧情&type=11&interval_id=100:90&action=">99% 剧情片</a><br/>
            好于 <a href="/typerank?type_name=犯罪&type=3&interval_id=100:90&action=">99% 犯罪片</a><br/>
        </div>
</div>


                
            </div>
        
.........

    <!-- sindar19a-docker-->

  <script>_SPLITTEST=\'\'</script>
</body>

</html>

 

  可以通过如下代码来解析相应字段(其中有用Jsoup和正则表达式的)

for (Element info : infos) {
    if (info.childNodeSize() > 0) {
        String key = info.getElementsByAttributeValue("class", "pl").text();
        if ("导演".equals(key)) {
            movie.setDirector(info.getElementsByAttributeValue("class", "attrs").text());
        } else if ("编剧".equals(key)) {
            movie.setScenarist(info.getElementsByAttributeValue("class", "attrs").text());
        } else if ("主演".equals(key)) {
            movie.setActors(info.getElementsByAttributeValue("class", "attrs").text());
        } else if ("类型:".equals(key)) {
            movie.setType(doc.getElementsByAttributeValue("property", "v:genre").text());
        } else if ("制片国家/地区:".equals(key)) {
            Pattern patternCountry = Pattern.compile(".制片国家/地区:</span>.+[\\\\u4e00-\\\\u9fa5]+.+[\\\\u4e00-\\\\u9fa5]+\\\\s+<br>");
            Matcher matcherCountry = patternCountry.matcher(doc.html());
            if (matcherCountry.find()) {
                movie.setCountry(matcherCountry.group().split("</span>")[1].split("<br>")[0].trim());// for example: >制片国家/地区:</span> 中国大陆 / 香港     <br>
            }
        } else if ("语言:".equals(key)) {
            Pattern patternLanguage = Pattern.compile(".语言:</span>.+[\\\\u4e00-\\\\u9fa5]+.+[\\\\u4e00-\\\\u9fa5]+\\\\s+<br>");
            Matcher matcherLanguage = patternLanguage.matcher(doc.html());
            if (matcherLanguage.find()) {
                movie.setLanguage(matcherLanguage.group().split("</span>")[1].split("<br>")[0].trim());
            }
        } else if ("上映日期:".equals(key)) {
            movie.setReleaseDate(doc.getElementsByAttributeValue("property", "v:initialReleaseDate").text());
        } else if ("片长:".equals(key)) {
            movie.setRuntime(doc.getElementsByAttributeValue("property", "v:runtime").text());
        }
    }
}
movie.setTags(doc.getElementsByClass("tags-body").text());
movie.setName(doc.getElementsByAttributeValue("property", "v:itemreviewed").text());
movie.setRatingNum(doc.getElementsByAttributeValue("property", "v:average").text());

  

对于服务端返回不同状态的http status,本程序对于如304,401,403,404等都采取了丢弃处理,不作解析。

 

效果展示

 

  record表记录

 

  movie表记录

 

  comments表记录

 

  以上只是一个爬取数据的后台实现雏形,还有很多细节的问题需要解决。后期可能会补上环境搭建以及遇到的问题和解决方法相关的文章。

  Java豆瓣电影爬虫——使用Word2Vec分析电影短评数据

  Java豆瓣电影爬虫——小爬虫成长记(附源码)

  程序爬取控制在豆瓣可接受范围内,不会给豆瓣服务器带来很大的压力,写此程序也是个人把玩,绝无恶意,万望豆瓣君谅解^_^

 

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

 

以上是关于豆瓣电影数据分析的主要内容,如果未能解决你的问题,请参考以下文章

python豆瓣电影爬虫

Java豆瓣电影爬虫——抓取电影详情和电影短评数据

《豆瓣》查看优质电影及影评方法介绍

从豆瓣电影评分算法说起

豆瓣电影top250的电影都有哪些?

团队-爬取豆瓣电影TOP250-需求分析