写在前面
记录一下这学期《数据分析与应用》这门课的课程报告,下面是正文内容。


  • 1 背景分析
  • 2 数据介绍
  • 3 数据爬虫
  • 4 数据清洗
  • 5 数据分析
    • 5.1 最受欢迎的前10种电影类型
    • 5.2 不同类型电影数和上映时间之间的关系
    • 5.3 电影排名和上映时间的关系
    • 5.4 电影总数和上映时间的关系
    • 5.5 最受欢迎的10位导演
    • 5.6 电影平均票房排名前10的电影类型
    • 5.7 电影票房和电影排名之间的关系
  • 6 总结
  • 参考文献

摘要:电影事业在近几十年来得到了蓬勃发展,分析全球前100名的电影的相关数据对于有助于了解整个电影市场及行业,本文以Python作为编程语言,首先利用Scrapy框架对全球前100名的电影数据进行了获取,并进行了数据清洗,最后利用Pandas、Matplotlib等进行了数据分析,对全球前100名电影的整体情况进行了探究。

关键词:Scrapy、电影、Python、数据分析

1 背景分析

随着人们生活水平的不断提高,看电影等精神层面的消费越来越受到人们的青睐,而电影拍摄和制作水平的提升也让电影制作的周期大幅度地降低。那么截止目前,全球前100名电影的情况呈现哪些趋势呢?这是我们想要探究的问题。

2 数据介绍

本数据的数据源来自网站www.piaofang.biz(全球电影票房排行榜网),观察网站我们需要获取的数据包括排名、电影名、上映时间、类型、导演和全球票房。

图 1 全球电影票房排行榜

3 数据爬虫

Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。下图显示了Scrapy的架构。

图 2 Scrapy架构图

基于Scrapy框架,简单地编写爬虫代码,将全球电影票房排行榜网的源代码保存为boxoffice.html留在本地,下面是关键代码,保存在附件中的tutorial/spider/Tutorial.py。

import scrapy
from tutorial.items import TutorialItemclass TutorialSpider(scrapy.Spider):name = 'Tutorial'allowed_domains = ['piaofang.biz']start_urls = ['http://www.piaofang.biz']def parse(self, response):filename = "boxoffice.html"open(filename, 'wb+').write(response.body)

这样我们就获取到了全球电影票房排行榜网的关键数据,爬取到html源代码如下图所示。

