Python分析《奔跑吧》21307 条热评,看看大家都在吐槽些什么

大邓和他的Python

共 2146字,需浏览 5分钟

 · 2020-12-22


腾讯课堂 | Python网络爬虫与文本分析(戳一戳)~~


「《奔跑吧》第五季」已经播出两期了,节目以“黄河生态经济带”沿线地区为依托,通过创新游戏设置、直播带货扶贫等新形式,展现黄河流域的重要地位,描绘黄河生态经济带城市“文化之美”。

然而,网友貌似并不买账,邓超、郑凯等退出跑男后,「收视明显不如以前」,而吐槽貌似有所增加。为了了解吃瓜群众们对于跑男的看法,我爬了爬腾讯视频关于跑男的评论,并做了简单文本「可视化分析」

数据获取

腾讯视频评论要点击「查看更多评论」才能加载更多数据,很明显是一个动态网页,评论内容使用了「Ajax动态加载技术」。因此,我们需要找到「真实URL」,然后再请求数据。通过真实URL获取到cursor=?_=?这两个参数即可。核心代码如下:

def main():
#初始页面的_=?
page=1607948139253
#初始待刷新页面的cursor=?
lastId="0"
for i in range(1,1000):
time.sleep(1)
html = get_content(page,lastId)
#获取评论数据
commentlist=get_comment(html)
print("------第"+str(i)+"轮页面评论------")
k = 0
for j in range(1,len(commentlist)):
comment = commentlist[j]
k += 1
print('第%s条评论:%s'%(k,comment))
#获取下一轮刷新页ID
lastId=get_lastId(html)
page += 1

if __name__ == '__main__':
main()

数据处理

导入相关包

import jieba
import re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.globals import ThemeType
import stylecloud
from IPython.display import Image

导入评论数据

分别爬取了两期评论,因此需要分别读取并合并所有数据。

df1 = pd.read_csv('/菜J学Python/腾讯评论/paonan.csv',names=['评论内容'])
df2 = pd.read_csv('/菜J学Python/腾讯评论/paonan1.csv',names=['评论内容'])
df = pd.concat([df1,df2])
df.head(10)
数据预览

查看数据信息

print('共有评论数:',df.shape[0],'条')
共有评论数:21307 条
df.info()
df['评论内容'] = df['评论内容'].astype('str')
<class 'pandas.core.frame.DataFrame'>
Int64Index:
21307 entries, 0 to 11833
Data columns (total 1 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 评论内容 21199 non-null object
dtypes: object(1)
memory usage: 332.9+ KB

删除重复评论

df = df.drop_duplicates()

删除缺失数据

df = df.dropna()

增加评论类型

人为划分评论类型,20字以下为短评,20-50字为中评,50字以上为长评。

cut = lambda x : '短评' if len(x) <= 20 else ('中评' if len(x) <=50 else '长评')
df['评论类型'] = df['评论内容'].map(cut)

提取演员关键词

根据评论内容关键词,提取出人物提及字段。

tmp=[]
for i in df["评论内容"]:
if "黑牛" in i:
tmp.append("李晨")
elif "杨颖" in i:
tmp.append("杨颖")
elif "沙溢" in i:
tmp.append("沙溢")
elif "坤" in i:
tmp.append("蔡徐坤")
elif "毅" in i:
tmp.append("成毅")
elif "一桐" in i:
tmp.append("李一桐")
else:
tmp.append("其他")
df['人物提及'] = tmp

机械压缩去重

定义一个机械压缩函数:

def yasuo(st):
for i in range(1,int(len(st)/2)+1):
for j in range(len(st)):
if st[j:j+i] == st[j+i:j+2*i]:
k = j + i
while st[k:k+i] == st[k+i:k+2*i] and k k = k + i
st = st[:j] + st[k:]
return st
yasuo(st="菜J学Python真的真的真的很菜很菜")

调用函数,对评论内容进行机械压缩去重:

df["评论内容"] = df["评论内容"].apply(yasuo)

特殊字符处理

用正则表达式提取出中文:

df['评论内容'] = df['评论内容'].str.extract(r"([\u4e00-\u9fa5]+)")
df = df.dropna() #纯表情弹幕直接删除

过滤掉评论字数少于四个字的评论:

df = df[df["评论内容"].apply(len)>=4]
df = df.dropna()

数据可视化

整体评论情况

# 绘制词云图
text1 = get_cut_words(content_series=df['评论内容'])
stylecloud.gen_stylecloud(text=' '.join(text1), max_words=1000,
collocations=False,
font_path='演示悠然小楷.ttf',
icon_name='fas fa-video',
size=653,
#palette='matplotlib.Inferno_9',
output_name='./评论.png')
Image(filename='./评论.png')

通过对所有评论进行词云图绘制,我们发现「成毅」提及最多,对于最新跑男的看法,大家表现出非一致的看法。有人说「好看、喜欢」,有人说「没意思」。另外,评论中还多次提到往期节目中的嘉宾,如「陈赫、郑凯、郭麒麟」等,没有比较就没有伤害,很多人还是更喜欢往期的跑男的。

评论类型分布

df2 = df.groupby('评论类型')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="评论类型占比",subtitle="数据来源:腾讯视频",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()

短评占据「81.99%」,仅有2.65%的观众给出了50字以上的评论。

演员角色提及

df8 = df["人物提及"].value_counts(ascending=True)[:6]
print(df8.index.to_list())
print(df8.to_list())
c = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add_xaxis(df8.index.to_list())
.add_yaxis("",df8.to_list()).reversal_axis()
.set_global_opts(title_opts=opts.TitleOpts(title="人物提及次数",subtitle="数据来源:腾讯视频 \t制图:菜J学Python",pos_left = 'top'),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改横坐标字体大小
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)), #更改纵坐标字体大小
)
.set_series_opts(label_opts=opts.LabelOpts(font_size=16,position='right'))
)
c.render_notebook()

