摘要:

本实训报告聚焦于运用Python技术实现B站排行榜数据的获取、预处理及可视化分析。在互联网视频媒介蓬勃发展的背景下,为助力视频创作者在自媒体领域优化内容策略,本研究通过官方API接口定向采集B站排行榜数据,涵盖视频标题、播放量、互动指标等多维信息。 程序构建了数据获取、分析预处理、可视化及主流程控制四大模块。数据获取模块通过requests库调用B站公开API,以合规方式获取JSON格式数据;预处理模块利用pandas完成数据结构化转换、索引优化、异常值处理及衍生指标计算,同时通过分组聚合挖掘创作者特征与时长分布规律;可视化模块借助matplotlib与seaborn生成直方图、折线图等图表,直观呈现播放量分布、互动指标对比等关键规律。 实训结果表明,该方案可有效提取B站视频数据特征,为内容创作提供数据支撑。未来可拓展多平台数据采集、完善异常值处理策略及丰富可视化交互设计,进一步提升数据分析的实用性与深度。

1. 数据获取可行性分析和需求分析

1.1 程序模块划分以及功能描述

在互联网技术飞速发展的当下,视频媒介凭借强大的传播力,让人们足不出户便能领略大自然的鬼斧神工、汲取海量知识养分、拓展社交圈层。这一趋势促使越来越多的人投身视频创作领域,分享生活趣事、专业见解与实用知识。在此背景下,为在竞争激烈的自媒体赛道脱颖而出,通过系统分析视频数据中的点赞量、评论量、播放量、视频时长等关键指标,挖掘受众偏好与创作规律,成为打造优质视频作品的重要路径。

基于此需求,本程序构建了四大核心模块:

  • 数据获取模块:由fetch_bilibili_data函数主导,通过 B 站公开 API 接口定向获取排行榜数据,涵盖视频标题、创作者信息、播放量等多维数据,为后续深度分析筑牢数据根基。
  • 数据分析与预处理模块:依托analyze_data函数,综合运用数据框构建、索引调整、条件筛选、统计运算、异常值处理等技术,深度挖掘不同视频在各项指标上的特征差异,提升数据可用性。
  • 数据可视化模块:借助visualize_data函数,将处理后的数据转化为直方图、折线图、柱状图及散点图等可视化图表,以直观图形呈现数据规律,辅助创作者精准制定内容策略。
  • 主流程控制模块:main函数作为程序中枢,有序串联数据获取、分析处理、存储及可视化全流程,确保各环节高效协同运行。

1.2 爬虫网页、互联网安全、法律等方面的可行性分析

1.2.1 爬虫网页可行性分析

从技术层面来看,当前网络爬虫技术已较为成熟,本实训采用 Python 的requests库发送 HTTP 请求,结合BeautifulSoup或直接解析 JSON 数据(如本次从 B 站 API 获取数据),能够高效获取网页或 API 返回的数据。对于结构复杂的网页,还可借助Scrapy等框架进行更精细化的爬取。B 站提供了公开的 API 接口,数据以 JSON 格式返回,相较于传统 HTML 页面解析,具有结构清晰、解析便捷、效率更高的显著优势,大幅降低数据采集与处理的复杂度,使得从该平台获取数据在技术上具有较高的可行性。同时,通过合理设置请求头信息,模拟浏览器访问行为,可以有效避免被网站识别为恶意爬虫而限制访问,进一步保障了数据获取的可行性。

1.2.2 法律可行性分析

在法律层面,数据获取需严格遵守相关法律法规。本次实训从 B 站 API 获取数据,使用的是官方提供的公开接口,属于合法的数据获取途径,不涉及侵犯网站的知识产权或违反相关法律规定。同时,在数据使用过程中,仅用于实训学习和分析,不进行商业用途或非法传播,符合数据合理使用的法律要求。此外,在数据获取过程中,严格遵循网站的使用条款和爬虫协议,不进行恶意爬取或过度请求,避免对网站服务器造成损害,确保数据获取行为在法律允许的范围内,因此在法律方面具有可行性。

随着网络数据的海量增长,不同网站的结构和数据呈现方式各不相同,这就要求数据获取工具具备强大的适应性。对于采用 API 接口提供数据的网站,如 B 站,需要准确理解 API 的调用规则、参数含义和返回数据格式,以确保获取到准确、完整的数据。而对于普通网页,数据获取工具需要能够解析复杂的 HTML 和 CSS 结构,定位到所需数据的标签位置。同时,为了提高数据获取效率,工具还应具备多线程或异步请求的能力,能够在短时间内获取大量数据。此外,还需要具备一定的错误处理机制,当遇到网络故障、网站结构变化或反爬虫机制拦截时,能够及时做出响应,保证数据获取的稳定性和可靠性。

