600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 海报人脸个数与豆瓣电影评分的相关分析【python爬虫+人脸识别】

海报人脸个数与豆瓣电影评分的相关分析【python爬虫+人脸识别】

时间:2019-01-16 18:39:11

相关推荐

海报人脸个数与豆瓣电影评分的相关分析【python爬虫+人脸识别】

学习python有一段时间了,刚好有空自己搞一个案例练练手,于是诞生了这篇记录博。案例目的是研究电影海报上的人脸个数与这部电影豆瓣评分有没有一定的关系,当然这个分析结果不会有太大的商业效果,因为豆瓣评分不可控因素比较大,而且在人脸识别过程中还是有一定的偏差,这篇博文主要是记录在爬取电影海报中遇到的一些问题及解决方法,并且做法可能不是最简便的。

如有不对,欢迎指正。

下面进入正题。

step1:selenium+beautifulsoup爬取电影海报及评分

爬取的网页是豆瓣电影页面每一部电影的海报,如下

本人爬虫新手,打算用urllib.request模块爬取海报链接,但是在返回的源码是不完整的,我能在网页上能找到海报链接的代码段,但是返回的源码并没有找到,百度之后发现这部分代码是js动态代码,我把它理解成反爬的一种形式,在广大网友的建议下选择selenium爬取。

1.1安装selenium+webdriver

selenium的安装很简单,打开anaconda prompt,输入pip install selenium搞定。

webdriver,因为我的Chrome浏览器版本为76,所以安装Chromedriver76.0.3809.x,选择win32版本就够了,适用于32位或64位。然后将chromedriver.exe放入Chrome.exe所在的目录,并且将这个目录加入环境变量。准备工作完成,下面正式进行爬取。上代码!

from bs4 import BeautifulSoupfrom selenium import webdriverimport pandas as pdbrowser = webdriver.Chrome() # Get local session of firefoxbrowser.get("/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0") # Load page# print(browser.page_source) 检查打印的源码确实包含了之前没有显示的那一部分,成功!

这段代码运行之后会自动用Chrome浏览器打开这个网址,然后你在这个网页上的操作都会被记录,最终的代码量取决于你什么时候停止对该网页的操作,比如这个网站有加载更多这个选项,如果你选择加载更多,就会有新的电影显示出来,那代码自然会增加,这也是动态爬取的一种意思,这也是selenium的强大之处

为了获取更多的数据,我爬取了300部电影,虽然样本量不算大,但是爬取也是需要时间的,更多的数据意味着要花更多的时间。

我们先来看看海报链接所在的代码段,阴影部分就是要爬取的,为了让自己知道是哪一部电影,把alt='xxxx’部分也爬取了,链接在img标签下,并且只有jpg格式的才是海报链接,所以爬取之后还需要筛选,上代码

img_list = [] #建一个列表来保存海报链接url_temp = browser.page_sourcebs_obj = BeautifulSoup(url_temp,'html.parser',from_encoding='utf-8')# print(bs_obj)link_list = bs_obj.find_all('img')for each in link_list:img_list.append([str(each.get('alt')),str(each.get('src'))])# print(img_list)img_jpglink = [i for i in img_list if 'jpg' in i[1] ]print(len(img_jpglink))

1.2 处理图片大小

细心的话会发现,这个网址上的海报图片太小了,分辨率太低不利于提高人脸识别的准确率,所以研究一番后,发现图片地址如果要放大只需将海报链接中‘s_ratio_poster’换成‘m’即可放大,写到这里,还是得感慨一下自己经验不够,因为我本来打算一直爬取海报链接里层去获得更大的海报,但是大海报的格式是webp结尾的,直接改jpg是不行的,所以百度了很多方法,后来选择在线将webp转成二进制再转成jpg,过程可谓缓慢且坑多,后来灵感一现,找一找大图jpg和小图jpg的区别,还真让我找到了,感动天地!这也就是爬虫的乐趣吧,成功了就很有成就感。

# 将小图变大图,建立一个列表来保存# bigger_poster_link = []for each in img_jpglink:each[1] = each[1].replace('s_ratio_poster','m')# print(img_jpglink) 检查一下链接是否可用,可用即成功

效果如下:

放大倍数很满意!!!接下来是评分

1.3 爬取电影评分

还是先来看看评分所在代码段,标签是p,但是如果查找p的话会出现很多不相关的结果,观察源代码后发现这一段只有标签p,而其他以标签p的代码段都有class属性,所以尝试查找标签为p,class=None,结果理想准确!为了分辨出评分属于哪一部电影,也把这里的电影名称也爬取了,于是坑又出现了,这里代码可以看出就是有空白格以及莫名的换行,机智的我想到把这些用replace函数全部换成空白格就好

