用Python分析《令人心动的offer2》的13万条弹幕,网友们都在吐槽什么?

前言

大家好,我是J哥。

综艺,是我们劳累了一天的放松方式,也是我们饭后的谈资。看着自己喜欢的综艺,时光足够美。而《令人心动的offer》,就是一个不错的综艺选择。

《令人心动的offer》目前为止已经播出了两季,第一季在豆瓣为8.3分,共有5万余人评分,第二季目前评分低于第一季,评分仅7.1分。本文通过爬取《令人心动的offer》第二季13万+弹幕,进行可视化分析和情感分析,完整代码后台回复**「offer」**即可免费获取。

数据获取

《令人心动的offer》第二季在腾讯视频独家播出,目前已播出四期(含面试篇),本文采取分集爬取。弹幕数据爬虫在往期原创文章中已详细讲解,本文不做赘述,感兴趣的朋友可点击:视频弹幕爬虫,看这一篇就够了。以下以爬取面试篇弹幕为例,并给出完整代码:

1#-*- coding = uft-8 -*- 2#@Time : 2020/11/30 21:35 3#@Author : 公众号 菜J学Python 4#@File : tengxun_danmu.py 5 6import requests 7import json 8import time 9import pandas as pd 10 11target_id = "6130942571%26" #面试篇的target_id 12vid = "%3Dt0034o74jpr" #面试篇的vid 13df = pd.DataFrame() 14for page in range(15, 3214, 30): #视频时长共321415 headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'} 16 url = 'https://mfm.video.qq.com/danmu?otype=json&timestamp={0}&target_id={1}vid{2}&count=80'.format(page,target_id,vid) 17 print("正在提取第" + str(page) + "页") 18 html = requests.get(url,headers = headers) 19 bs = json.loads(html.text,strict = False) #strict参数解决部分内容json格式解析报错 20 time.sleep(1) 21 #遍历获取目标字段 22 for i in bs['comments']: 23 content = i['content'] #弹幕 24 upcount = i['upcount'] #点赞数 25 user_degree =i['uservip_degree'] #会员等级 26 timepoint = i['timepoint'] #发布时间 27 comment_id = i['commentid'] #弹幕id 28 cache = pd.DataFrame({'弹幕':[content],'会员等级':[user_degree],'发布时间':[timepoint],'弹幕点赞':[upcount],'弹幕id':[comment_id]}) 29 df = pd.concat([df,cache]) 30df.to_csv('面试篇.csv',encoding = 'utf-8') 31

分别爬取完成后,将四个弹幕csv文件放入一个文件夹中。打开面试篇csv文件,预览如下:

数据清洗

合并弹幕数据

首先,将四个弹幕csv文件进行数据合并,采用concat方法。

1import pandas as pd 2import numpy as np 3df1 = pd.read_csv("/菜J学Python/弹幕/腾讯/令人心动的offer/面试篇.csv") 4df1["期数"] = "面试篇" 5df2 = pd.read_csv("/菜J学Python/弹幕/腾讯/令人心动的offer/第1期.csv") 6df2["期数"] = "第1期" 7df3 = pd.read_csv("/菜J学Python/弹幕/腾讯/令人心动的offer/第2期.csv") 8df3["期数"] = "第2期" 9df4 = pd.read_csv("/菜J学Python/弹幕/腾讯/令人心动的offer/第3期.csv") 10df4["期数"] = "第3期" 11df = pd.concat([df1,df2,df3,df4]) 12

预览下合并后的数据:

1df.sample(10) 2

合并后数据

查看数据信息

1df.info() 2
1<class 'pandas.core.frame.DataFrame'> 2Int64Index: 133627 entries, 0 to 34923 3Data columns (total 8 columns): 4 # Column Non-Null Count Dtype 5--- ------ -------------- ----- 6 0 Unnamed: 0 133627 non-null int64 7 1 用户名 49040 non-null object 8 2 内容 133626 non-null object 9 3 会员等级 133627 non-null int64 10 4 评论时间点 133627 non-null int64 11 5 评论点赞 133627 non-null int64 12 6 评论id 133627 non-null int64 13 7 期数 133627 non-null object 14dtypes: int64(5), object(3) 15memory usage: 9.2+ MB 16

