1、STAR展示

背景:B 站作为学习类视频的主流平台,其评论区蕴含大量用户真实反馈、学习需求与痛点,但海量评论文本缺乏结构化分析,难以直观提炼用户关注重点。

任务:为了精准挖掘用户核心诉求,我基于爬取保存的 B 站某视频评论数据,开展文本可视化分析,让用户关注点从无结构文本变为可直观查看的图表。

行动:数据清洗(去空值)、生成词云图展示整体关键词分布、统计并绘制高频词 TOP30 柱状图量化热度

结果:直观呈现用户关注重点,量化高频词汇,为需求分析提供有效数据支撑。

2、爬虫展示

本文按代码的顺序理清一遍思路生成笔记,并随时附上请求网页时开发者模式中找数据的图

(1)库导入阶段

import requests
import json
import time
import pandas as pd

(2)请求头

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
    "Referer": "https://www.bilibili.com/video/BV1ZM4y1u7uF/",
    "Cookie": "buvid3=3CD272C1-2A43-EBD3-27B5-209E29798E1526378infoc; b_nut=1774579526; _uuid=6105C6665-E2BB-BB4C-7FDE-6B810D538DF5E27931infoc; CURRENT_QUALITY=0; buvid_fp=692592d98b9767faa8acf46003571ed2; buvid4=00D8389E-2745-AEC5-BBF0-6A5A2DAF71BE30708-026032710-ekr0geIP93nCCpmsSPRtFA%3D%3D; home_feed_column=5; browser_resolution=1470-801; SESSDATA=8f72c39b%2C1794320391%2C431e7%2A52CjCJwxG12Z5Zi9Bu1oUDokSt6bL_I0lhTyGZMIDjwTzQcdrT2ef0BuJXLo4Adux-VIoSVkhFU2hBbzhfYjY4RG9SWDBZcGp6RWNJcDBXaVFYQmVUa3oyQWdoeUR1NU9SYWVIYjVrV0tPd3BoWEdRcFc1bU9UaW9BLXlQR3NVXzA0TnNtWlRldG5RIIEC; bili_jct=6e18546b62a5bb46e1800e22ee06061b; DedeUserID=1143175366; DedeUserID__ckMd5=0c88deb0fc9e5a80; theme-tip-show=SHOWED; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzkwMjc1OTksImlhdCI6MTc3ODc2ODMzOSwicGx0IjotMX0.7hw2rYu6aOrYDoa0qYNHlsYuwDd00oTBB0eKRexXx2w; bili_ticket_expires=1779027539; rpdid=|(J~|~JJYl)~0J'u~~)~Y)R|Y; bsource=search_bing; theme-avatar-tip-show=SHOWED; CURRENT_FNVAL=4048; sid=7pgvjua6; b_lsid=ADC87C9E_19E299414AF"
}

目的:伪装成正常用户浏览器访问,顺利拿到数据,通过反爬验证

(3)请求网址

url = "https://api.bilibili.com/x/v2/reply/main"

这里的请求url就是我们的目标网址

所以发送 GET 请求时,params就必须要带这些参数

后面从repiles记录里我们可以看到一个网址是只有20条评论记录的,要是想爬取到所有页面,必须通过游标参数做更新循环处理,这里先简单理解请求网址的结构,以及在哪里看的问题~

(4)初始化设置

all_comments = []

目的:用来存放后续爬下来的所有评论数据

page = 1

目的:记录当前爬取的是第几页评论
 

next_offset = ""

分页游标初始化,从图中可以看出第一页的游标参数就为{"offset":""}

(5)发起 GET 请求,获取并解析评论数据

res = requests.get(url, headers=headers, params=params, timeout=10)
data = res.json()

res 是 requests.get() 返回的一个响应对象,里面的 res.text 是JSON 格式的字符串。JSON 是一种数据格式,长得像字典

data = res.json() 就是把 JSON 字符串转成 Python 字典,你才能取评论、翻页

(6)获取评论列表

replies = data["data"]["replies"]

get解析出来的data中有子集data,data的子级有replies,从上面“预览”的图可以清晰看出

(7)获取想要的列

    for r in replies:
        all_comments.append({
            "用户名": r["member"]["uname"],
            "评论": r["content"]["message"],
            "点赞": r["like"],
            "回复": r["rcount"]
        })

(8)提取分页游标,获取下一页请求参数

