“
《我不是药神》与《邪不压正》最近真的是非常火!到底哪些人喜欢这两部电影呢?今天的数据侠就手把手教你用Python好好分析一下!
《我不是药神》是由文牧野执导,宁浩、徐峥共同监制的剧情片,徐峥、周一围、王传君、谭卓、章宇、杨新鸣等主演 。影片讲述了神油店老板程勇从一个交不起房租的男性保健品商贩程勇,一跃成为印度仿制药“格列宁”独家代理商的故事。
该片于2018年7月5日在中国上映。上映之后获得一片好评,不少观众甚至直呼“中国电影希望”,“《熔炉》、《辩护人》之类写实影片同水准”,诚然相较于市面上一众的抠图贴脸影视作品,《药神》在影片质量上确实好的多,不过我个人觉得《药神》的火爆还有以下几个原因:
影片题材稀少带来的新鲜感,像这类”针砭时弊” 类影视作品,国内太少。
顺应潮流,目前《手机》事件及其带来的影响和国家层面文化自信的号召以及影视作品水平亟待提高的大环境下,《药神》的过审与上映本身也是对该类题材一定程度的鼓励。
演员靠谱、演技扎实,这个没的说,特别是王传君的表现,让人眼前一亮。
本文通过爬取《我不是药神》和《邪不压正》豆瓣电影评论,对影片进行可视化分析。
截止7月13日:《我不是药神》豆瓣评分:8.9 分,猫眼:9.7 分,时光网:8.8 分 。
截止7月13日: 《邪不压正》 豆瓣评分:7.2 分,猫眼:7.4 分,时光网:7.3 分 。
豆瓣的评分质量相对而言要靠谱点,所以本文数据来源也是豆瓣。
▍0.需求分析
+获取影评数据
+清洗分析存储数据
+分析展示影评城市来源、情感
+分时展示电影评分趋势
+当然主要是用来熟练pandas和爬虫及可视化技能
▍1.前期准备
1.1 网页分析
豆瓣从2017.10月开始全面禁止爬取数据,仅仅开放500条数据,白天1分钟最多可以爬取40次,晚上一分钟可爬取60次数,超过此次数则会封禁IP地址。
tips发现
实际操作发现,点击影片评论页面的后页时,url中的一个参数start会加20,但是如果直接赋予’start’每次增加10,网页也是可以存在的!
登录状态下,按网页按钮点击后页,start最多为480,也就是20*25=500条
非登录状态下,最多为200条。
登录状态下,直接修改url的方法可以比官方放出的评论数量多出了一倍!!!
1.2 页面布局分析
本次使用xpath解析,因为之前的博客案例用过正则,也用过beautifulsoup,这次尝试不一样的方法。
如下图所示,本此数据爬取主要获取的内容有:
评论用户ID
评论内容
评分
评论日期
用户所在城市
1.3城市信息获取
评论页面没有城市信息,因此需要通过进入评论用户主页去获取城市信息元素。
通过分析页面发下,用户ID名称里隐藏着主页链接!所以我的思路就是request该链接,然后提取城市信息。
▍2.数据获取-爬虫
2.1 获取cookies
因为豆瓣的爬虫限制,所以需要使用cookies作身份验证,通过chrome获取cooikes位置如下图:
2.2 加载cookies与headers
下面的cookie被修改了,诸君需要登录后自己获取专属cookieo(∩_∩)o
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
cookies = {'cookie':'bid=GOOb4vXwNcc; douban-fav-remind=1; viewed="27611266_26886337"; ps=y; ue="citpys原创分享@163.com"; " \
"push_noty_num=0; push_doumail_num=0; ap=1; loc-last-index-location-id="108288"; ll="108288"; dbcl2="187285881:N/y1wyPpmA8"; ck=4wlL'}
url ="https://movie.douban.com/subject/"+ str(id) +"/comments?start="+ str(page *10) +"&limit=20&sort=new_score&status=P"
res = requests.get(url, headers=headers, cookies=cookies)
res.encoding ="utf-8"
if(res.status_code ==200):
print("\n第{}页短评爬取成功!".format(page +1))
print(url)
else:
print("\n第{}页爬取失败!".format(page +1))
一般刷新页面后,第一个请求里包含了cookies。
2.3 延时反爬虫
设置延时发出请求,并且延时的值还保留了2位小数(自我感觉模拟正常访问请求会更加逼真…待证实)。
time.sleep(round(random.uniform(1, 2), 2))
2.4 解析需求数据
这里有个大bug,找了好久!
因为有的用户虽然给了评论,但是没有给评分,所以score和date这两个的xpath位置是会变动的。
所以需要加判断,如果发现score里面解析的是日期,证明该条评论没有给出评分。
name = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/a/text()'.format(i))
# 下面是个大bug,如果有的人没有评分,但是评论了,那么score解析出来是日期,而日期所在位置spen[3]为空
score = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/span[2]/@title'.format(i))
date= x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/span[3]/@title'.format(i))
m ='\d-\d-\d'
match= re.compile(m).match(score[])
ifmatchisnotNone:
date= score
score = ["null"]
else:
pass
content = x.xpath('//*[@id="comments"]/div[{}]/div[2]/p/span/text()'.format(i))
id = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/a/@href'.format(i))
try:
city = get_city(id[], i) # 调用评论用户的ID城市信息获取
except IndexError:
city =" "
name_list.append(str(name[]))
score_list.append(str(score[]).strip('[]\'')) # bug 有些人评论了文字,但是没有给出评分
date_list.append(str(date[]).strip('[\'').split(' ')[])
content_list.append(str(content[]).strip())
city_list.append(city)
2.5 获取电影名称
从url上只能获取电影的subject的8位ID数值,引起需要自行解析网页获取ID号对应的电影名称,该功能是后期改进添加的,因此为避免现有代码改动多(偷个懒),采用了全局变量赋值给movie_name,需要注意全局变量调用时,要加global声明一下。
pattern = re.compile('
.*?
.*?(.*?) 短评', re.S)
globalmovie_name
movie_name = re.findall(pattern, res.text)[]# list类型
▍3.数据存储
因为数据量不是很大,因为普通csv存储足够,把获取的数据转换为pandas的DF格式,然后存储到csv文件中。
infos = {'name': name_list,'city': city_list,'content': content_list,'score': score_list,'date': date_list}
data = pd.DataFrame(infos, columns=['name','city','content','score','date'])
data.to_csv(str(ID) +"_comments.csv")
因为考虑到代码的复用性,所以main函数中传入了两个参数。
一个是待分析影片在豆瓣电影中的ID号(这个可以在链接中获取到,是一个8位数。
一个是需要爬取的页码数,一般设置为49,因为网站只开放500条评论。
另外有些电影评论有可能不足500条,所以需要调整,之前尝试通过正则匹配分析页面结构。
▍4.数据清洗
爬取出来的结果如下:
4.1 城市信息清洗
从爬取的结果分析可以发现,城市信息数据有以下问题:
有城市空缺
海外城市
乱写
领取专属 10元无门槛券
私享最新 技术干货