发现数据存在以下几个问题:1.字段名称可调整(个人洁癖)2.Unnamed字段多余 3.用户名字段有缺失值,可填充 4.内容和评论时间点字段类型需要调整 5.评论id对分析无意义,可删除

重命名字段

1df = df.rename(columns={'用户名':'用户昵称','内容':'弹幕内容','评论时间点':'发送时间','评论点赞':'弹幕点赞','期数':'所属期数'}) 2

过滤字段

1#选择需要分析的字段 2df = df[["用户昵称","弹幕内容","会员等级","发送时间","弹幕点赞","所属期数"]] 3

缺失值处理

1df["用户昵称"] = df["用户昵称"].fillna("无名氏") 2

发送时间处理

发送时间字段是秒数,需要改成时间,这里自定义一个time_change函数进行处理。

1def time_change(seconds): 2 m, s = divmod(seconds, 60) 3 h, m = divmod(m, 60) 4 ss_time = "%d:%02d:%02d" % (h, m, s) 5 print(ss_time) 6 return ss_time 7time_change(seconds=8888) 8

将time_change函数应用于发送时间字段:

1df["发送时间"] = df["发送时间"].apply(time_change) 2

设置为需要的时间格式:

1df['发送时间'] = pd.to_datetime(df['发送时间']) 2df['发送时间'] = df['发送时间'].apply(lambda x : x.strftime('%H:%M:%S')) 3

弹幕内容处理

将object数据类型更改为str:

1df["弹幕内容"] = df["弹幕内容"].astype("str") 2

机械压缩去重:

1#定义机械压缩函数 2def yasuo(st): 3 for i in range(1,int(len(st)/2)+1): 4 for j in range(len(st)): 5 if st[j:j+i] == st[j+i:j+2*i]: 6 k = j + i 7 while st[k:k+i] == st[k+i:k+2*i] and k<len(st): 8 k = k + i 9 st = st[:j] + st[k:] 10 return st 11yasuo(st="菜J学Python真的真的真的很菜很菜") 12
1#调用机械压缩函数 2df["弹幕内容"] = df["弹幕内容"].apply(yasuo) 3

特殊字符过滤:

1df['弹幕内容'] = df['弹幕内容'].str.extract(r"([\u4e00-\u9fa5]+)") #提取中文内容 2df = df.dropna() #纯表情弹幕直接删除 3

清洗后数据预览如下:

数据分析

各期弹幕数量对比

《令人心动的offer》第二季已播出四期(含面试篇),第1期:规则升级,实习生面临高压考核弹幕数量最多,达到42422个,面试篇:实习生面试遭灵魂拷问弹幕数量最少,仅为17332个。

1import pyecharts.options as opts 2from pyecharts.charts import * 3from pyecharts.globals import ThemeType 4 5df7 = df["所属期数"].value_counts() 6print(df7.index.to_list()) 7print(df7.to_list()) 8c = ( 9 Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK)) 10 .add_xaxis(df7.index.to_list()) 11 .add_yaxis("",df7.to_list()) 12 .set_global_opts(title_opts=opts.TitleOpts(title="各期弹幕数量",subtitle="数据来源:腾讯视屏 \t制图:菜J学Python",pos_left = 'left'), 13 xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改横坐标字体大小 14 yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改纵坐标字体大小 15 ) 16 .set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='top')) 17 ) 18c.render_notebook() 19

各期弹幕数量

谁是弹幕发射机

用户昵称为想太多de猫几期下来共发射弹幕227个,遥遥领先其他弹幕党,名副其实的弹幕发射机。

