Verified Commit 44501cb3 authored by 施乐存's avatar 施乐存
Browse files

论文:视频涉及的话题的分析

Signed-off-by: 施乐存's avatarszdytom <szdytom@qq.com>
parent f72fcc19
Loading
Loading
Loading
Loading
+55 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@

== 数据收集与数据库构建

数据来源于 Bilibili 官方网页端应用程序所使用的未公开 API,这些 API 由“哔哩哔哩 - API 收集整理”@Bilibili_API_collect 项目通过逆向工程获得。过自主编写的爬虫程序系统收集了自20193月至202511月共348期“每周必看”榜单的全部数据。数据存储采用SQLite关系型数据库,共计收集 12725 条视频记录,涵盖包括视频标识(bvid)、所属分区、时长、各项互动数据(播放量、弹幕、评论、点赞、投币、收藏、分享)等多个维度的信息。
数据来源于 Bilibili 官方网页端应用程序所使用的未公开 API,这些 API 由“哔哩哔哩 - API 收集整理”@Bilibili_API_collect 项目通过逆向工程获得。过自主编写的爬虫程序,我们系统收集了自20193月至202511月共348期“每周必看”榜单的全部数据。数据存储采用SQLite关系型数据库,共计收集 12725 条视频记录,涵盖包括视频标识(bvid)、所属分区、时长、各项互动数据(播放量、弹幕、评论、点赞、投币、收藏、分享)等多个维度的信息。

另外,为了进一步理解“每周必看”视频的内容特征,我们通过爬虫程序获取了每个视频的封面图像,并使用多模态大语言模型对这些封面进行识别分析 @Qwen_VL @Qwen3_VL,以提取视频的视觉内容的量化特征。

@@ -194,6 +194,60 @@ B 站创作者生态呈现出“*头部效应显著、中间层薄弱、新入

综上所述,B站“每周必看”上榜视频的互动生态正经历深刻的结构性调整。用户互动行为从早期的泛化、轻量趋向于理性、分化与深化。这对于创作者而言意味着,制造“热门”不仅需要吸引眼球,更需要创造能够经得起理性考量、值得用户投入“高成本”互动(如时间、硬币、收藏夹位置)的内容价值。这也预示着 B 站的内容竞争,正从流量争夺进阶到用户心智与价值认同的更深层次竞争。

== 视频涉及的话题的分析

视频的“话题”或“分区”,是B站社区文化的重要载体,直接反映了平台的内容生态结构与用户兴趣变迁。本节基于“每周必看”榜单中视频的主分区数据,对其历时性变化进行统计分析,旨在揭示热门内容背后的社区趋势、平台策略与社会动因。

=== 总体生态结构:双核驱动与多元长尾

#figure(
  image("../zone-analysis/overall_partition_distribution.png"),
  caption: [上榜视频分区构成的总体分析],
  placement: auto,
) <zone-overall-distribution-fig>

#figure(
  image("../zone-analysis/partition_percentage_grouped_bars.png"),
  caption: [上榜视频分区构成的历时性分析],
  placement: auto,
) <zone-trend-fig>

 2019  2025 年的总体数据来看,B站“每周必看”的内容生态呈现出鲜明的“*双核驱动,多元并存*”格局。游戏($14.55%$) 与动画($12.67%$)两大核心分区合计贡献了超过四分之一的上榜视频,构成了 B 站热门内容的传统基本盘与社区文化底色。紧随其后的是知识区($8.36%$),标志着 B 站“学习网站”的标签已深入人心。音乐、美食、小剧场等分区构成了重要的多元化支撑力量,占比均在 $7%$  $8%$ 之间。值得注意的是,“其他分区”总和高达 $13.32%$,显示出尽管头部效应显著,但海量中小垂类内容共同构成的“长尾”同样是热门榜单不可或缺的组成部分,体现了平台内容生态的丰富性与活力。

=== 主要分区的动态演变轨迹

