Python 2.7
IDE Pycharm 5.0.3
PyExcelerator 0.6.4a
可视化 Plotly
请看这里此文备份链接
在上次爬完豆瓣的东西后,感觉锻(zhuang)炼(yi)能(xia)力(bi)之外,貌似并没有实际用处,说实话,我宁可去网页一页页浏览电影也不愿意面对这苍白的文字。所以,分析一下比较好。
根据豆瓣所有的电影,分析各国各地区各类别时间年份评分数量等各个参数之间的联系,大体上进行分析。我会说谎,但是数据不会。
这次爬取的电影总共6323部,因为豆瓣没有全部电影的列表,所以爬取的时候按照每类进行爬取,之后整合,去重,所剩参评影片4007部。(算法略简陋,最后列表大概有十部左右未爬取,但是综合各类别包含关系,误差会变得很小)
简单介绍下情况后,根据所需要的对比数据再进行再分割的处理,这个具体代码片段详见后半部分。好了,接下来轮到plotly大显身手的时候了。
主要比较世界电影和中国,以及中国大陆和中国港台电影之间的差别,分析各参数之间是否存在关联性及对评分产生的影响;数据来源于豆瓣,我对评分不做主观表现,我只对数据进行分析展示,能力偏弱,但图像不弱。
首先放上一张堪忧的世界电影好评趋势图
补充箱线图概念:(@ZhangHongju–箱线图(数据分布)分析 )
世界电影趋势这样,那么中国呢?
中国评分均值和全世界之间的比较
这零零散散的数据也真是少的可怜,上架豆瓣的中国电影数据量略微有点少,参评数目大概为662部左右,其中中国大陆电影为295部,中国港台为367部,趋势和世界电影的趋势差不多,也是颓废状态,但是分数更加低,大概中位数在6分以下 ,那么喜欢电影的朋友肯定知道大陆和港台电影风格还是有很大区别的,至于他们趋势分别是怎样的呢。。。
接下来看下大陆和港台的电影趋势
把时间轴推移到二十世纪八十年代
把时间轴推移到近十余年
豆瓣中国大陆港台的box图趋势放大图2002-2016
对比近十余年同期世界电影
再来看一下上世纪八十年代世界其他电影进展
注意:这里我选取了每年电影必须大于5部的年份进行比较,不然曲线会变得太陡峭。比如橙色这根线,我没有做过处理,在1980年之后,参评电影远超5部之多,所以两线重合,但是在1980年之前,参评数目少于5部,被我切了。。
可以看出,中文的影评数在1980年一直追平世界平均水平,而在2004年之后呈上升趋势,一方面中国电影在此时刻开始数量不断上升,近两年成爆炸方式上升(难怪烂片也增加超多,评分就被相应拉低),来看看近些年电影产量:
所以回到上一个话题,就是电影评论数和年份的关系,一个原因就是拍的片多了,评论会相应上升,但是,这些求得都是均值,所以数量而言并不是非常重要,我!觉!得!是!烂片太多!吐槽也越发严重!!!!!但看着烂片吐槽我赶脚着还是很有意思的哈哈
补充一张图:类型和评论数的关系
中国大陆电影时长
吓得我把世界电影时长拿出来看一下
时长和评分
时长和类型探索
全世界类型及评分
超级八Super8,6.4,27856,科幻/悬疑/惊悚/儿童,美国,英语,2011/6/10,112
所以,这个标签是不是乱贴的呢,还是主演是孩子就是儿童电影呢,当然不是啦,反正我是没搞懂儿童电影和动画电影实质区别,动画电影有些并不适合儿童呢(脑补);
世界电影时长&类型&评分探索–最长时长
大陆和港台的时长&评分及类型分布–最长时长
大陆和港台的时长&评分及类型分布–时长最短
中国大陆和中国港台类型和时长
中国大陆时长&评分&年份三维分布
中国港台时长&评分&年份三维分布
这个大家可能没注意,但是经过我分析(凑巧)发现,中国和世界的标签数目都是不一样的呢,差别还挺大的呢,还特么会影响评分呢!!(科幻/恐怖 这样算两个标签)
全世界的类别标签数目比例
中国的类型标签数目比例
美国的类型标签数目比例
类别和词频
标签数和评分的关系
末世纪爆潮 95年的科幻片,有空我得去看看集成科幻动作悬疑惊悚犯罪音乐奇幻的电影到底是个啥
时间间隔有点长,我脑子差不多糊了,还有什么想知道的,相分析的请留言,可能会得出很有意思结论呢,搞不好还能被大导演看到然后走上人生巅峰赢取白富美呢
最后奉上豆瓣评分9分以上并且评论超过25万的不看就浪费生命系列电影。
还有豆瓣评分6分以下并且有25k人忍着被侮辱的心灵写下影评,看了就浪费生命系列电影。
BTW-祖国总算为我们挣了口气呢~话说我赶脚独立日还是挺好看的啊0.0
好了,接下来就是程序员世界了
代码贴了太长,需要的请下载源码下载
注意:原始代码我基本不怎么用,但是能用;对于类别的连续爬取,其实写个循环就可以了,我再爬电视剧的事后才想到,然后在之后的写入txt也好,写入excel也好,都是用了批量处理的代码,这样就不用查岗了,要知道,一个类别460部电影,即使用静态爬也爬了我25分钟,我还得看着它,爬完一类爬下一类。
内容格式:
殿下,这是利息!殿、利息でござる! 7.2 579 喜剧 日本 日语 2016-05-14 129
代码格式爬取形式:
* -去重:*因为我爬十六个种类全部爬完,然后再聚合起来,其中肯定有重合部分,所以使用set函数去重,当然,你会发现,set函数也无法完全去重,因为爬的时候,评论数目还在变化,只要有一项不同,set就无法去重,结果还是excel直接去重。
- 格式规范化:因为使用plotly展现图形,所以最好的方式就是将其写成excel的,至于怎么写,我下面有代码。
* - 缺失数据处理:*对于此类型数据,我的方法是剔除,当然我用的是最暴力的方法,剔除之后肯定不会对分析有点影响,但是这样的电影很少。比如说各种这样的电影,只要主要信息都在,我还是会爬取的,主要信息是指殿下,这是利息!殿、利息でござる! 7.2 579 喜剧 日本 日语 2016-05-14 129
名字,评分,评论数,类型,国家,语言,时间,时长八个参数。
放上一个标准页面:
清洗函数
计算标签所占比例代码片
#计算总标签数,以及各类所占比例
import re
dicttype = {}
def TypeCount(line):
line = re.sub("\t",",",line)
line = line.split(",")
typeline = line[3]
typelines = typeline.split("/")
for i in typelines:
if i not in dicttype:dicttype[i]=0
dicttype[i] +=1
return dicttype
#测试的line格式,中间是tab键隔开的,制表符
#line = "诺斯费拉图Nosferatu/eineSymphoniedesGrauens 8.3 4202 恐怖/科幻 德国 德语 1922/3/4 94"
f = open("C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ALLMovie.txt")
fr = open("C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ALLMovie_typenum.txt","a")
k=0
lines = f.readlines()
for line in lines:
k +=1
dicttype = TypeCount(line)
x=0
for j in dicttype.values():
x +=j
print "参评影片总数:%s;所有标签总数:%s"%(k,x)
for i in dicttype:
print "%s:%s;类型所占比例:%.2f;标签词频比例:%.2f"%(i,dicttype[i],(dicttype[i])/(k*0.01),(dicttype[i])/(x*0.01))
fr.write("%s,%s,%.2f,%.2f"%(i,dicttype[i],(dicttype[i])/(k*0.01),(dicttype[i])/(x*0.01)))
fr.write('\n')
最后得出如下记录,存入txt或者excel中就可以后续绘图处理了:
# 获取各个种类电影及存储分割,这里是对全部电影的切割,单独国家电影种类切割同理
def Write2txt(line,txtname):
fr = open(txtname,"a")
if line :
fr.write(line)
fr.write("\n")
fr.close()
readpath = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ALLMovie.txt"
writepath = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\%s.txt"
typelist = ["犯罪","动作","歌舞","家庭","鬼怪","剧情","音乐","武侠","运动","战争","黑色电影","传记","历史","情色","儿童","悬疑","灾难","爱情","冒险","奇幻","科幻","古装","惊悚","恐怖","喜剧","动画","同性","西部"]
f = open(readpath)
lines = f.readlines()
for line in lines:
line = line.strip() # 记得去除空格,不然输出存在空格行
lineSplit = line.split("\t")
for type1 in typelist:
if type1 in lineSplit[3]:# 列表第四个为种类
lineCsv = line.replace("\t",",").strip()
Write2txt(lineCsv,writepath%(type1.decode('utf-8')))
上述的式子只需要略微修改参数即可用于分类各个国家的各电影种类并单独存储,接下来是将存储在txt中的数据批量转化存储在excel中(有人会说为啥不一次性写入excel中,因为我懒啊,哈哈,其实,模块化我感觉挺好用,要不是为了能在plotly上用,我才懒得存excel)
# 以"中国大陆爱情.txt"的txt文件为例,其中存在txt中的格式为:苏州河,7.8,80931,剧情/爱情,中国大陆,汉语普通话,2000,83
from pyExcelerator import *
readpath = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\%s.txt"
writepath = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\%s.xls"
typelist = ["犯罪","动作","歌舞","家庭","鬼怪","剧情","音乐","武侠","运动","战争","黑色电影","传记","历史","情色","儿童","悬疑","灾难","爱情","冒险","奇幻","科幻","古装","惊悚","恐怖","喜剧","动画","同性","西部"]
for type1 in typelist:
try:
f = open(readpath%(u"中国大陆"+type1.decode('utf-8')))
lines = f.readlines()
w = Workbook()
sheet1 = w.add_sheet("Sheet1")
i = 0
for line in lines:
linesplist = line.split(",")
j = 0
for linesp in linesplist:
sheet1.write(i,j,linesp.strip().decode('utf-8')) # 需要转化成unicode才能存储
j += 1
i +=1
w.save(writepath%(u"中国大陆"+type1.decode('utf-8')+u"xls")) # 解码成unicode码
except:
print "No type: %s"%type1
# 分割月份单独存储
def Write2txt(line,txtname):
fr = open(txtname,"a")
if line :
fr.write(line)
fr.write("\n")
fr.close()
readpath = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\AllOverTheWorld_alltype_splite\\%s.txt"
writepath = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\AllOverTheWorld_alltype_splite\\%s.txt"
typelist = ["犯罪","动作","歌舞","家庭","鬼怪","剧情","音乐","武侠","运动","战争","黑色电影","传记","历史","情色","儿童","悬疑","灾难","爱情","冒险","奇幻","科幻","古装","惊悚","恐怖","喜剧","动画","同性","西部"]
for typelist1 in typelist:
try:
f = open(readpath%(u"港台"+typelist1.decode('utf-8')))
lines = f.readlines()
for line in lines:
line = line.strip() # 记得去除空格,不然输出存在空格行
lineSplit = line.split(",")
try:
newline ="%s,%s,%s,%s,%s,%s"%(lineSplit[1],lineSplit[2],lineSplit[4],lineSplit[5],lineSplit[6].split("/")[1],lineSplit[7])
Write2txt(newline,writepath%(u"港台"+typelist1.decode('utf-8')+u"OnlyMonth"))
except:
print "Only year No month:%s"%lineSplit[0]
except:
print "No Type :%s"%typelist1
对照一下,粗略看一下有没有处理正确,ok,没什么错误。
# 计算不同年份的评分,评论数,时长平均值并存储excel
from pyExcelerator import *
def Write2txt(line,txtname):
fr = open(txtname,"a")
if line :
fr.write(line)
fr.write("\n")
fr.close()
def txt2excel():
try:
f = open("C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ChinaAllmovieOnlyYearWithAverage.txt")
lines = f.readlines()
w = Workbook()
sheet1 = w.add_sheet("Sheet1")
i = 0
for line in lines:
linesplist = line.split(",")
j = 0
for linesp in linesplist:
sheet1.write(i,j,linesp.strip().decode('utf-8')) # 需要转化成unicode才能存储
j += 1
i +=1
w.save("C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ChinaAllmovieOnlyYearWithAverage.xls") # 解码成unicode码
except:
print "Something wrong"
path = "C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ChinaAllmovieOnlyYear.txt"
lines = open(path).readlines()
for years in range(1900,2017):
TotalStar,TotalComment,TotalTime,i = 0.0,0.0,0.0,0.0
for line in lines:
lineSplit = line.split("\t")
if lineSplit[6] == str(years):
TotalStar +=float(lineSplit[1])
TotalComment +=float(lineSplit[2])
TotalTime +=float(lineSplit[7])
i +=1
try:
if i>4: # 设置影片数目阈值
print "%s:Average star %s"%(years,TotalStar/i)
print "%s:Average comment %s"%(years,TotalComment/i)
print "%s:Average time %s"%(years,TotalTime/i)
print "%s: movieNum %s"%(years,i)
writeline = "%s,%s,%s,%s,%s"%(years,i,TotalStar/i,TotalComment/i,TotalTime/i)
Write2txt(writeline,"C:\\Users\\MrLevo\\PycharmProjects\\test\\M&TCleanData\\ChinaAllmovieOnlyYearWithAverage.txt")
txt2excel()
except:
print "No movie this year %s"%years
之后效果应该是这样的
1981:Average star 7.6125
1981:Average comment 2312.25
1981:Average time 97.0
1981:movieNum 8.0
...
总结这一次的小项目, 经历了数据的收集爬取-数据的清洗规范-数据存储-数据可视化-数据分析,虽然对大神来说非常浅显而没有太多价值,但这也是我这种菜鸡必须需要经历的一步,完完整整,虽有各种波折,所幸全部解决,从中也学到很多,以后编代码思考也会成熟,共勉各位。
防止辛辛苦苦做的50多张图片挂了,这里是备用链接(大)数据分析:豆瓣电影分析报告【1】
python对excel的读取操作
@MrLevo520–Python自定义豆瓣电影种类,排行,点评的爬取与存储(基础)
@MrLevo520–Python自定义豆瓣电影种类,排行,点评的爬取与存储(初级)
@MrLevo520–Python自定义豆瓣电影种类,排行,点评的爬取与存储(进阶上)
@MrLevo520–Python自定义豆瓣电影种类,排行,点评的爬取与存储(进阶下)
@MrLevo520–Python自定义豆瓣电影种类,排行,点评的爬取与存储(高阶上)