1df8 = df["用户昵称"].value_counts()[1:11] 2df8 = df8.sort_values(ascending=True) 3df8 = df8.tail(10) 4print(df8.index.to_list()) 5print(df8.to_list()) 6c = ( 7 Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK)) 8 .add_xaxis(df8.index.to_list()) 9 .add_yaxis("",df8.to_list()).reversal_axis() #X轴与y轴调换顺序 10 .set_global_opts(title_opts=opts.TitleOpts(title="弹幕发送数量TOP10",subtitle="数据来源:腾讯视频 \t制图:菜J学Python",pos_left = 'left'), 11 xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改横坐标字体大小 12 yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改纵坐标字体大小 13 ) 14 .set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='right')) 15 ) 16c.render_notebook() 17

随机抽取想太多de猫弹幕信息,发现其对《令人心动的offer》第二季爱的深沉。弹幕内容透露出其观看视频还是相当之认真,几乎每个弹幕都获得了一定的点赞。

1df[df["用户昵称"]=="想太多de猫"].sample(10) 2

弹幕发射机弹幕抽样

会员等级分布

在观看《令人心动的offer》第二季的观众中,高达74.31%的用户和J哥一样不是腾讯视频的会员,占比第二的会员等级3占5.6%,共计7419人,占比第三的会员等级1占5.39%,共计7153人。

1df2 = df["会员等级"].astype("str").value_counts() 2print(df2) 3df2 = df2.sort_values(ascending=False) 4regions = df2.index.to_list() 5values = df2.to_list() 6c = ( 7 Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK)) 8 .add("", list(zip(regions,values))) 9 .set_global_opts(legend_opts = opts.LegendOpts(is_show = False),title_opts=opts.TitleOpts(title="会员等级分布",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="0.5%",pos_left = 'left')) 10 .set_series_opts(label_opts=opts.LabelOpts(formatter="等级{b}占比:{d}%",font_size=14)) 11 12 ) 13c.render_notebook() 14

会员等级分布

弹幕在讨论些什么

通过对13+弹幕制作词云图,我们发现,弹幕中出现频率较高的词汇有**「丁辉、律师、喜欢、加油、徐律、干饭、撒老师」**等。丁辉作为8个实习生里本科学校最差、年龄最大的成员,从一开始就被观众所热议。徐律作为第1季的带教导师,其雷厉风行又知性温柔的风范,早已赢得广大观众的喜爱。干饭作为最近非常热门的网络词汇,出现在热播综艺中也不足为奇。而撒老师作为这一季的搞笑担当和凡尔赛担当,也被广大观众所热议。

1# 定义分词函数 2def get_cut_words(content_series): 3 # 读入停用词表 4 stop_words = [] 5 with open("/菜J学Python/offer/stop_words.txt", 'r', encoding='utf-8') as f: 6 lines = f.readlines() 7 for line in lines: 8 stop_words.append(line.strip()) 9 # 添加关键词 10 my_words = ['撒老师', '范丞丞','第一季'] 11 for i in my_words: 12 jieba.add_word(i) 13 # 自定义停用词 14 my_stop_words = ['好像', '真的','感觉'] 15 stop_words.extend(my_stop_words) 16 # 分词 17 word_num = jieba.lcut(content_series.str.cat(sep='。'), cut_all=False) 18 # 条件筛选 19 word_num_selected = [i for i in word_num if i not in stop_words and len(i)>=2] 20 return word_num_selected 21# 绘制词云图 22text1 = get_cut_words(content_series=df['弹幕内容']) 23stylecloud.gen_stylecloud(text=' '.join(text1), max_words=100, 24 collocations=False, 25 font_path='字酷堂清楷体.ttf', 26 icon_name='fas fa-square', 27 size=653, 28 #palette='matplotlib.Inferno_9', 29 output_name='./offer.png') 30Image(filename='./offer.png') 31

整体弹幕词云

