Python数据分析豆瓣电影Top250

初学数据分析,这次就来分析一下电影信息。豆瓣电影的实战项目网上文章也不少,不过还是要自己操作一下才能理解得更深刻一点,也顺便了解一下这些电影的特点。

项目涉及的是一个特殊的电影排行榜,能上榜的想必都是非常受欢迎的电影,毕竟豆瓣上的评分还有热度都是很有参考性的。所以在这里对这个排行榜的排列标准探索一下,当然也只是粗略地分析。

豆瓣用户每天都在对“看过”的电影进行“很差”到“力荐”的评价,豆瓣根据每部影片看过的人数以及该影片所得的评价等综合数据,通过算法分析产生豆瓣电影 Top 250。


数据提取

首先分析一下网页信息,排行榜地址:https://movie.douban.com/top250
在这里插入图片描述
先看一下页面源代码内容,需要提取的信息都可以很快地找到。提取内容:排名、电影名、上映年份、制片国家/地区、类型、导演、评论人数、评分。

定位信息

我是采用 requests 库发送请求来获取网页,然后用 BeautifulSoup 库分析页面来获取信息。

获取请求没什么限制,甚至不需要加headers头信息,只需要把链接确认好:url = ‘https://movie.douban.com/top250?start={}&filter=’,start后面是25的倍数。分析页面就有一点麻烦,难在导演、演员和年份处在同一个 <p> 标签内,而且分离这些信息的时候无法用同一个标准,因为有些电影并没有完全给出信息,所以花了些时间在这个上面。

每个页面所有电影列表是放在一个 class=‘grid_view’ 的 <ol> 标签中的,这个标签下的每一个 <li> 标签就是每一部电影信息的Item。我采用的是BeautifulSoup库中的 css 选择方法,每个页面只有一个 <ol> 标签:

for list in range(10):
    movie_content = requests.get(movie_url.format(list * 25)).text
    soup = BeautifulSoup(movie_content, 'lxml')
    for li in soup.select('ol li'):
        movie_num = li.select('em')[0].string
        movie_name = li.select('.title')[0].string
        movie_info = li.select('.bd .')[0].get_text().lstrip().rstrip().split('\xa0/\xa0')
        movie_year = movie_info[0].split()[-1]
        movie_country = movie_info[1]
        movie_type = movie_info[2]
        movie_director = movie_info[0].split()[1]
        movie_assess = li.select('.star span')[-1].string[:-3]
        movie_score = li.select('.star span')[1].string
        writer.writerow([
            movie_num, movie_name, movie_year, movie_country, movie_type,
            movie_director, movie_assess, movie_score
        ])

只需要采用 select() 方法就可以一步步提取,只不过要注意好结果是Beautiful对象还是列表、字符串。这也是上面代码中不断出现 [ ]string[ : ] 的原因。

最后会把所有信息都存入一个 csv文件,也是为了后面数据提取得更方便。要注意的是,如果在Windows上面直接打开这个csv文件会出现乱码,因为我采用的是 UTF-8 编码,想要生成可以正常显示的信息可以在 open() 中把编码改成 gb18030

数据分析

数据导入
import pandas as pd

df = pd.read_csv('movies.csv', encoding='utf-8')
print(df.head())

为了看清楚,这里用表格展示出来:

0名称年份国家类型导演评价人数评分
01肖申克的救赎1994美国犯罪 剧情弗兰克·德拉邦特13224319.6
12霸王别姬1993中国大陆 香港剧情 爱情 同性陈凯歌9765649.6
23这个杀手不太冷1994法国剧情 动作 犯罪吕克·贝松12111479.4
34阿甘正传1994美国剧情 爱情罗伯特·泽米吉斯10418969.4
45美丽人生1997意大利剧情 喜剧 爱情 战争罗伯托·贝尼尼6094599.5
重复值检查
print(df.duplicated().value_counts())

得到:

False    250
dtype: int64

检查是否有重名电影:

print(len(df.名称.unique()))

得到:

250
分析同一上映年份的电影数量
print(df["年份"].value_counts().head())

这里以表格形式展示:

Name: 年份dtype: int64
201014
200412
199411
201110
201310
分析制片国家

有些电影由多个国家或地区联合制作的

area_split = df['国家'].str.split(' ').apply(pd.Series)
print(area_split.head())

这里以表格形式展示:

012345
0美国NaNNaNNaNNaNNaN
1中国大陆香港NaNNaNNaNNaN
2法国NaNNaNNaNNaNNaN
3美国NaNNaNNaNNaNNaN
4意大利NaNNaNNaNNaNNaN

可以看到,有些电影甚至有6个国家或地区参与制作,对于这么多的空值,可以通过先按列计数,将空值 NaN 替换为 ‘0’,再按行汇总。