cursor = data["data"]["cursor"]
next_offset = cursor["pagination_reply"]["next_offset"]

params里游标参数的值----"pagination_str": f'{{"offset":"{next_offset}"}}'

在“负载”里也能看出游标参数变化,最重要的是看出游标参数的格式

为什么url里翻页参数不是图上的样式,像乱码

其实是一个东西

(9)导出excel

df = pd.DataFrame(all_comments)
df.to_excel("B站评论.xlsx", index=False)

openpyxl = Python 生成 Excel 文件必须用的库,没有它就导不出 Excel。

所以要在终端输入pip install openpyxl

完整代码:

import requests
import json
import time
import pandas as pd

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
    "Referer": "https://www.bilibili.com/video/BV1ZM4y1u7uF/",
    "Cookie": "buvid3=3CD272C1-2A43-EBD3-27B5-209E29798E1526378infoc; b_nut=1774579526; _uuid=6105C6665-E2BB-BB4C-7FDE-6B810D538DF5E27931infoc; CURRENT_QUALITY=0; buvid_fp=692592d98b9767faa8acf46003571ed2; buvid4=00D8389E-2745-AEC5-BBF0-6A5A2DAF71BE30708-026032710-ekr0geIP93nCCpmsSPRtFA%3D%3D; home_feed_column=5; browser_resolution=1470-801; SESSDATA=8f72c39b%2C1794320391%2C431e7%2A52CjCJwxG12Z5Zi9Bu1oUDokSt6bL_I0lhTyGZMIDjwTzQcdrT2ef0BuJXLo4Adux-VIoSVkhFU2hBbzhfYjY4RG9SWDBZcGp6RWNJcDBXaVFYQmVUa3oyQWdoeUR1NU9SYWVIYjVrV0tPd3BoWEdRcFc1bU9UaW9BLXlQR3NVXzA0TnNtWlRldG5RIIEC; bili_jct=6e18546b62a5bb46e1800e22ee06061b; DedeUserID=1143175366; DedeUserID__ckMd5=0c88deb0fc9e5a80; theme-tip-show=SHOWED; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzkwMjc1OTksImlhdCI6MTc3ODc2ODMzOSwicGx0IjotMX0.7hw2rYu6aOrYDoa0qYNHlsYuwDd00oTBB0eKRexXx2w; bili_ticket_expires=1779027539; rpdid=|(J~|~JJYl)~0J'u~~)~Y)R|Y; bsource=search_bing; theme-avatar-tip-show=SHOWED; CURRENT_FNVAL=4048; sid=7pgvjua6; b_lsid=ADC87C9E_19E299414AF"
}

url = "https://api.bilibili.com/x/v2/reply/main"

all_comments = []
page = 1
next_offset = ""

while True:
    print(f"\n📖 正在读取第 {page} 页")

    params = {
        "oid": 931313129,
        "type": 1,
        "mode": 3,
        "plat": 1,
        "pagination_str": f'{{"offset":"{next_offset}"}}',
    }

    try:
        res = requests.get(url, headers=headers, params=params, timeout=10)
        data = res.json()
    except:
        print("请求失败")
        break

    if data.get("code") != 0:
        print("错误:", data.get("message"))
        break

    replies = data["data"]["replies"]

    for r in replies:
        all_comments.append({
            "用户名": r["member"]["uname"],
            "评论": r["content"]["message"],
            "点赞": r["like"],
            "回复": r["rcount"]
        })

    print(f"第 {page} 页完成,累计:{len(all_comments)} 条")

    # 最后一页判断
    if not replies:
        print("✅ 全部爬完!")
        break

    cursor = data["data"]["cursor"]
    next_offset = cursor["pagination_reply"]["next_offset"]
    page += 1
    time.sleep(1.0)

df = pd.DataFrame(all_comments)
df.to_excel("B站评论.xlsx", index=False)

print(f"\n🎉 完成!共 {len(all_comments)} 条")

 【小插曲】

1、刚开始一直权限不足,换了一个老接口,就成功运行了

2、为什么总评论是7000多条,我只爬取到4000多条

:因为是一级评论,就是只算楼主的评论。楼中楼的评论都没爬!

3、词云图柱状图展示

代码如下:

import pandas as pd
import jieba
import matplotlib.pyplot as plt
from wordcloud import WordCloud
from collections import Counter
import re