grade_list = list(bs_obj.find_all('p',class_=None))hhh = [] # 用来保存电影评分for i in grade_list:hhh.append(i.get_text().replace('\n',' ').replace(' ',''))# 结果是这样的:#'寄生虫8.9',#'恶人传7.7',#'三更半夜居然要香蕉爱的真实故事6.7',#'作家的谎言:笔忠诱罪6.7',# '绿皮书8.9',# '追龙Ⅱ5.5',.....

但是我想讲电影名称和分数分开,变成两个字段,纯split是无法做到的,百度之后采用广大网友建议的re模块+正则表达式解决,re.sub("[A-Za-z0-9.]", “”, string)提取汉字,由于评分是小数,所以采用re.findall(r"\d+.?\d*", string),本以为一切顺利呀,但是看了结果发现评分是一个列表形式,[9.0]这样看着是不是特别别扭,于是放弃了这种提取方式,但是搜了很多都没有更合适的,于是返回去看爬取的结果,又灵光一现发现分数都是以统一x.x的形式,这说明什么?说明可以用切片啊!!!

写到这里,突然想到一句话:不愧是我

虽然我这里风轻云淡描述了这个过程,但是当时被正则表达式虐的不行啊,对于小白写正则表达式实在残忍

res = [] # 保存评分for i in hhh:res.append({'电影名称':i[:-3],'评分':i[-3:]})# print(res)

到这里,爬取数据结束~

step 2:cognitive-face人脸识别

2.1 准备工作安装必要模块

cognitive-face模块是需要微软人脸识别服务的api的,免费的,但是有次数限制,不过这种小case足够了。另外关于这个网站的操作可以看看教程,不会太难申请链接在此

还有一点需要注意,注册完成后得到key有两个,用哪一个都可以,另外还有个Endpoint,这个是BaseUrl,使用这个模块不止要key,还要这个Endpoint链接,否则会报错,但是我百度出来的使用教程都没有提到这一点,希望这篇博客能帮助到要用这个模块的人吧~

cognitive-face的安装也简单,pip install cognitive_face完成

上代码~

import cognitive_face as CFKEY = 'xxxxxxxxxxxxxxxx' # 这里替换一个自己可用的keyCF.Key.set(KEY)BASE_URL = 'https://xxxxxxxxxx.xxxxxxxxxxxxxx' # 这里填上你的Endpoint地址CF.BaseUrl.set(BASE_URL)num_face = []n_face = -1for img_link in img_jpglink:try:face_list = CF.face.detect(img_link[1])n_face = len(face_list)print('电影名称:%s 海报人脸个数:%d个'% (img_link[0],n_face))num_face.append({'电影名称':img_link[0],'人脸个数':n_face})except CF.util.CognitiveFaceException:print('电影名称:%s ,无效图片' % img_link[0])# 部分结果展示:#电影名称:寄生虫 海报人脸个数:0个#电影名称:恶人传 海报人脸个数:3个#电影名称:三更半夜居然要香蕉 爱的真实故事 海报人脸个数:3个#电影名称:作家的谎言:笔忠诱罪 海报人脸个数:5个#电影名称:绿皮书 海报人脸个数:2个

寄生虫海报其实是有人脸的,但是这种打了码的脸cognitive-face并不能识别出来,我观察了海报,侧脸的人也是无法识别的,或许针对这个cognitive-face有更好的升级而我还不知道,希望有缘的朋友看到这里可以提供帮助,感激不尽!!

2.2 整理数据

这部分主要是为可视化准备的

df_n_face = pd.DataFrame(num_face)df_res = pd.DataFrame(res)df_img_jpglink = pd.DataFrame(img_jpglink,columns=['电影名称','图片链接'])df_data = pd.merge(df_img_jpglink,df_n_face,on='电影名称')df_final = pd.merge(df_data,df_res,on='电影名称')# 去除无效人脸df_final = df_final[df_final['人脸个数'] != -1]

step3 :matplotlib可视化结果

前面说过300部电影这个数据是不够大的,可视化的结果告诉我们海报人脸个数仿佛和评分没啥关系,当然这也不能说失败,因为一切因素都可以成为相关分析的对象,但是如果样本量能达到2000以上出来的效果还是比较好,可以发现海报人脸个数和评分还是有那么点关系,人脸越多的话评分比较低,越少的评分较高,所以在设计海报的时候,不宜将太多的人物放上去。

from matplotlib import pyplot as pltdf_final[['评分']] = df_final[['评分']].astype('float',inplace=True)face_score = df_final['评分'].groupby(by=df_final['人脸个数']).mean()face_score.name = 'Score'face_score.index.name = 'Number of Face'face_score.plot(kind='bar')plt.show()

可视化结果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。