all_country = area_split.apply(pd.value_counts).fillna('0') 

所有的 NaN 都会替换成 ‘0’,以便于后面的统计,接下来计算每个国家参与制作电影总数排名情况:

all_country.columns = ['area1', 'area2', 'area3', 'area4', 'area5', 'area6']
all_country['area1'] = all_country['area1'].astype(int)
all_country['area2'] = all_country['area2'].astype(int)
all_country['area3'] = all_country['area3'].astype(int)
all_country['area4'] = all_country['area4'].astype(int)
all_country['area5'] = all_country['area5'].astype(int)
all_country['area6'] = all_country['area6'].astype(int)
all_country['all_counts'] = all_country['area1'] + all_country['area2']\
                        + all_country['area3'] + all_country['area4']\
                        + all_country['area5'] + all_country['area6']
all_country.sort_values(['all_counts'], inplace = True, ascending=False)    # 降序
print(all_country.head())

得到一个国家或地区参与制作电影数的排名总情况,这里以表格形式展示:

area1area2area3area4area5area6all_counts
美国122142510144
日本322000034
英国1515400034
香港196000025
法国99210021

顺便根据最后的总数据画出直方图:

import matplotlib
import matplotlib.pyplot as plt

matplotlib.rcParams['font.family'] = 'SimHei'   #配置中文字体
matplotlib.rcParams['font.size'] = 15   # 更改默认字体大小

country = pd.DataFrame({'国家':all_country['all_counts']})
country.sort_values(by='国家', ascending=False).plot(kind='bar', figsize=(10,7))
plt.show()

得到:
在这里插入图片描述
可以看到排行榜中,美国参与制作的电影数量最多,而中国大陆排第七。

分析电影类型
all_type = df['类型'].str.split(' ').apply(pd.Series)
all_type = all_type.apply(pd.value_counts).fillna('0')
all_type.columns = ['tpye1', 'type2', 'type3', 'type4', 'type5']
all_type['tpye1'] = all_type['tpye1'].astype(int)
all_type['type2'] = all_type['type2'].astype(int)
all_type['type3'] = all_type['type3'].astype(int)
all_type['type4'] = all_type['type4'].astype(int)
all_type['type5'] = all_type['type5'].astype(int)
all_type['all_counts'] = all_type['tpye1'] + all_type['type2']\
                        + all_type['type3'] + all_type['type4']\
                        + all_type['type5']
all_type = all_type.sort_values(['all_counts'],ascending=False)
print(all_type.head())

统计每个类型在这些电影中出现的次数,这里以表格形式展示:

tpye1type2type3type4type5all_counts
剧情16422500191
爱情237180057
冒险652014247
喜剧242300047
犯罪122363044

顺便根据最后的总数据画出直方图:

movie_type = pd.DataFrame({'数量':all_type['all_counts']})
movie_type.sort_values(by='数量', ascending = False).plot(kind ='bar', figsize = (10,6))
plt.show()

得到:
在这里插入图片描述

统计上榜次数最多的导演
director = df['导演'].value_counts()
print(director.head())

这里以表格形式展示:

Name: 导演dtype: int64
克里斯托弗·诺兰7
宫崎骏7
史蒂文·斯皮尔伯格5
王家卫5
李安4

可以见识一下大导演的风采,以后看他们拍的电影想必不会失望的。

评分与排名的关系

既然想探索一下排名究竟与各项指标有什么联系,就要分别与排名比较一下,当然这里只是举几个例子,更多的比较方法可以自己探索一下。先看一下评分:

# 评分和排名的关系散点图
plt.figure(figsize=(14,6))
plt.subplot(1,2,1)
plt.scatter(df['评分'], df['0'])
plt.xlabel('评分')
plt.ylabel('排名')
plt.gca().invert_yaxis()    #修改y轴为倒序
# 评分数量直方图
plt.subplot(1,2,2)
plt.hist(df['评分'], bins=14)
plt.xlabel('评分')
plt.ylabel('出现次数')
plt.show()

结果:
在这里插入图片描述

评论人数与排名的关系
# 评价人数与排名的关系散点图
plt.figure(figsize=(14,6)) 
plt.subplot(1,2,1)
plt.scatter(df['评价人数'], df['0'])
plt.xlabel('评价人数')
plt.ylabel('排名')
plt.gca().invert_yaxis()
# 评价人数直方图
plt.subplot(1,2,2)
plt.hist(df['评价人数'], bins=14)
plt.xlabel('评价人数')
plt.ylabel('出现次数')
plt.show()

结果:
在这里插入图片描述


只做了一下初步分析,感兴趣的可以再深入探索。

代码的Github地址:https://github.com/Stevengz/Douban_movies_top250

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值