新成员「成毅」被观众提及次数最多,达到790次,其次是「蔡徐坤」,被提及452次。李晨被提及次数最少。

成毅评论词云

cy = df[df["人物提及"]=="成毅"]
text = get_cut_words(content_series=cy['评论内容'])
stylecloud.gen_stylecloud(text=' '.join(text), max_words=500,
collocations=False,
font_path='演示悠然小楷.ttf',
icon_name='fas fa-comments',
#palette='matplotlib.Inferno_9',
size=653,
output_name='./dinghui.png')
Image(filename='./dinghui.png')

成毅在新一季跑男的表现被网友广泛议论,认可他的观众「喜欢、期待、可爱」他的表现。也有相当多的观众觉得他「智商」有问题,是个「游戏黑洞」,而且很「搞笑」

情感分析

这里使用了百度开源的成熟「NLP模型」来预测情感倾向,准确率相对还可以,通过模型计算出评论的「积极分值」「消极分值」

import paddlehub as hub
senta = hub.Module(name="senta_bilstm")
texts = df['评论内容'].tolist()
input_data = {'text':texts}
res = senta.sentiment_classify(data=input_data)
df['积极分值'] = [x['positive_probs'] for x in res]
df['消极分值'] = [x['negative_probs'] for x in res]

对积极分值求平均值,我们发现「低于0.5」,可见,观众对新一季跑男并不太感冒。

df["积极分值"].mean()
0.47351818330338175

通过积极分值和消极分值的判断,我们可以进一步判断出每个评论的「情感倾向」

t = df.eval("积极分值-消极分值")
df["情感倾向"] = np.where(t > 0, "正面", np.where(t == 0, "中立", "负面"))
df

观众对成毅的情感倾向

df2 = df[df["人物提及"]=="成毅"].groupby('情感倾向')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="观众对成毅情感倾向",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()
df[df["人物提及"]=="成毅"].sample(10)

观众对蔡徐坤的情感倾向

df2 = df[df["人物提及"]=="蔡徐坤"].groupby('情感倾向')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="观众对蔡徐坤情感倾向",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()
df[df["人物提及"]=="蔡徐坤"].sample(10)

观众对李晨的情感倾向

df2 = df[df["人物提及"]=="李晨"].groupby('情感倾向')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="观众对李晨情感倾向",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()
df[df["人物提及"]=="李晨"].sample(5)

观众对杨颖的情感倾向

df2 = df[df["人物提及"]=="杨颖"].groupby('情感倾向')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="观众对杨颖情感倾向",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()
df[df["人物提及"]=="杨颖"].sample(10)

观众对沙溢的情感倾向

df2 = df[df["人物提及"]=="沙溢"].groupby('情感倾向')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="观众对沙溢情感倾向",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()
df[df["人物提及"]=="沙溢"].sample(10)

观众对李一桐的情感倾向

df2 = df[df["人物提及"]=="李一桐"].groupby('情感倾向')['评论内容'].count()
df2 = df2.sort_values(ascending=False)
regions = df2.index.to_list()
values = df2.to_list()
c = (
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK))
.add("", zip(regions,values),radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="观众对李一桐情感倾向",subtitle="数据来源:腾讯视频\t制图:菜J学Python",pos_top="2%",pos_left = 'center'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%",font_size=18))
)
c.render_notebook()
df[df["人物提及"]=="李一桐"].sample(10)

近期文章

Python网络爬虫与文本数据分析
bsite库 | 采集B站视频信息、评论数据
爬虫实战 | 采集&可视化知乎问题的回答
pdf2docx库 | 转文件格式,支持抽取文件中的表格数据
rpy2库 | 在jupyter中调用R语言代码
tidytext | 耳目一新的R-style文本分析库
reticulate包 | 在Rmarkdown中调用Python代码
plydata库 | 数据操作管道操作符>>
plotnine: Python版的ggplot2作图库
七夕礼物 | 全网最火的钉子绕线图制作教程
读完本文你就了解什么是文本分析
文本分析在经管领域中的应用概述  
综述:文本分析在市场营销研究中的应用
plotnine: Python版的ggplot2作图库
小案例: Pandas的apply方法  
stylecloud:简洁易用的词云库 
用Python绘制近20年地方财政收入变迁史视频  
Wow~70G上市公司定期报告数据集
漂亮~pandas可以无缝衔接Bokeh  
YelpDaset: 酒店管理类数据集10+G  

    分享”和“在看”是更好的支持!



浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报