豆瓣高分电影信息分析(数据分析)
1、数据抓取
数据集的获取是我们进行数据分析的第一步。现在获取数据的主要途径一般为:现成数据;自己写爬虫去爬取数据;使用现有的爬虫工具爬取所需内容,保存到数据库,或以文件的形式保存到本地。
博主是用python软件爬取的豆瓣高分电影信息,用以获取其中的数据。
1.1网页分析
1.网页URL地址:https://www.douban.com/doulist/240962/
2.根据URL在浏览器打开网页的首页:
3.检查网页:
右击选中检查或按F12,在该窗口中找到存放电影信息的代码
从检查得到的源代码可以看到:
class=‘title’的div标签文本中存放着电影名称
class=‘rating’的div标签中存放着星级,评分和评价人数
class=‘abstract’的div标签中存放着导演,主演,类型,制片国家/地区和年份的信息
1.2获取信息
通过网页分析可知,我们所需要的信息都在HTML页面里,所以我们只需要获取HTML页面相应class类div中的信息就可以了
1.获得网页所有数据:
r=requests.get(link,headers=headers,timeout=10)
soup=BeautifulSoup(r.text,"lxml")
2.获取电影名称:
div_list=soup.find_all(\'div\',class_=\'title\')
for each in div_list:
# 在div中,a标签的text的内容就是中文电影名称
movie_name=each.a.text.strip()
movie_names.append(movie_name)
3.获取电影评分和评价人数:
for each in soup.find_all(\'div\',class_=\'rating\'):
#在div中,第二个span的text内容为评分,第三个span的text的内容为评价人数
a=each.text.split(\'\n\')
#获取字符串中的数字
x=\'\'.join(re.findall(r\'[0-9]\',str(a[3])))
movie_dis.append(x)
movie_grade.append(float(a[2]))
4.获取电影导演,主演,类型,制片国家/地区和年份的信息:
for each in soup.find_all(\'div\',class_=\'abstract\'):
a=each.text
#.匹配任意字符,除了换行符
tp = re.search(r\'类型: (.*)\',a)
#对空值和字符进行处理
if tp==None:
movie_types.append(" ")
else:
movie_types.append(tp.group(1))
actor = re.search(r\'主演: (.*)\',a)
if actor==None:
movie_actor.append(" ")
else:
movie_actor.append(actor.group(1))
director = re.search(r\'导演: (.*)\',a)
if director==None:
movie_director.append(" ")
else:
movie_director.append(director.group(1))
addr = re.search(r\'制片国家/地区: (.*)\',a)
if addr==None:
movie_addr.append(" ")
else:
movie_addr.append(addr.group(1))
year=re.search(r\'年份: (.*)\',a)
if year==None:
movie_year.append(" ")
else:
year_str=year.group(1)
sj=int(year_str[:2])+1
nd=year_str[2]+\'0\'
movie_year.append(str(sj)+\'世纪\'+nd+\'年代\')
2.数据清洗
数据得到手,我们就需要对我们爬取的数据进行清洗工作,为之后的数据分析做铺垫,如果清洗的不到位势必会对之后的数据分析造成影响。
2.1空值处理
对于数据中存在的空值,直接用空字符代替空值数据
#对空值和字符进行处理
if tp==None:
movie_types.append(" ")
else:
movie_types.append(tp.group(1))
actor = re.search(r\'主演: (.*)\',a)
if actor==None:
movie_actor.append(" ")
else:
movie_actor.append(actor.group(1))
director = re.search(r\'导演: (.*)\',a)
if director==None:
movie_director.append(" ")
else:
movie_director.append(director.group(1))
addr = re.search(r\'制片国家/地区: (.*)\',a)
if addr==None:
movie_addr.append(" ")
else:
movie_addr.append(addr.group(1))
year=re.search(r\'年份: (.*)\',a)
if year==None:
movie_year.append(" ")
else:
year_str=year.group(1)
sj=int(year_str[:2])+1
nd=year_str[2]+\'0\'
movie_year.append(str(sj)+\'世纪\'+nd+\'年代\')
2.2格式统一
movies=get_movies("https://www.douban.com/doulist/240962/")
movies_1=pd.DataFrame({\'movie_names\':movies[0],\'movie_types\':movies[1],\'movie_director\':movies[6],\'movie_actor\':movies[5],\'movie_dis\':movies[2],\'movie_grade\':movies[3],\'movie_addr\':movies[4],\'movie_year\':movies[7]})
for i in range(1,4):
#总共3页,一页25个
movies=get_movies("https://www.douban.com/doulist/240962/")
movies_1=pd.DataFrame({\'movie_names\':movies[0],\'movie_types\':movies[1],\'movie_director\':movies[6],\'movie_actor\':movies[5],\'movie_dis\':movies[2],\'movie_grade\':movies[3],\'movie_addr\':movies[4],\'movie_year\':movies[7]})
for i in range(1,4):
#总共3页,一页25个
link="https://www.douban.com/doulist/240962/?start="+str(i*25)
movies=get_movies(link)
movies_1=movies_1.append(pd.DataFrame({\'movie_names\':movies[0],\'movie_types\':movies[1],\'movie_director\':movies[6],\'movie_actor\':movies[5],\'movie_dis\':movies[2],\'movie_grade\':movies[3],\'movie_addr\':movies[4],\'movie_year\':movies[7]}),ignore_index=True)
all_movies_message=movies_1
#将数据写入豆瓣.csv文件中
all_movies_message.to_csv(\'豆瓣.csv\',index=False)
print(all_movies_message)
link="https://www.douban.com/doulist/240962/?start="+str(i*25)
movies=get_movies(link)
movies_1=movies_1.append(pd.DataFrame({\'movie_names\':movies[0],\'movie_types\':movies[1],\'movie_director\':movies[6],\'movie_actor\':movies[5],\'movie_dis\':movies[2],\'movie_grade\':movies[3],\'movie_addr\':movies[4],\'movie_year\':movies[7]}),ignore_index=True)
all_movies_message=movies_1
#将数据写入豆瓣.csv文件中
all_movies_message.to_csv(\'豆瓣.csv\',index=False)
print(all_movies_message)
由于每个电影年分不同,不便于后面分析,故需将年份替换为世纪、年代
year=re.search(r\'年份: (.*)\',a)
if year==None:
movie_year.append(" ")
else:
year_str=year.group(1)
sj=int(year_str[:2])+1
nd=year_str[2]+\'0\'
movie_year.append(str(sj)+\'世纪\'+nd+\'年代\')
3.数据存取
本博客将数据存储到CSV中
3.1存储到CSV文件中
将爬取的信息以列表的形式保存到all_movies_message中,并存储到豆瓣.csv文件中,用以后面的数据分析
movies=get_movies("https://www.douban.com/doulist/240962/")
movies_1=pd.DataFrame({\'movie_names\':movies[0],\'movie_types\':movies[1],\'movie_director\':movies[6],\'movie_actor\':movies[5],\'movie_dis\':movies[2],\'movie_grade\':movies[3],\'movie_addr\':movies[4],\'movie_year\':movies[7]})
for i in range(1,4):
#总共3页,一页25个
link="https://www.douban.com/doulist/240962/?start="+str(i*25)
movies=get_movies(link)
movies_1=movies_1.append(pd.DataFrame({\'movie_names\':movies[0],\'movie_types\':movies[1],\'movie_director\':movies[6],\'movie_actor\':movies[5],\'movie_dis\':movies[2],\'movie_grade\':movies[3],\'movie_addr\':movies[4],\'movie_year\':movies[7]}),ignore_index=True)
all_movies_message=movies_1
#将数据写入豆瓣.csv文件中
all_movies_message.to_csv(\'豆瓣.csv\',index=False)
print(all_movies_message)
存储数据截图:
4.数据分析及可视化
数据表格的参数信息
4.1对每个年代电影上榜数量进行分析
对豆瓣高分电影每个年代上榜电影数量进行分析,可对年代划分为10个等级:
分别为20世纪20年代,20世纪30年代,20世纪40年代,20世纪50年代,20世纪60年代,20世纪70年代,20世纪80年代,20世纪90年代,21世纪00年代,21世纪10年代
y1=len(data[data[\'movie_year\']==\'20世纪20年代\'])
y2=len(data[data[\'movie_year\']==\'20世纪30年代\'])
y3=len(data[data[\'movie_year\']==\'20世纪40年代\'])
y4=len(data[data[\'movie_year\']==\'20世纪50年代\'])
y5=len(data[data[\'movie_year\']==\'20世纪60年代\'])
y6=len(data[data[\'movie_year\']==\'20世纪70年代\'])
y7=len(data[data[\'movie_year\']==\'20世纪80年代\'])
y8=len(data[data[\'movie_year\']==\'20世纪90年代\'])
y9=len(data[data[\'movie_year\']==\'21世纪00年代\'])
y10=len(data[data[\'movie_year\']==\'21世纪10年代\'])
再通过matplotlib数据库进行数据的可视化得到下图:
# 坐标轴上能显示中文
plt.rcParams[\'font.sans-serif\'] = [\'SimHei\']
plt.rcParams[\'axes.unicode_minus\'] = False
# 调节图形大小
plt.rcParams[\'figure.figsize\']=[13,8]
#定义标签
labels=[\'20世纪20年代\',\'20世纪30年代\',\'20世纪40年代\',\'20世纪50年代\',\'20世纪60年代\',\'20世纪70年代\',\'20世纪80年代\',\'20世纪90年代\',\'21世纪00年代\',\'21世纪10年代\']
# 每一小块的值
sizes=[y1,y2,y3,y4,y5,y6,y7,y8,y9,y10]
explode=(0,0,0,0,0,0,0,0,0,0)
plt.pie(
sizes,
explode=explode,
labels=labels,
autopct=\'%1.1f%%\'#数据保留固定小数位
)
# x,y轴刻度设置一致
plt.axis(\'equal\')
plt.title(\'电影年代上榜数量分布图\')
# 右上角显示
plt.legend()
plt.show()
通过图可以很清晰的看到,20世纪70年代高分电影最少,20世纪90年代和21世纪00年代高分电影最多
4.2对每个年代电影评分分析
对豆瓣高分电影的电影评分进行分析,我们可以求出每个年代的电影平均分,进而进行分析:
import matplotlib.pyplot as plt
# 调节图形大小
plt.rcParams[\'figure.figsize\']=[12,8]
grouped=data.groupby(data[\'movie_year\'])[\'movie_grade\'].mean()
grouped.plot()
plt.xticks(rotation=60)#夹角旋转60度
plt.xlabel(\'The movie year\',fontsize=15)#x轴及字号
plt.ylabel(\'The movie grade\',fontsize=15)#y轴及字号
对数据通过matplotlib数据库进行数据的可视化:
从折线图中,我们可以看出每个年代的平均评分都在9.0分以上
4.3对电影评论数前十分析
豆瓣高分电影中,评论越多说明该电影观众越活跃,以电影评论人数进行查找
d1=data.nlargest(10,columns=\'movie_dis\')
d1
对数据通过matplotlib数据库进行数据的可视化:
# 调节图形大小
plt.rcParams[\'figure.figsize\']=[12,8]
grouped=d1.groupby(d1[\'movie_names\']).mean()
grouped.plot.bar()
plt.xticks(rotation=60)#夹角旋转60度
plt.xlabel(\'The movie of number\',fontsize=15)#x轴及字号
plt.ylabel(\'The movie of names\',fontsize=15)#y轴及字号
plt.title(\'The movies of top 10\')
plt.show()
从图中可以看出,肖申克的救赎评论的人最多,说明该电影观众最为活跃,电影感触最深
4.4对电影类型的分析
豆瓣高分电影类型有很多种,通过各个类型出现的次数,可以判断出那种类型最受欢迎
查找各个类型出现的次数
types=\'/\'.join(data[\'movie_types\'])#转化成以‘/’间隔的字符串
types=types.replace(\' \',\'\')#将空格值进行替换
typelist=types.split(\'/\')#进行切割
t=list(set(typelist))#去除重复
count=[]
for i in t:
count.append(typelist.count(i))#统计出现 次数
plt.bar(range(len(count)),count,width=0.5)
对数据通过matplotlib数据库进行数据的可视化:
# 坐标轴上能显示中文
plt.rcParams[\'font.sans-serif\'] = [\'SimHei\']
plt.rcParams[\'axes.unicode_minus\'] = False
# 调节图形大小
plt.rcParams[\'figure.figsize\']=[12,8]
plt.xticks(rotation=60)#夹角旋转60度
plt.xlabel(\'电影类型\',fontsize=15)#x轴及字号
plt.ylabel(\'数量\',fontsize=15)#y轴及字号
plt.xticks(range(len(t)),t)
plt.title(\'电影类型分布情况\')
plt.show()
由柱状图可知,剧情片最受欢迎,其次为喜剧、爱情、家庭片
用词云进行可视化:
# 解决中文乱码问题
font=r\'C:\windows\Fonts\simfang.ttf\'
string=\' \'.join(typelist)
w=wordcloud.WordCloud(background_color=\'white\',font_path=font)
w.generate(string)
w.to_file(r"db.png")
从词云图中可以看出,剧情、爱情、戏剧、犯罪、家庭、冒险的频率比较高