通过对主要分区年度占比的历时性分析(@zone-trend-fig),可以发现各分区并非一成不变,而是经历了显著的起伏与轮动,勾勒出 B 站内容生态的动态演化图景。

游戏区的韧性与周期性爆发:游戏区占比始终保持在 $12%$ 以上,*长期位居榜首,展现了其作为 B 站“压舱石”的稳固地位*。其演变路径呈现出明显的周期性波动,在 2024 年达到峰值($18.36%$)。这并非偶然,通常与现象级单机游戏(如 2024 年游戏科学的国产大作《黑神话:悟空》)、爆款网游新版本或全球性电竞赛事高度相关,*反映了游戏内容强烈的“事件驱动”特征和强大的即时社区爆发力*

动画区的平台定位转移:动画区占比在 2020 年达到顶峰($15.74%$)后逐年回落并趋于稳定。这一轨迹清晰表明了动画内容从 B 站早期赖以生存的“核心护城河”,逐渐演变为与平台共同成长的“文化基本盘”。其峰值的出现往往与年度“霸权”番剧或原创国创作品的上线紧密绑定,而占比的稳定则说明,*尽管面临其他内容品类的分流,二次元文化依然是 B 站不可动摇的社区根基和用户情感连接的核心*

知识区的价值沉淀与常态化:知识区占比在 2020 年疫情期间冲高($11.66%$)后有所回调,但自 2023 年起重回升势。这表明*知识内容经历了从“特殊时期的应急需求”到“后疫情时代的常态需求”的转变*。用户不再仅仅将其视为临时补充,而是内化为一种稳定的内容消费习惯。平台通过系统性的品牌运营,成功将知识区从流量风口塑造成了代表平台深度与价值的“金字招牌”。

小剧场的结构性崛起:小剧场(或微短剧)是变化最显著的分区之一。其占比从 2019  2020 年的不足 $5%$,到 2023 年后稳定在接近 $9%$,完成了从边缘品类到主流形式的跃迁。这一变化精准回应了当代用户碎片化、强情节的观看偏好,也是 B 站积极拥抱市场趋势、主动调整内容供给结构的直接体现。

美食区的分流与转型:与此相对,美食区占比从 2019 年的高位($11.59%$)持续下滑至2025 年的 $5.56%$。这反映了在短视频平台专业化美食内容的激烈竞争下,B 站美食内容面临的挑战。这可能与后疫情时代经济下滑、实体餐饮业持续受挫有关,从而导致用户对“探店”“测评”等内容的兴趣减弱。平台需重新审视美食区的内容策略,以适应新的市场环境。

=== 分区变迁的多重动因分析

“每周必看”榜单分区结构的演变,是平台算法机制、官方创作导向、创作者生态、用户代际变迁及外部社会环境共同作用的结果。

*平台算法与运营策略的导向作用*:平台的推荐机制与专项激励计划如同“指挥棒”,直接影响内容流向。例如,对知识区的长期扶持、对小剧场的流量倾斜,以及对游戏直播和赛事版权的加码,都直接体现在对应分区占比的提升上。榜单本身作为官方精选,也承担着向社区示范“何为优质内容”的引导功能。

*社会趋势与热点事件的催化效应*:外部环境是内容潮流的放大器。2020 年的疫情直接催生了“知识普惠”的窗口期;2024 年国产 3A 游戏《黑神话:悟空》的现象级破圈,则瞬间点燃了社区的游戏创作与讨论热情。这些社会性热点为特定分区注入了爆发性增长动力。

*用户代际变迁与需求演化*:随着B站主流用户年龄增长,其内容消费需求也从单纯的娱乐消遣,向知识获取、技能学习、社会议题探讨等更复合的方向扩展。这为知识、科技、财经等分区提供了持续增长的用户基础。同时,年轻用户对高密度、快节奏叙事(小剧场)的偏爱也塑造了新的内容风口。