# Windows 系统专用:解决中文不显示、方框乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False    # 解决负号 - 显示异常

# ---------------------- 1. 读取数据 ----------------------
df = pd.read_excel("B站评论.xlsx")

# 查看缺失值
print("=== 缺失值统计 ===")
print(df.isnull().sum())

# 删除评论为空的行
df = df.dropna(subset=["评论"])

# ---------------------- 3. 分词 + 停用词过滤 ----------------------
stop_words = {
    "的", "了", "是", "我", "什么","哪里","你", "他", "在", "有", "就", "都", "也", "和", "这", "那",
    "吧", "吗", "呀", "哦","请问", "嗯", "哈","有没有","哇","没有","师兄", "UP", "UP主","视频","可以","为什么","一下","打卡","还是","这个","怎么"
}

all_words = []
for text in df["评论"]:
    words = jieba.lcut(text)
    # 过滤:长度>1 + 不是停用词
    words = [w for w in words if len(w) > 1 and w not in stop_words]
    all_words.extend(words)

# ---------------------- 4. 生成词云图 ----------------------
wc = WordCloud(
    font_path="msyh.ttc",
    background_color="white",
    width=1200, height=600,
    max_words=150
)
wc.generate(" ".join(all_words))

plt.figure(figsize=(14, 7))
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.title("B站评论词云图", fontsize=16)
wc.to_file("B站评论词云图.png")
plt.show()

# ---------------------- 5. 高频词柱状图 ----------------------
top30 = Counter(all_words).most_common(30)
words = [x[0] for x in top30]
counts = [x[1] for x in top30]

plt.figure(figsize=(14, 8))
plt.bar(words, counts, color="#4285F4")
plt.xlabel("词语")
plt.ylabel("出现次数")
plt.title("高频词 TOP30(从高到低)")
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.savefig(
    '评论高频词 TOP30.png',  # 保存的文件名
    dpi=300,         # 清晰度(300足够打印/使用)
    bbox_inches='tight'  # 自动裁剪掉多余的空白边,避免文字被截断
)
plt.show()

# ---------------------- 6. 输出TOP30词汇 ----------------------
for i, (word, cnt) in enumerate(top30, 1):
    print(f"{i:2d}. {word:<6} {cnt:>4} 次")

(1)词云图效果如下:

添加蒙版图片的词云图

可以将有白色背景的图片作为蒙版图片,而有图案的地方会被词云填充。

添加蒙版图片需要使用PIL库和numpy库,需提前下载安装。

本案例添加蒙版图片如下:

# 打开蒙版图片,生成Image对象
img = Image.open("蒙版.jpg")  # 打开遮罩图片
# 生成蒙版
mask = np.array(img)   # 将图片转换为数组

wc = WordCloud(
    mask=mask,
    font_path="msyh.ttc",
    background_color="white",
    width=1200, height=600,
    max_words=150
)

wc.generate(" ".join(all_words))

词云图效果如下:

(2)高频词 TOP30 柱状图如下:

4、分析结论

基于本次 B 站数据分析教学视频评论的词云与高频词分析,可得出以下核心结论:

(1)用户画像与核心诉求(人群、需求)

评论受众以零基础数据分析入门学习者为主,核心诉求高度聚焦

  • 工具层面:工具热度排序 Excel > Tableau > SQL > Python,清晰体现了零基础学习者的路径偏好。
  • 学习层面:对「课程、笔记、可下载资料」等系统化学习资源有强烈需求,说明用户依赖结构化的教学内容。
  • 目标层面:整体围绕「数据处理」展开,所有讨论都服务于数据分析的学习目标。

(2)核心痛点与情绪反馈(问题)

  • 大哭报错打不开问题 等词汇的高频出现,反映出零基础学习者的典型困境。
  • 实操门槛高:在 Excel、SQL 的实际操作中频繁遇到报错、软件打不开等问题。
  • 学习挫败感强:大量情绪性吐槽(如 “大哭”),说明入门阶段的学习体验较差,需要更友好的教学引导。

(3)教学优化方向(改进)

结合以上分析,后续教学内容可针对性优化:

  • 强化 Excel 实操教学,增加报错排查、软件使用等问题的讲解。
  • 提供配套的可下载笔记、资料,满足用户对系统化资源的需求。
  • 降低入门门槛,增加情绪友好的引导内容,缓解用户的学习挫败感。

更多推荐