作为一名长期关注数据分析和可视化领域的技术博主,我最近完成了一个基于B站视频数据的分析项目。这个项目最初是作为某位同学的毕业设计而构思的,但在实际开发过程中,我发现其中蕴含的分析思路和方法论对广大数据分析爱好者都具有很好的参考价值。
B站作为国内领先的年轻人文化社区,其视频数据反映了当下年轻人的兴趣偏好和内容消费趋势。通过对这些数据的挖掘,我们不仅可以了解各分区内容的受欢迎程度,还能发现用户互动行为的深层次特征。本项目从整体数据分析和单一视频分析两个维度入手,运用Python生态中的数据分析和可视化工具,对B站视频数据进行了全面剖析。
B站视频数据可以通过官方API或爬虫技术获取。考虑到毕业设计的实际需求和API调用限制,本项目采用了爬虫方案。核心爬虫代码使用Python的requests库和BeautifulSoup库实现,主要抓取以下数据字段:
提示:在实际爬取过程中,需要注意设置合理的请求间隔(建议不低于3秒),并添加User-Agent等请求头信息,以避免被反爬机制拦截。
原始数据往往存在各种质量问题,需要进行系统的清洗和转换:
python复制# 基础数据质量检查
df.info() # 查看数据概览
df.isnull().sum() # 检查缺失值
df.nunique() # 检查唯一值数量
df.dtypes # 检查数据类型
# 处理全站排名数据(可能存在重复)
df_nall = df.loc[df['区类别'] != '全站']
df_nall['区类别'].value_counts()
# 提取Top100视频
df_top100 = df_nall.sort_values(by='分数', ascending=False)[:100]
# 按分区聚合数据
df_type = df_nall.drop(['作者','视频编号','标签名称','视频名称','排名'], axis=1)
gp_type = df_type.groupby('区类别').sum().astype('int')
type_all = gp_type.index.tolist()
数据清洗过程中需要特别注意以下几点:
播放量是衡量视频受欢迎程度的核心指标。我们首先对各分区播放量进行了统计分析:
python复制# 计算各分区播放量(单位:亿次)
play = [round(i/100000000, 2) for i in gp_type['播放次数'].tolist()]
# 绘制饼图
pie = (
Pie()
.add(
"",
[list(z) for z in zip(type_all, play)],
radius=["40%", "75%"],
)
.set_global_opts(
title_opts=opts.TitleOpts(title="各分区播放量情况 单位:亿次"),
legend_opts=opts.LegendOpts(
orient="vertical", pos_top="15%", pos_left="2%"
),
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
pie.render_notebook()
分析结果显示,播放量排名前三的分区分别是:
这个结果有些出人意料,传统认知中B站以动漫内容起家,但实际数据显示生活类内容的播放量已经超过了动画类。这可能反映了B站用户群体的扩展和内容生态的多元化发展趋势。
B站的"三连"(硬币、点赞、收藏)是用户表达喜好的重要方式。我们通过柱状图对比了各分区的三连数据:
python复制# 计算三连数据(单位:百万次)
coin_all = [round(i/1000000, 2) for i in gp_type['硬币数'].tolist()]
like_all = [round(i/1000000, 2) for i in gp_type['点赞数'].tolist()]
favourite_all = [round(i/1000000, 2) for i in gp_type['喜欢人数'].tolist()]
# 绘制柱状图
bar = (
Bar()
.add_xaxis(type_all)
.add_yaxis("硬币", coin_all)
.add_yaxis("点赞", like_all)
.add_yaxis("收藏", favourite_all)
.set_global_opts(
title_opts=opts.TitleOpts(title="各分区三连情况"),
yaxis_opts=opts.AxisOpts(name="次/百万"),
xaxis_opts=opts.AxisOpts(name="分区", axislabel_opts={"rotate":45})
)
)
bar.render_notebook()
从图表中可以观察到几个有趣的现象:
弹幕、评论和转发代表了用户的不同参与程度。我们使用折线图展示了各分区的社交互动情况:
python复制# 计算社交互动数据(单位:十万次)
danmaku_all = [round(i/100000, 2) for i in gp_type['弹幕数'].tolist()]
reply_all = [round(i/100000, 2) for i in gp_type['评论数'].tolist()]
share_all = [round(i/100000, 2) for i in gp_type['转发数'].tolist()]
# 绘制折线图
line = (
Line()
.add_xaxis(type_all)
.add_yaxis("弹幕", danmaku_all, label_opts=opts.LabelOpts(is_show=False))
.add_yaxis("评论", reply_all, label_opts=opts.LabelOpts(is_show=False))
.add_yaxis("转发", share_all, label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="弹幕、评论、转发情况"),
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
yaxis_opts=opts.AxisOpts(name="人数 单位:十万"),
xaxis_opts=opts.AxisOpts(name="分区", axislabel_opts={"rotate":45})
)
)
line.render_notebook()
分析发现:
通过词云图可视化视频标签,可以直观了解B站的热门话题:
python复制# 提取并统计标签
tag_list = ','.join(df_nall['标签名称']).split(',')
tags_count = pd.Series(tag_list).value_counts()
# 绘制词云图
wordcloud = (
WordCloud()
.add("", [list(z) for z in zip(tags_count.index, tags_count)], word_size_range=[10, 100])
.set_global_opts(title_opts=opts.TitleOpts(title="热门标签"))
)
wordcloud.render_notebook()
词云图显示,"原创"、"搞笑"、"日常"等标签出现频率最高,这与生活区内容占主导的分析结果一致。同时也能看到一些特定兴趣标签,如"动漫"、"游戏"、"科技"等,反映了B站多元化的内容生态。
我们首先分析了Top100视频的类别分布:
python复制# 统计Top100视频的类别分布
top100_type_dist = df_top100['区类别'].value_counts()
# 可视化代码与整体分析类似,此处省略
结果显示,Top100视频的类别分布与整体分布基本一致,生活区、动画区和鬼畜区仍然占据主导地位。这说明各分区的内容质量相对均衡,热门视频的产出与分区规模成正比。
通过雷达图对比了Top100视频在各分区的平均互动质量:
python复制# 计算各分区平均三连数据
gp_triple_quality = df_top100.groupby('区类别')[['硬币数','喜欢人数','点赞数']].mean().astype('int')
gp_index = gp_triple_quality.index.tolist()
gp_coin = gp_triple_quality['硬币数'].values.tolist()
gp_favorite = gp_triple_quality['喜欢人数'].values.tolist()
gp_like = gp_triple_quality['点赞数'].values.tolist()
# 绘制雷达图
radar = (
Radar()
.add_schema(
schema=[opts.RadarIndicatorItem(name=name, max_=600000) for name in gp_index]
)
.add("硬币数", [gp_coin], color='#40e0d0')
.add("喜欢人数", [gp_favorite], color='#1e90ff')
.add("点赞数", [gp_like], color='#b8860b')
.set_series_opts(
label_opts=opts.LabelOpts(is_show=False),
linestyle_opts=opts.LineStyleOpts(width=3, type_='dotted')
)
.set_global_opts(title_opts=opts.TitleOpts(title="硬币、收藏、点赞平均人数分布"))
)
radar.render_notebook()
从雷达图可以得出以下结论:
为了深入分析单个视频的用户反馈,我们爬取了特定视频的弹幕数据。弹幕数据清洗是分析的关键环节:
python复制# 弹幕数据清洗流程
def clean_danmu(data):
# 机械压缩去重
data['danmu'] = data['danmu'].apply(yasuo)
# 过滤非中文字符
data['danmu'] = data['danmu'].str.extract(r"([\u4e00-\u9fa5]+)")
data = data.dropna()
# 过滤过短内容
data = data[data["danmu"].apply(len) >= 4]
return data.dropna()
# 机械压缩去重函数
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<len(st):
k = k + i
st = st[:j] + st[k:]
return st
弹幕清洗需要特别注意:
清洗后的弹幕数据可以通过词云和频率统计进行可视化:
python复制# 弹幕词云生成
def generate_wordcloud(text_series):
text = ' '.join(text_series.tolist())
wordcloud = WordCloud(width=800, height=400).generate(text)
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()
# 主演提及统计
def count_actor_mentions(data, actors):
mentions = {}
for actor in actors:
mentions[actor] = data['danmu'].str.contains(actor).sum()
return pd.Series(mentions).sort_values(ascending=False)
分析某热门剧集的弹幕发现:
使用SnowNLP库进行情感分析:
python复制# 情感分析
df['score'] = df["danmu"].apply(lambda x: SnowNLP(x).sentiments)
# 可视化情感分布
plt.figure(figsize=(12, 6))
sns.distplot(df['score'],
hist_kws={'color':'green', 'label':'直方图'},
kde_kws={'color':'red', 'label':'密度曲线'},
bins=20)
plt.title("弹幕整体情感倾向")
plt.show()
情感分析结果显示:
使用LDA模型挖掘弹幕中的主题:
python复制# 主题分析流程
def topic_analysis(text_series, num_topics=5):
# 分词
texts = text_series.apply(lambda x: ' '.join(jieba.cut(x)))
# 构建词典和语料
dictionary = corpora.Dictionary([text.split() for text in texts])
corpus = [dictionary.doc2bow(text.split()) for text in texts]
# LDA模型训练
lda = models.LdaModel(corpus, num_topics=num_topics, id2word=dictionary)
# 输出主题
for i in range(num_topics):
print(f'Topic {i+1}:')
print(lda.print_topic(i))
print('-'*50)
# 对积极和消极弹幕分别分析
positive_danmu = df[df['score'] > 0.8]['danmu']
negative_danmu = df[df['score'] < 0.3]['danmu']
print("积极弹幕主题:")
topic_analysis(positive_danmu)
print("\n消极弹幕主题:")
topic_analysis(negative_danmu)
主题分析发现:
积极弹幕主要涉及:
消极弹幕主要涉及:
通过这个B站数据分析项目,我总结了几点重要的实践经验:
对于想要复现或扩展这个项目的同学,我有以下建议:
这个项目展示了如何用Python数据科学生态对视频平台数据进行全面分析。虽然作为毕业设计它已经足够完整,但在实际业务场景中,还可以进一步深化和扩展,比如构建内容推荐模型或流行度预测系统。