*跨平台竞争下的生态位选择*:在短视频平台侵蚀部分生活、娱乐内容的压力下,B站的内容生态自觉或不自觉地强化了其差异化的“生态位”:即依靠社区文化和用户关系,深耕需要一定理解门槛、具备深度或强叙事性的中长视频内容。游戏、知识、深度解说、系列短剧等分区的稳固或崛起,正是这一战略选择的体现。

=== 小结:动态平衡中的生态演进

综上所述,“每周必看”榜单的分区变迁史,是一部B站内容生态在动态平衡中不断演进的历史。它呈现出“稳定性与流动性并存、从‘兴趣部落’到‘数字市集’、‘热门’定义的多元化”这三条核心特征。

其中,“游戏+动画”的双核结构保持了基本稳定,确保了社区文化基石的牢固。与此同时,知识、小剧场等分区的崛起与更迭,则展现了生态内部的充沛活性和对时代脉搏的敏锐响应。进一步的,B 站正从一个以特定兴趣(ACG#footnote[ACG:英文单词 AnimeComicsGame 的缩写,即动画、漫画、游戏。])为核心的“部落”,演变为一个包罗万象、满足用户多元化精神消费需求的“数字市集”。热门话题的多样性,正是这一转型的最直观注脚。分区的轮动表明,成为“热门”的路径不再是单一的。无论是依靠瞬间爆发的社区情绪(游戏赛事),还是依靠长期沉淀的认知价值(知识科普),或是依靠抓人的叙事技巧(小剧场),都能在当前的B站生态中找到自己的位置。

因此,对创作者而言,理解分区趋势不仅关乎内容选题,更关乎对平台生态位和用户深层需求的把握。对平台而言,维持这种核心稳固与边缘创新的动态平衡,是保持社区长期健康与吸引力的关键。这揭示了“热门视频炼成”的另一重要维度:它不仅关乎视频本身的品质,也深刻依赖于其所处话题领域在特定历史时刻的“势能”。

#pagebreak()

#bibliography("works.bib", style: "gb-7714-2015-numeric")
−15.6 KiB (80.6 KiB)
Loading image diff...
+46 −0
Original line number Diff line number Diff line
@@ -79,5 +79,51 @@ barChart = BarChart[
Export[FileNameJoin[{exportDir, "partition_percentage_grouped_bars.png"}], barChart];
Print["\:5df2\:5bfc\:51fa: partition_percentage_grouped_bars.png"];

(* \:5728notebook\:4e2d\:663e\:793a\:8868\:683c\:6570\:636e *)
Print["\:5206\:533a\:5360\:6bd4\:6570\:636e\:8868\:683c (2019-2025):"];

(* \:521b\:5efa\:8868\:5934 *)
header = Prepend[partitions, "\:5e74\:4efd"];

(* \:521b\:5efa\:8868\:683c\:6570\:636e *)
tableData = Table[
  Prepend[dataMatrix[[i]], years[[i]]],
  {i, Length[years]}
];

(* \:683c\:5f0f\:5316\:4e3a\:767e\:5206\:6bd4\:5b57\:7b26\:4e32 *)
formattedTableData = Table[
  Join[
    {tableData[[i, 1]]}, (* \:5e74\:4efd *)
    Map[If[NumericQ[#] && # > 0, ToString[#] <> "%", "0%"] &, tableData[[i, 2 ;;]]]
  ],
  {i, Length[tableData]}
];

(* \:521b\:5efa\:8868\:683c *)
dataTable = Grid[
  Prepend[formattedTableData, header],
  Frame -> All,
  Background -> {
    {LightBlue, LightGray},  (* \:7b2c\:4e00\:884c\:662f\:8868\:5934 *)
    None,                    (* \:5176\:4ed6\:884c\:4e0d\:8bbe\:7f6e\:80cc\:666f\:8272 *)
    {{1, 1}, {1, -1}} -> LightBlue,  (* \:7b2c\:4e00\:5217\:7279\:6b8a\:80cc\:666f\:8272 *)
    {{1, 1}, {1, 1}} -> LightBlue    (* \:5de6\:4e0a\:89d2\:5355\:5143\:683c *)
  },
  ItemStyle -> {
    {Bold, Bold, Bold},  (* \:8868\:5934\:52a0\:7c97 *)
    {Bold}               (* \:7b2c\:4e00\:5217\:52a0\:7c97 *)
  },
  Alignment -> {{Center, Left}, Center},  (* \:7b2c\:4e00\:5217\:5de6\:5bf9\:9f50\:ff0c\:5176\:4ed6\:5217\:5c45\:4e2d *)
  Dividers -> {All, {2 -> True}},  (* \:6dfb\:52a0\:5206\:9694\:7ebf\:ff0c\:7b2c\:4e8c\:884c\:4ee5\:4e0b\:5206\:9694 *)
  Spacings -> {2, 1}  (* \:8c03\:6574\:5355\:5143\:683c\:95f4\:8ddd *)
];

(* \:663e\:793a\:8868\:683c *)
Print[dataTable];

(* \:5728notebook\:4e2d\:663e\:793a\:56fe\:8868 *)
barChart


+21 −14
Original line number Diff line number Diff line
(* 从数据库获取分区数据 *)
(* ::Package:: *)

(* \:4ece\:6570\:636e\:5e93\:83b7\:53d6\:5206\:533a\:6570\:636e *)
partitionData = Normal[ExternalEvaluate[
  DatabaseReference[
   File[FileNameJoin[{NotebookDirectory[], "..", "data.db"}]]],
   "WITH partition_counts AS (
    SELECT 
        COALESCE(vc.name, '未知分区') as partition_name,
        COALESCE(vc.name, '\:672a\:77e5\:5206\:533a') as partition_name,
        COUNT(v.id) as video_count,
        ROUND(COUNT(v.id) * 100.0 / (SELECT COUNT(*) FROM videos), 2) as percentage,
        ROW_NUMBER() OVER (ORDER BY COUNT(v.id) DESC) as rank
@@ -13,30 +15,35 @@ partitionData = Normal[ExternalEvaluate[
    GROUP BY v.pidv2
)
SELECT 
    partition_name as 分区,
    video_count as 视频数量,
    percentage as 占比
    partition_name as \:5206\:533a,
    video_count as \:89c6\:9891\:6570\:91cf,
    percentage as \:5360\:6bd4
FROM partition_counts
WHERE rank <= 15
UNION ALL
SELECT 
    '其他分区' as 分区,
    SUM(video_count) as 视频数量,
    ROUND(SUM(percentage), 2) as 占比
    '\:5176\:4ed6\:5206\:533a' as \:5206\:533a,
    SUM(video_count) as \:89c6\:9891\:6570\:91cf,
    ROUND(SUM(percentage), 2) as \:5360\:6bd4
FROM partition_counts
WHERE rank > 15
ORDER BY 视频数量 DESC;"]];
ORDER BY \:89c6\:9891\:6570\:91cf DESC;"]];

(* \:51c6\:5907\:997c\:56fe\:6570\:636e *)
labels = #["\:5206\:533a"] <> "(" <> ToString[#["\:5360\:6bd4"]] <> "%)" & /@ partitionData;
values = #["\:89c6\:9891\:6570\:91cf"] & /@ partitionData;

(* 准备饼图数据 *)
labels = #["分区"] <> "(" <> ToString[#["占比"]] <> "%)" & /@ partitionData;
values = #["视频数量"] & /@ partitionData;
labels

(* 绘制饼图 *)
(* \:7ed8\:5236\:997c\:56fe *)
PieChart[values,
 ChartLabels -> labels,
 ChartStyle->"Pastel",
 PlotLabel -> Style["上榜视频分区分布", 16, Bold],
 PlotLabel -> Style["\:4e0a\:699c\:89c6\:9891\:5206\:533a\:5206\:5e03", 16, Bold],
 LabelStyle -> Directive[12],
 ImageSize -> 800,
 PlotRangePadding -> Scaled[0.1]
]