1.3 流程图 + 文字说明

#构造获取数据的函数返回data['data']['list']json文件里面的视频列表

def fetch_bilibili_data():

    url = "https://api.bilibili.com/x/web-interface/ranking/v2"

#哔哩哔哩(B 站)开放的官方排行榜 API

    headers ={

        'user - agent':

           "粘贴自己的即可(教程如下图)",

        'referer':

            '粘贴自己的即可',

        'cookie':

            "粘贴自己的即可"

    }

    params = {"rid":0,"type":"all"}#(教程如下图)

    response = requests.get(url,headers=headers,params=params)

    data = response.json()

    return data['data']['list'] if data ['code'] ==0 else []

找user - agent、referer、cookie:

右键点击“检查”/按F12

params = {"rid":0,"type":"all"}的查找:要看哪个区就点哪个,我点的是“全部”

    

API返回的JSON数据结构大致如下:是多个字典,其中键为”data”的值又嵌套了字典,其中键为“list”的值为列表,每个列表存着每个视频的信息,每个视频里嵌套着字典,其中字典里每个键是视频的各种信息如:视频ID号、BV号、视频标题、”owner”里嵌套”name”,”start”里面嵌套播放量、弹幕数、点赞数、收藏数。获取的json框架如下:

分析可知我们可以返回最有用的部分data['data']['list']这里面是类似二维,各个视频是一个维度,每个视频的信息是另一个维度。大致如下:

2. 网页页面分析

