昨天爬了豆瓣上成龙出道以来的电影得分,发现大哥近些年电影水平确实有些下滑。今天再来搞猫眼,爬一爬猫眼上《龙牌之谜》的用户评论,看看这个口碑不佳的作品,用户的想法是怎么样的
分析猫眼网站
我们首先进入到猫眼,找到对应的电影,地址为:https://maoyan.com/films/343473
页面拖到最下面,发现只有10条最热门的评论,其他评论去哪了?
浏览器手机模式
这里可以使用浏览器手机模式,在 Chrome 浏览器下,按 F12 打开开发者工具,再点击下图中的按钮,即可进入到手机模式
此时再重新刷新网页,发现我们已经神奇的进入到了猫眼的 M 站了
现在再拖动网页到最下部,点击查看全部评论,就可以进入到评论页面,查看全部的评论了。
寻找加载评论的接口
接下来我们继续下拉页面,发现评论是动态加载的。此时经验就非常重要了,我们让页面多加载加载评论几次,就能够发现一个“可疑”的请求,如下
它是以 comments 命名的啊,差不多就是它了。
接下来再查看其 response,确实就是评论内容,而且是清爽的 json 数据,很开心!
分析接口参数
我们先来观察下这个接口
movieid 很显然就是电影的 id,不动
userid 是 -1,应该是我们没有登陆的原因
offset 经过尝试,相当于是 page 的作用,且每次的步长为 15
limit 应该是每次返回数据的数量
其他参数暂时不明
我们把该接口信息放到 postman 中,尝试着调用下
我去掉了 movieid 以外的所有参数,发现是可以调用成功的
查看接口返回数据的最后面,发现一个 paging 字段
"paging": {
"hasMore": true,
"limit": 10,
"offset": 0,
"total": 2838
}
已经清楚的告诉了我们,还有更多数据(“hasMore”: true),每页限制为10(“limit”: 10),当前是第0页(“offset”: 0),总共的数据为2838条(“total”: 2838)。
最后经过测试,type = 3 会每次都会返回 hotComments 这个字段,而当 type = 2 时,则不会返回该字段,于是我选择使用 type 为2来发送请求,那么最终我决定使用的请求 url 就是如下:
offset 作为变量,循环替换即可。
编写爬虫代码
提取 json 数据
def get_json(res):
data_list = []
res_json = json.loads(res)
data = res_json['data']['comments']
for d in data:
content = d['content']
gender = d['gender']
userLevel = d['userLevel']
score = d['score']
try:
if len(d['tagList']) == 0:
ticket = 0
elif len(d['tagList']) == 1:
if d['tagList'][0]['id'] == 4:
ticket = 1
else:
ticket = 0
elif len(d['tagList']) == 2:
ticket == 1
except:
ticket = 0
tmp = [content, gender, userLevel, score, ticket]
data_list.append(tmp)
return data_list
解析 json 就比较简单了,只要做好异常处理即可。
因为评论中有很多 emoji 表情,可以使用正则过滤掉
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
"]+", flags=re.UNICODE)
emoji_pattern1.sub(r'', str1)
最后保存数据到 csv 文件
def save_to_csv(data):
with open('maoyan_data.csv', 'w', encoding='utf-8') as f:
f.write('content,gender,userlevel,score,ticket\n')
for d in data:
try:
row = '{},{},{},{},{}'.format(d[0], d[1], d[2], d[3], d[4])
f.write(row)
f.write('\n')
except:
continue
最后得到的数据如下:
数据可视化分析
性别分布
我们先来看下评论者的性别分布式怎样的
可以看出,男性观众的比例还是多一些,不过大多数都是每有设置性别,隐私工作做得很不多哦
用户等级
不出所料,大部分都是 level-0的用户,普通大众最普通,天下何止千千万。
评分分布
看到结果之后扎心不,打分数量最高的是0分,不知道如果可以打负分,那么情况会是怎么样
评论词云
最后,我们再来做一个词云,看看评论中的高频词汇都有哪些
老规矩,不对评论做过多点评
不过还是忍不住要说一句,评论里面“好看”这个词出现的频率还是非常高的,看评论里有人说是水军,拿钱了,不知道你怎么看呢
最后给出完整的代码: