这个毕业设计项目让我想起了自己第一次接触大数据分析时的兴奋感。作为一个长期混迹B站的老用户,我一直在好奇:为什么生活区的视频越来越火?鬼畜区的魅力到底在哪里?这次终于有机会用数据来验证这些疑问了。
本项目采用Python大数据分析技术,对B站视频数据进行深度挖掘。不同于简单的数据统计,我们实现了从数据采集、清洗到可视化分析的全流程,特别是创新性地结合了弹幕情感分析,让数据不仅能"说话",还能"表达情绪"。
项目采用经典的ETL+分析架构:
技术选型心得:初期考虑过Scrapy框架,但针对B站的反爬机制,手动构建的轻量级爬虫反而更灵活。PyEcharts的交互性比Matplotlib更适合展示多维数据。
通过B站API获取视频基础信息,核心字段包括:
python复制def get_video_info(bvid):
url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Referer": "https://www.bilibili.com/"
}
response = requests.get(url, headers=headers)
return response.json()['data']
弹幕需要先获取cid(弹幕池ID),再通过专用接口获取:
python复制def get_danmu(cid):
url = f"https://comment.bilibili.com/{cid}.xml"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
return [d.text for d in soup.find_all('d')]
爬虫注意事项:B站对高频请求限制严格,建议:
- 设置3秒以上的请求间隔
- 使用代理IP池
- 模拟真实用户行为(携带Cookie、Referer)
python复制# 检查缺失值
print(df.isnull().sum())
# 处理策略:
# - 关键字段缺失直接删除记录
# - 非关键字段用分区均值填充
df['播放量'].fillna(df.groupby('分区')['播放量'].transform('mean'), inplace=True)
使用IQR方法检测异常值:
python复制Q1 = df['播放量'].quantile(0.25)
Q3 = df['播放量'].quantile(0.75)
IQR = Q3 - Q1
df = df[~((df['播放量'] < (Q1 - 1.5*IQR)) | (df['播放量'] > (Q3 + 1.5*IQR)))]
创建衍生特征更有分析价值:
python复制# 计算互动率
df['互动率'] = (df['弹幕数'] + df['评论数']) / df['播放量']
# 标准化处理
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df[['播放量_norm', '弹幕数_norm']] = scaler.fit_transform(df[['播放量', '弹幕数']])
python复制import re
def clean_danmu(text):
# 去除特殊符号
text = re.sub(r'[^\w\s]', '', text)
# 去除emoji
text = text.encode('ascii', 'ignore').decode('ascii')
# 机械压缩
text = re.sub(r'(.)\1{2,}', r'\1', text)
return text.strip()
df['弹幕'] = df['弹幕'].apply(clean_danmu)
使用扩展的停用词表(包含B站特有词汇):
code复制[爷青回, 哈哈哈, 打卡, 前排, 666]
使用环形图展示各分区占比:
python复制from pyecharts import options as opts
from pyecharts.charts import Pie
pie = (
Pie()
.add(
"",
[list(z) for z in zip(labels, values)],
radius=["40%", "75%"],
)
.set_global_opts(title_opts=opts.TitleOpts(title="各分区播放量占比"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
pie.render_notebook()
创新性地使用雷达图展示各分区互动特征:
python复制radar = (
Radar()
.add_schema(
schema=[
opts.RadarIndicatorItem(name="生活区", max_=100),
opts.RadarIndicatorItem(name="动画区", max_=100),
# ...其他分区
]
)
.add("硬币", coin_values)
.add("收藏", fav_values)
.add("点赞", like_values)
)
发现生活区占比达35%,但优质内容集中在少数头部UP主:
python复制top100 = df.sort_values('综合得分', ascending=False)[:100]
top100['分区'].value_counts().plot.bar()
使用词云展示热门标签:
python复制from wordcloud import WordCloud
text = ' '.join(df['标签'].dropna())
wordcloud = WordCloud(font_path="msyh.ttc").generate(text)
plt.imshow(wordcloud)
使用SnowNLP计算情感倾向:
python复制def get_sentiment(text):
try:
return SnowNLP(text).sentiments
except:
return 0.5
df['情感得分'] = df['弹幕'].apply(get_sentiment)
python复制plt.figure(figsize=(10,6))
sns.distplot(df['情感得分'], bins=20, kde=True)
plt.title("弹幕情感分布")
使用LDA挖掘积极/消极弹幕的主题:
python复制from gensim import corpora, models
# 构建词典
dictionary = corpora.Dictionary(tokenized_texts)
# LDA模型训练
lda = models.LdaModel(corpus, num_topics=5, id2word=dictionary)
Pandas加速:
df.itertuples()替代df.iterrows()swifter并行处理内存优化:
python复制df = df.astype({
'播放量': 'int32',
'弹幕数': 'int16'
})
问题:B站反爬导致封IP
解决方案:
fake-useragent随机UA问题:网络用语识别率低
改进方案:
问题:静态图表不直观
改进方案:
这个项目让我深刻体会到:数据不会说谎,但需要正确的解读方式。有几个意外发现:
建议后续可以:
完整代码已整理在GitHub仓库,包含详细注释和数据集。对于想入门大数据分析的同学,这个项目涵盖了完整的数据处理流程,是非常好的练手素材。