图 3 boxoffice.html爬取到的网页源代码(左图是记事本源代码,右图是html打开网页

4 数据清洗

通过分析爬取的网页源代码,我们编写相关的正则表达式来匹配需要的信息,这里注意两个点,第一是爬取的是排名的数字、上映时间和全球票房是数值型的数据,爬取后的数据是字符串类型,需要进行字符串到数值类型的转换;二是电影名对应的html代码可能存在超链接,需要对存在超链接的匹配字符串进行二次正则表达式匹配,提取真正的电影名。下面是数据清洗的关键代码:

from pandas.core.frame import DataFrame
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import re
# 正则表达式匹配规则
numberinfo='<td class="num">.*?第 (.*?) 名</td>'
titleinfo='<td class="title">《(.*?)》<[/s]'
yearinfo='<td class="year">(.*?)</td>'
typeinfo='<td class="type">(.*?)</td>'
directorinfo='<td class="daoyan">(.*?)</td>'
boxofficeinfo='<td class="piaofang"><span>(.*?)</span>'# 排名:字符串转换为数值型数据
number=re.findall(numberinfo,str(soup))
number=[int(y) for y in number]
# 电影名:由于匹配的字符串有的存在超链接,所以进行了二次正则表达式匹配去除超链接
title=re.findall(titleinfo,str(soup))
title_n=[]
for t in title:if '<' in t:t=re.findall('<a href=.*?>(.*?)</a>',t)title_n.append(t)
# 年份:字符串转换为数值型数据
year=re.findall(yearinfo,str(soup))
year=[int(y) for y in year]
# 电影类型:字符串转换为数值型数据
types=re.findall(typeinfo,str(soup))
# 电影导演
director=re.findall(directorinfo,str(soup))
# 电影票房:去除数字中的逗号并将字符串转换为数值型数据
boxoffice=re.findall(boxofficeinfo,str(soup))
boxoffice=[s.replace(",","") for s in boxoffice]
boxoffice=[int(s) for s in boxoffice]

进行了提取以后我们将数据转化为Pandas支持的DataFrame格式,命名为dataF。

data={"number": number,"title" :   title_n,"year":     year,"type":     types,"director": director,"boxoffice": boxoffice}
dataF=DataFrame(data)

经过处理后的dataF再把电影类型中的’/’替换为’,’。并且保存为csv格式

dataF['type']=dataF['type'].str.replace('/',',')
dataF.to_csv('电影票房100.csv', encoding='gbk',index=False)

我们可以查看一下我们导出的csv的部分数据:

图 4 导出的csv的部分数据

5 数据分析

5.1 最受欢迎的前10种电影类型

在dataF中的电影类型的电影类型可能有多种,我们进行拆分并去重得到全球前100名电影的电影类型。

#对type进行二次拆分
types_cnt=[]#[x,y,z,t]
types_rnt=[]#[[x,y],[z,t]]
for i in dataF['type']:i=i.split(',')types_cnt.extend(i)
types_rnt.append(i)types_all=[]
for i in types_rnt:for j in i:if j not in types_all:types_all.append(j)
print(types_all[:])

[‘科幻’, ‘动作’, ‘灾难’, ‘爱情’, ‘冒险’, ‘动画’, ‘犯罪’, ‘奇幻’, ‘喜剧’, ‘枪战’, ‘惊悚’, ‘战争’, ‘音乐’, ‘传记’, ‘军事’, ‘亲情’, ‘家庭’]

我们按照电影类型进行分组并进行排序,然后进行绘图。

type_list=pd.Series(types_cnt).value_counts()[:10].sort_values(ascending=False)
type_df=pd.DataFrame(type_list)
type_df.rename(columns={0:"Total"}, inplace=True)
import matplotlib.font_manager as mfm    #font_path=r"msyh.ttc"#字体 华文仿宋
prop=mfm.FontProperties(fname=font_path)
plt.style.use('ggplot')
plt.subplots(figsize=(10,8))
sns.barplot(y=type_df.index,x='Total', data=type_df)
plt.xticks(fontsize=12)
plt.yticks(fontproperties=prop,fontsize=12)
plt.xlabel('电影数量', fontproperties=prop,fontsize=12)
plt.ylabel('电影类型',fontproperties=prop, fontsize=12)
plt.title('最受欢迎的前10种电影类型', fontproperties=prop, fontsize=16)

图 5 最受欢迎的10种电影类型

可以看出全球前100名电影最受欢迎的还是动作、冒险、科幻、奇幻等更为震撼和吸引人的题材,相比之下犯罪、爱情、惊悚等类型要出彩难得多。

5.2 不同类型电影数和上映时间之间的关系

根据5.1节所得到的最受欢迎的电影类型,我们想研究一下这100部电影中,不同类型电影数和上映时间之间存在着什么关系,我们取前10种最受欢迎类型的电影进行绘图,如下图所示。从中可以看到,近几年动作、冒险、科幻等题材的电影发布数量有较大的增加,这可能是因为消费者偏好这些电影类型,电影市场很大程度地向其倾斜。

图 6 最受欢迎的10种电影类型上映数和上映时间之间的关系

下面是本节所使用的代码:

year_min=dataF['year'].min()
year_max=dataF['year'].max()
year_gen=pd.DataFrame(index=types_CNT, columns=range(int(year_min),int(year_max)+1))
year_gen.fillna(value=0, inplace=True)
year_gen.head()
z=0
for i in types_rnt:for j in list(i):year_gen.loc[j, int(yearArray[z])]=year_gen.loc[j, int(yearArray[z])]+1z += 1
#绘制子图的函数
def setplot_TypeTime(i,data,type):plt.rcParams['font.family']=['SimHei']plt.plot(data.loc[type].T)plt.title(str(i)+'.'+type+'类型电影和时间的关系', fontsize=16)plt.xlabel('电影上映时间')plt.ylabel('电影数')plt.xticks(range(1982,2023,5))plt.ylim([0,10])plt.legend([type])
#绘图
plt.rcParams['font.family']=['SimHei']
data=year_gen
plt.figure(figsize=(10, 10))
for i in range(1,11):plt.subplot(5,2,i)type=type_df.index[:][i-1]setplot_TypeTime(i,data,type)plt.tight_layout()

5.3 电影排名和上映时间的关系

我们还可以查看一下电影排名和时间之间的关系,如下图所示。图中的纵坐标是排名,横坐标是上映的时间,随着排名越低(对应着图更上方的位置),散点图的颜色越浅,可以看到,排名前20名的电影大都在近10年上映,这说明现代的电影拍摄手法以及剧情较之以前有了很大的提升,观众愿意为这些新电影买单。但其中有一个特例,上映时间是1997年,经过查看是排名第三的电影《泰坦尼克号》,可见真正的经典之作是不会被人们所遗忘的。

图 7 电影排名和上映时间的关系
#绘图
plt.subplots(figsize=(10,8))
sc1=plt.scatter(dataF['year'][:],dataF['number'][:],s=100,c=dataF['number'][:],cmap='hot')
plt.colorbar(sc1)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.xlabel('电影上映时间')
plt.ylabel('电影排名')
plt.title('电影排名和上映时间的关系',fontsize=16)
plt.show()

上面这个图可能不太直观,我们可以取每一年排名最高(数字最小)的电影作为代表数据,描绘电影最好排名和上映时间之间的关系,如下图所示。可以得出同样的结论:近几年的电影排名都跻身到了前20,说明随着时间的演进,有越来越多优质的影片出现,占据老影片排名的位置。

图 8 电影最好排名和上映时间之间的关系

5.4 电影总数和上映时间的关系

根据5.3,我们直观的体会是,随着时间的推进,优质电影的数量在不断增长。和5.2不同,这次我们按照年份对电影进行分组并记数,绘制了下图。可以看到,总体趋势上,优质电影的数量确实是随着时间在增加的,这一方面得益于电影拍摄手法以及剧情较之以前有了很大的提升,使电影的制作周期缩短,另一方面则是因为观众的消费水平和收入水平随着时间演进有所提升,使得近些年来的这些电影票房增加,排名随之冲到了前面。

图 9 电影数量和上映时间的关系

下面是本节的代码:

year_count=[]
for y in range(year_min,year_max+1):ye=dataF[dataF['year']==y]if ye.empty:year_count.append(0)else:df=ye.groupby(['year'])['title'].count()year_count.append(df[y])
#绘图
plt.subplots(figsize=(10,8))
plt.bar(range(year_min,year_max+1),year_count,color='#539caf')
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.xlabel('电影上映时间')
plt.ylabel('电影数量')
plt.title('电影数量和上映时间的关系',fontsize=16)
plt.show()

5.5 最受欢迎的10位导演

这100部电影中的导演谁最擅长拍摄呢,谁的电影最受欢迎呢?同样的,我们可以对这100部电影按照导演的名字进行分组并记数,绘制如下的条形图。可以看到最受欢迎的10位导演大都还是欧美的导演,中国的电影也在不断发展,但还需要继续努力。

图 10 最受欢迎的10位导演

下面是本节的关键代码:

#创建dirctor的series对象
se_dirctor_number=dataF.groupby(['director'])['title'].count().sort_values(ascending=False)
print(se_dirctor_number[:10])#把series对象转化为dataFrame对象
dit_dirctor_number = {'director':se_dirctor_number.index,'numbers':se_dirctor_number.values}
df_dirctor_number = pd.DataFrame(dit_dirctor_number)
print(df_dirctor_number[:10])#绘图
plt.subplots(figsize=(10,8))
sns.barplot(y='director',x='numbers', data=df_dirctor_number[:10])
plt.xticks(fontsize=12)
plt.yticks(fontproperties=prop,fontsize=12)
plt.xlabel('拍摄电影数量', fontproperties=prop,fontsize=12)
plt.ylabel('电影类型',fontproperties=prop, fontsize=12)
plt.title('最受欢迎的十位导演', fontproperties=prop, fontsize=16)

5.6 电影平均票房排名前10的电影类型

在5.1我们已经统计了前10种最受欢迎的电影类型,这是根据题材分类进行统计的,更进一步的,如果对这些同类型的电影票房取平均获取它们的平均票房,那么是否还是按照这个顺序呢?平均票房的计算按照下式计算:
b o x o f f i c e a v e r a g e = ( b o x o f f i c e t o t a l ) / n u m b e r boxoffice_{average}=(boxoffice_{total})/number boxofficeaverage​=(boxofficetotal​)/number
式中的 b o x o f f i c e a v e r a g e boxoffice_{average} boxofficeaverage​表示同类型平均票房, b o x o f f i c e t o t a l boxoffice_{total} boxofficetotal​表示同类型电影的总票房,而 n u m b e r number number则代表同类型的电影数量。

绘制图像如下,可以看到爱情、灾难、犯罪片反而是平均票房最高的电影类型,这和5.1前10种最受欢迎的电影类型的结论似乎有点矛盾,但是由于本文只考虑了全球前100名的电影数据,且前两名爱情和灾难类型的电影中包含总票房第三的《泰坦尼克号》,总票房数较高,样本数量又少,所以平均票房就出现了下图的情况。

图 11 电影平均票房排名前10的电影类型

下面是本节的代码:

part_df=dataF[['title','type','year','boxoffice']].reset_index(drop=True)
part_df.head()
movie_types = types_CNT
for mt in movie_types:part_df[mt]=0z=0for g in types_rnt:if mt in list(g):part_df.loc[z,mt]=1else:part_df.loc[z,mt]=0z+=1
boxoffice_means = []
for mt in movie_types:i=part_df.groupby(mt, as_index=True)['boxoffice'].mean()boxoffice_means.append(i)
part_df.head()
mean_list = [m[1] for m in boxoffice_means]
mean_df=pd.DataFrame(movie_types)
mean_df.rename(columns={0:"type"}, inplace=True)
mean_df['average_boxoffice']=mean_list
mean_df.head()
s1=mean_df.sort_values(['average_boxoffice'],ascending=False)[:10]
#绘图
plt.subplots(figsize=(10,8))
sns.barplot(x='average_boxoffice', y='type',data=s1)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.xlabel('平均票房')
plt.ylabel('电影类型')
plt.title('电影平均票房排名前10的电影类型',fontsize=16)
plt.show()

5.7 电影票房和电影排名之间的关系

网站中的这个电影排名是根据什么规则排出来的呢?我们大胆猜测,电影票房越高,电影排名越好,我们根据网站中的数据绘制了电影票房和电影排名之间关系的图像,如下图所示。可以看出我们的猜测是正确的,网站的电影票房确实和电影排名存在严格的负相关关系。

图 12 电影票房和电影排名之间的关系

下面是本节的关键代码:

#绘图
plt.subplots(figsize=(10,8))
plt.plot(dataF['number'], dataF['boxoffice'])
plt.scatter(dataF['number'], dataF['boxoffice'],s=10)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.xlabel('电影排名')
plt.ylabel('电影票房')
plt.title('电影票房和电影排名之间的关系',fontsize=16)
plt.show()

6 总结

本文利用Scrapy爬虫技术对全球前100名的电影进行了数据获取和分析,从数据中我们可以看出电影的行业在不断地发展和进步,越来越多的好电影不断涌现,电影市场也在向科幻、动作等强视觉效果的类型不断拓展。下一个票房冠军是什么电影呢?我们拭目以待。

参考文献

[1] Scrapy入门教程.https://www.runoob.com/w3cnote/scrapy-detail.html

基于Scrapy爬虫的全球前100名电影数据分析相关推荐

  1. 最新世界大学自然指数排名:30所内地高校进入全球前 100 名!

    来源 | 中国教育在线.nature 编辑 | 双一流高校 近日,自然指数网站更新了2022年最新的自然指数(Nature Index)排名,统计时间节点为2021.4.1-2022.3.31.中国高 ...

  2. 最新全球学术排名出炉:23所中国大学跻身世界前100名!

    来源:iinature 编辑:双一流高校 2021年11月,Nature指数公布了2020年8月1日到2021年7月31日大学/机构排名,也就是说最新的一期机构/大学的学术排名正式出炉.在全球前100 ...

  3. 【转】GitHub 中国区前 100 名到底是什么样的人?

    原文网址:http://mt.sohu.com/20160407/n443539407.shtml 本文根据Github公开API,抓取了地址显示China的用户,根据粉丝关注做了一个排名,分析前一百 ...

  4. 爬虫(一):用python爬取亚马逊所有家具种类前100名的商品信息(上)

    目标 亚马逊公司(Amazon),是美国最大的一家网络电子商务公司,位于华盛顿州的西雅图,是网络上最早开始经营电子商务的公司之一,现在已成为全球商品品种最多的网上零售商和全球第二大互联网企业. 本次目 ...

  5. 爬虫(二):用python爬取亚马逊所有家具种类前100名的商品信息(下)

    目标 亚马逊公司(Amazon),是美国最大的一家网络电子商务公司,位于华盛顿州的西雅图,是网络上最早开始经营电子商务的公司之一,现在已成为全球商品品种最多的网上零售商和全球第二大互联网企业. 本次目 ...

  6. 【python+爬虫】爬去猫眼电影前100名具体信息

    爬去猫眼电影前100名具体信息 准备工作 1:requests,json,time,re库 2:python3.x 3:pycharm 4:在线正则表达式测试网址 http://tool.oschin ...

  7. 2014年中国开源软件前100名

    不知道从什么时候开始,很多一说起国产好像就非常愤慨,其实大可不必.做开源中国六年有余,这六年时间国内的开源蓬勃发展,从一开始的使用到贡献,到推出自己很多的开源软件,而且还有很多软件被国外的认可.中国是 ...

  8. 5个大陆高校学科进入全球前10名;霍尼韦尔将发布全球最强大量子计算机 | 美通企业日报...

    今日看点 2020年QS世界大学学科排名发布.在最新发布的QS世界大学学科排名中,中国大陆地区大学在全球舞台上的表现更进一步.首次有100个中国大陆高校学科点进入了全球50强,这也是大陆地区大学连续第 ...

  9. 最新!TUI世界大学排名(2021)发布:清华位居全球前20名!

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 来源丨双一流高校 编辑丨极市平台 导读 南方教育智库大学第三方评价课 ...

最新文章

  1. 用于Fluent Design的UWP社区工具包蓄势待发
  2. redis教程(一)之redis简介
  3. 何杰月c语言课程,北京西城区教育科研月:学科核心素养的教学探索
  4. linux 编译内核几个常见问题解决方法
  5. 宗宁:全面解析微博财报数据爆发下的平台机会
  6. C++使用链表实现queue之二(附完整源码)
  7. qt撤销与回退_Qt动画框架
  8. leetcode(一)刷题两数之和
  9. java程序默认包含的包是,Java程序默认引用的包是 答案:java.lang包
  10. C#:xml操作(待补充)
  11. 戴尔服务器H330阵列卡取消磁盘阵列教程
  12. three.js 三维室内地图导航实例
  13. JVM之 永久代与元空间
  14. 程序员养生书单,九本必读养生书籍,颈椎按摩,脊椎按摩,脱发植发
  15. 在html里ff3d3d是什么颜色,HTML一些颜色方面的参考
  16. 一般人不会的电脑小绝技(ZT)
  17. vue用watch监听属性变化
  18. 前端题基础练习总结。。。。
  19. 同人逼死官方系列!基于sddc 协议的SDK框架 sddc_sdk_lib 解析
  20. Mac音乐播放器哪款好用?

热门文章

  1. matlab step函数跟踪斜坡信号及阶跃响应绘图
  2. PCB之AD导入logo
  3. unity 阳光插件_黄埔区阳光雅筑整厂空调维保价格,详情了解
  4. Spring boot热部署的作用和原理
  5. webpack 的 sourse-map 中 eval、cheap、inline 和 module 各是什么意思呢?
  6. Erase/Trim/Discard/Sanitize
  7. Halcon入门--提取图片对象个数
  8. 到底还要学什么才能成为2020年前端架构师!?(用图说话)
  9. 手机闹钟软件测试用例,手机测试用例
  10. java编程实例_几个java编程的典型例子