本次实训选定 B 站官方排行榜页面(https://www.bilibili.com/ranking)作为数据采集源。经开发者工具剖析发现,该平台采用 API 接口(https://api.bilibili.com/x/web-interface/ranking/v2)以 JSON 格式返回数据。相较于传统 HTML 页面解析,API 数据获取方式具有结构清晰、解析便捷、效率更高的显著优势,大幅降低数据采集与处理的复杂度。

核心代码展示:

url = "https://api.bilibili.com/x/web-interface/ranking/v2"

headers = {

    "User-Agent": "粘贴自己的即可",

    "Referer": "粘贴自己的即可"

}

params = {"rid": 0, "type": "all"}

#                区域:全部:0  游戏:1008     范围:所有(查找教程如上图)

response = requests.get(url, headers=headers, params=params)

data = response.json()

上述代码通过精准配置 API 请求地址、模拟浏览器请求头及参数设置,运用requests.get方法完成数据请求,并借助response.json()实现 JSON 数据的自动化解析,为后续数据提取与分析创造条件。

3. 数据获取

3.1 实验环境及实验平台

类别

详情

操作系统

Windows 10

Python 版本

Python 3.10

开发工具

PyCharm 2023.3

核心依赖库

requests、pandas、numpy、matplotlib、seaborn

3.2 网络爬虫的遵守协议和规范

在数据采集过程中,严格恪守 B 站服务条款与网络爬虫行业规范:

  1. 合规数据采集:优先使用官方 API 接口,规避对网页的直接爬取,减少服务器负载压力。
  2. 模拟正常访问:通过设置合理的User-Agent与Referer请求头信息,模拟真实用户访问行为,维护平台数据安全与服务稳定性。
  3. 频率控制策略:尽管本次实训数据请求规模较小,但在实际应用场景中,将建立动态请求频率控制机制,防止因过度请求影响平台正常运营。

3.3 数据获取

3.3.1文字融合代码说明:

fetch_bilibili_data函数作为数据获取的核心入口,通过精准配置 API 请求参数,构建完整请求链路。当服务器响应状态码code为 0 时,判定请求成功并提取data['list']中的视频数据列表;若请求失败,则返回空列表,确保程序健壮性。

核心代码展示:

def fetch_bilibili_data():

    """获取B站排行榜数据"""

    url = "https://api.bilibili.com/x/web-interface/ranking/v2"

    headers = {

        "User-Agent": "Mozilla/5.0 Chrome/100.0.0.0",

        "Referer": "https://www.bilibili.com/ranking"

    }

    params = {"rid": 0, "type": "all"}

    response = requests.get(url, headers=headers, params=params)

    data = response.json()

    return data['data']['list'] if data['code'] == 0 else []

3.3.2获取结果:

4. 数据预处理

4.1文字融合代码说明:

analyze_data函数围绕数据质量提升与价值挖掘,构建了完整的数据预处理体系:

  1. 结构化转换:将原始数据列表转化为pandas DataFrame格式,实现数据的结构化存储与高效管理。
  2. 数据概览分析:运用df.shape、df.columns及describe()方法,快速掌握数据集规模、特征构成及数值分布情况。
  3. 索引优化处理:通过set_index方法将 “排名” 字段设为索引,提升数据查询与分析效率。
  4. 精准数据筛选:结合iloc位置索引与条件表达式,实现数据的灵活筛选与定向提取。
  5. 指标衍生计算:借助numpy向量化运算,精准计算互动量、互动率等衍生指标,并妥善处理除零异常场景。
  6. 数据质量净化:通过fillna填充缺失值、drop_duplicates去除重复记录,显著提升数据完整性与准确性。
  7. 分组聚合洞察:基于作者与视频时长维度进行分组聚合,深度挖掘不同群体的创作特征与受众反馈差异。

4.2核心代码展示

def analyze_data(videos):

    df = pd.DataFrame([{

        '排名': idx + 1,

        '标题': v.get('title', np.nan),

        '作者': v['owner'].get('name', '未知作者'),

        '播放量': v['stat'].get('view', 0),

        '弹幕数': v['stat'].get('danmaku', 0),

        '点赞数': v['stat'].get('like', 0),

        '收藏数': v['stat'].get('favorite', 0),

        '时长(秒)': v.get('duration', 0)

    } for idx, v in enumerate(videos)])

    df.set_index('排名', inplace=True)

    high_view_df = df[df['播放量'] > 1000000]

    df['互动量'] = df['点赞数'] + df['收藏数'] + df['弹幕数']

    df['互动率'] = np.divide(

        df['互动量'],

        df['播放量'],

        out=np.zeros_like(df['播放量'], dtype=np.float64),

        where=df['播放量'] != 0

    ).round(4)

    df.fillna({'标题': "未命名视频"}, inplace=True)

    df_clean = df.drop_duplicates()

    author_group = df_clean.groupby('作者').agg({

        '播放量': ['sum', 'mean', 'count'],

        '互动率': 'mean'

    }).sort_values(('播放量', 'sum'), ascending=False)

    df_clean['时长分组'] = pd.cut(

        df_clean['时长(秒)'],

        bins=[0, 60, 300, 900, np.inf],

        labels=['<1分钟', '1-5分钟', '5-15分钟', '>15分钟']

    )

    time_group = df_clean.groupby('时长分组', observed=False).agg({

        '播放量': 'sum',

        '互动率': 'mean',

        '标题': 'count'

    }).sort_values('播放量', ascending=False)

    return df_clean

4.3结果图

5. 数据可视化

5.1文字融合代码说明

visualize_data函数综合运用matplotlib与seaborn可视化库,将抽象数据转化为直观图表:

  1. 播放量分布洞察

通过sns.histplot绘制带核密度曲线的直方图,直观呈现播放量数据的分布形态与集中趋势。

  1. 排名趋势分析:

借助sns.lineplot生成排名 - 播放量趋势折线图,清晰展现二者的动态关联与变化规律。

  1. 互动指标对比:

利用df[['点赞数', '收藏数', '弹幕数']].mean().plot(kind='bar')绘制柱状图,实现不同互动指标的横向对比分析

  1. 互动率关联探索:

通过sns.scatterplot绘制散点图,并以排名为色彩区分维度,深入探究播放量与互动率之间的潜在关系。

核心代码展示:

def visualize_data(df):

    plt.figure(figsize=(12, 8))

    plt.subplot(2, 2, 1)

    sns.histplot(df['播放量'], bins=100, kde=True, color='babyblue')

    plt.title('播放量分布')

    plt.subplot(2, 2, 2)

    sns.lineplot(x=df.index, y='播放量', data=df, marker='o', color='red')

    plt.title('排名与播放量趋势')

    plt.subplot(2, 2, 3)

    df[['点赞数', '收藏数', '弹幕数']].mean().plot(kind='bar', color=['gold', 'green', 'purple'])

    plt.title('平均互动指标对比')

    plt.subplot(2, 2, 4)

    sns.scatterplot(x='播放量', y='互动率', data=df, hue='排名')

    plt.title('播放量与互动率关系')

    plt.tight_layout()

    plt.savefig('bilibili_analysis.png')

    plt.show()

5.2结果图展示

6. 结束语

本次 Python 数据获取与预处理实训,通过完整的数据处理链路实践,成功实现 B 站排行榜数据的采集、分析与可视化呈现。在实训过程中,系统掌握了requests库的 API 调用技巧、pandas与numpy的数据处理方法,以及matplotlib和seaborn的可视化应用,为数据科学实践奠定了坚实基础。

在短视频行业蓬勃发展的今天,网络视频已成为人们获取信息、娱乐休闲的重要载体,吸引着众多创作者投身其中。本次实训所采用的数据分析方法,能够有效挖掘点赞量、评论量、播放量等数据背后的创作规律,为视频创作者优化内容策略、提升作品质量提供科学依据。

然而,数据采集层面,当前仅获取了 B 站单一平台的部分排行榜数据,未来可拓展至多平台、多维度数据采集;数据预处理环节,对异常值的识别与处理策略仍需完善;数据可视化方面,图表类型与交互设计的丰富度不足。后续将围绕这些方向深入钻研,持续提升数据处理与分析能力,为自媒体内容创作、市场趋势研究等实际应用场景提供更有力的数据支持。

完整代码:

(其中有一小部分涉及个人隐私就删去了,大家需要按照上面的步骤无脑粘贴成自己的就可以啦)

#导入库

import requests

#请求html

import pandas as pd

'''pd.DataFrame将json数据转为二维表格,每列对应爬取的不同属性

df.set_index(" ",inplace)把某列表设为索引,正序

df.iloc[:5,[0,2]]配合切片选择数据

df.fillna()处理缺失值

df.drop_duplicates()移除重复行

df.groupby("哪一类").agg({

'':['mean','max','min',std],均值,最大,最小,标准差

'':[]  np底层支持

}

)

pd.cut(

df['时长'],

bins=[,,],

lables=[,,]

)

'''

import numpy as np

'''np.divide(

除数,

被除数,

out=np.zeros_like(df[]),初始化分母为0返回0

where=df[]!=0   执行条件条件

缺失值处理:np.nan表示缺失值

np.number自动筛选出数值

dtype=np.float64指定数据类型

np.inf无穷大

)

'''

import matplotlib.pyplot as plt

import seaborn as sns

'''

sns.histplot(数据,bins=,kde=True,color=)直方图

                       曲线

sns.lineplot(x=,y=,data=,mark='o',color='red')线图

sns.scatterplot(x=,y=,data=,hue=)

                            点的着色依据                           

'''

from wordcloud import WordCloud

import jieba

import re#正则 清洗

import json

from datetime import datetime



plt.rcParams['font.sans-serif']=['SimHei']#黑体

plt.rcParams['axes.unicode_minus']=False





font_path = r'C:\Windows\Fonts\simhei.ttf'



#获取数据

def fetch_bilibili_data():

    url = "https://api.bilibili.com/x/web-interface/ranking/v2"

#哔哩哔哩(B 站)开放的官方排行榜 API

    headers ={

        'user-agent':

            "粘贴自己的",

        'referer':

            '粘贴自己的',

        'cookie':

            "粘贴自己的"

    }

    params = {"rid":1008,"type":"all"}



    response = requests.get(url,headers=headers,params=params,timeout=15)

    data = response.json()

    print("开始保存JSON数据")

    file_prefix = "bilibili_data"#主名

    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

    file_name = f"{file_prefix}_{timestamp}.json"

    try:

        with open(file_name,"w",encoding='utf-8') as f:

            json.dump(data,f, ensure_ascii=False,indent=4)

        print("已保存")

    except Exception as e:

        print(f"出错:{e}")

    return data['data']['list'] if data ['code'] ==0 else []

#                    只返回有用部分的信息                返回空列表





#分析数据

def analyze_data(videos):

    df = pd.DataFrame(

        [

            {

                '排名':idx +1,#索引操作

                '标题':v.get('title',"未命名视频"),#若没有,就做数据清洗,

                '作者':v['owner'].get('name','未知作者'),

                '播放量':v['stat'].get('view',0),

                '弹幕数': v['stat'].get('danmaku', 0),

                '点赞数': v['stat'].get('like', 0),

                '收藏数': v['stat'].get('favorite', 0),

                '时长(秒)': v.get('duration', 0)

            }for idx,v in enumerate(videos)#索引

        ]

    )



    print("数据概况分析")

    print(f"数据量:{df.shape[0]}行*{df.shape[1]}列")

    print("\n特征列表:",df.columns.tolist())



    numeric_stats = df.select_dtypes(include=np.number).describe()

    #               筛选出值为数据的

    print("\n数值型特征统计:")

    print(numeric_stats.round(2))

    #保留2位小数

    print("索引")

    df.set_index('排名',inplace=True)

    #设置排名为索引



    print("数据选择操作")

    print("按位置选择前五行播放量和点赞数:")

    print(df.iloc[:5,[3,5]])

    high_view_df=df[df['播放量']>1000000]

    #选择筛选视频播放量大的

    print(f"\n播放量>10000000的视频数量:{len(high_view_df)}")



    print("数据运算")

    df['互动量']=df['点赞数']+df['收藏数']+df['弹幕数']

    df['互动率']=np.divide(

        df['互动量'],

        df['播放量'],

        out=np.zeros_like(df['播放量'],dtype=np.float64),

        #out在np中用于指定输出结果的储存位置,预分配输出数组,而且长得跟df['播放量']一样

        where=df['播放量']!=0

    ).round(4)



    #数据清洗

    df_clean=df.drop_duplicates()



    print("数据的分组与聚合")

    author_group=df_clean.groupby('作者').agg(

        {

            '播放量':['sum','mean','count'],

            #        总和  均值      数量(同一个作者的有几个视频的播放量)

            '互动率':'mean'

        }

    ).sort_values(('播放量','sum'),ascending=False)

    print("作者播放量排名前五:")

    print(author_group.head(5))

    df_clean['时长分组']=pd.cut(

       df_clean['时长(秒)'],

       bins=[0,60,300,900,np.inf],

       labels=['<1分钟','1-5分钟','5-15分钟','>15分钟'])

    time_group = df_clean.groupby('时长分组',observed=False).agg({

       #确保了即使某些时长分组在数据中没有视频,这些分组仍然会出现在结果中

       '播放量':'sum',

       '互动率':'mean',

       '标题':'count'

   }).sort_values('播放量',ascending=False)

    print("\n不同时长视频播放量分布:")

    print(time_group)

    return df_clean



def generate_wordcloud(df,output_file='title_wordcloud.png'):

    print("\n生成标题词云图")

    all_titles = ' '.join(df['标题'].tolist())

    #             连接所有标题的分隔符    111 222 333

    words = jieba.cut(all_titles)#返回的是一个 生成器对象,特殊迭代器

    words_list = [word for word in words if len(word)>1]

    words_text = ' '.join(words_list)

    stopwords=set(

        [

            '的', '了', '和', '是', '在', '我', '有', '这', '个', '到', '就', '都', '着', '也', '让', '与', '中', '上','为', '你'

        ]

    )



    wc = WordCloud(

        font_path=font_path,  # 指定中文字体,确保中文正常显示

        width=800,

        height=400,

        background_color='white',

        max_words=100,

        stopwords=stopwords,#停用

        colormap='viridis'#它决定了词云中不同频率的词语将以何种颜色显示

    )

    wc.generate(words_text)

    plt.figure(figsize=(10,6))

    plt.imshow(wc,interpolation='bilinear')#像素之间创建平滑的颜色过渡

    plt.axis('off')#省去坐标轴

    plt.title("B站热门视频标题词云图")

    plt.tight_layout()



    plt.savefig(output_file,dpi=300, bbox_inches='tight')

    print("词云图已保存")#    分辨率     裁剪图像周围的空白区域,使图像边界更紧凑





def visualize_data(df):

    plt.figure(figsize=(12,8))

    #直方图

    plt.subplot(2,2,1)#坐标

    sns.histplot(df['播放量'],bins=100,kde=True,color='blue')

    plt.title('播放量分布')#           曲线





    #线图

    plt.subplot(2,2,2)

    sns.lineplot(x=df.index,y='播放量',data=df,marker='o',color='red')

#                             在data中找,并作为轴标题

    plt.title('排名与播放量趋势')



    #条形图

    plt.subplot(2,2,3)

    df[['点赞数','收藏数','弹幕数']].mean().plot(kind='bar',color=['gold','green','purple'])

    plt.title('平均互动指标对比')

    plt.xticks(rotation=0)  # 设置x轴标签水平显示



    #散点图

    plt.subplot(2,2,4)

    sns.scatterplot(x='播放量',y='互动率',data=df,hue='排名')

    plt.title('播放量与互动率的关系')



    plt.tight_layout()

    plt.savefig('bilibili_analysis.png')

    plt.show()











def main():

    print("开始获取B站数据")

    videos = fetch_bilibili_data()

    if not videos :

        print("数据获取失败!")

        return



    df_clean = analyze_data(videos)

    df_clean.to_csv('bilibili_clean.csv', index=False, encoding='utf-8-sig')

#                                           避免索引列的生成

    generate_wordcloud(df_clean)



    visualize_data(df_clean)



if __name__ == "__main__":

    main()

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