大家如何评论8个实习生

我们首先看下8位实习生的照片:

在所有弹幕中,丁辉被观众提及次数远超过另外7个实习生,共计9298次,其次是詹秋怡,被观众提及2455次,刘煜成被观众提及最少,仅有526次。

1df8 = df["人物提及"].value_counts()[1:11] 2print(df8.index.to_list()) 3print(df8.to_list()) 4c = ( 5 Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK)) 6 .add_xaxis(df8.index.to_list()) 7 .add_yaxis("",df8.to_list()) 8 .set_global_opts(title_opts=opts.TitleOpts(title="人物提及次数",subtitle="数据来源:腾讯视频 \t制图:菜J学Python",pos_left = 'left'), 9 xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改横坐标字体大小 10 yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改纵坐标字体大小 11 ) 12 .set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='top')) 13 ) 14c.render_notebook() 15

分别绘制8个实习生的弹幕词云图,我们发现,还是有很多观众认可**「丁辉」的,「加油、喜欢、看好、支持」等词出现频率较高;对于性格较为内向的詹秋怡,观众也非常喜欢,从「漂亮、刘亦菲、好看」等高频词可看出,不少人喜欢她是基于颜值;作为来自顶级学府斯坦福的王骁来说,观众呈现两边倒的局势,有人说「王骁好」,也有人认为他是「凡尔赛」;朱一暄也一样,有人觉得她很「可爱」,也有人「讨厌」她;瞿泽林则被表扬「情商高、可爱」;李晋晔的「帅气」被观众赞不绝口,甚至有很多人认为他很像第1季的人气实习生何运晨;人大毕业的王颖飞也被观众夸赞「好看、漂亮」;高分过司考的刘煜成被观众夸赞「专业知识不错」,由于在第3期中被王骁抢话,受了委屈,观众纷纷表示「心疼」**。

情感分析

通过运用百度开源NLP对弹幕内容进行情感分值计算,我们发现,《令人心动的offer》第二季整体情感分值高于0.5,观众表现出较高的积极倾向。会员等级较高的观众越能坚持观看到最后,弹幕点赞量从视频播放开始呈增长趋势,在最后15分钟时骤降。情感分值则表现为视频播放首尾高,中间低。

1import paddlehub as hub 2#这里使用了百度开源的成熟NLP模型来预测情感倾向 3senta = hub.Module(name="senta_bilstm") 4texts = df['弹幕内容'].tolist() 5input_data = {'text':texts} 6res = senta.sentiment_classify(data=input_data) 7df['情感分值'] = [x['positive_probs'] for x in res] 8#重采样至15分钟 9df.index = df['发送时间'] 10data = df.resample('15min').mean().reset_index() 11 12#给数据表添加调色板 13import seaborn as sns 14color_map = sns.light_palette('orange', as_cmap=True) #light_palette调色板 15data.style.background_gradient(color_map) 16

情感分值表

1c = ( 2 Line(init_opts=opts.InitOpts(theme=ThemeType.DARK)) 3 .add_xaxis(data["发送时间"].to_list()) 4 .add_yaxis('情感倾向', list(data["情感分值"].round(2)), is_smooth=True,is_connect_nones=True,areastyle_opts=opts.AreaStyleOpts(opacity=0.5)) 5 .set_global_opts(title_opts=opts.TitleOpts(title="情感倾向",subtitle="数据来源:腾讯视频 \t制图:菜J学Python",pos_left = 'left')) 6 ) 7c.render_notebook() 8

-------------------********************************** End **********-------------**-----********-**********************************

往期精彩文章推荐:

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

艺术与计算机编程发生令人怦然心动的反应

怦艺|绽放多元宇宙,艺术与计算机编程发生令人怦然心动的反应。

4cast

4castpackageloadcsv.KumarAwanish发布:2020122117:43:04.501348作者:KumarAwanish作者邮箱:awanish00@gmail.com首页: