利用B站公开API爬取简单信息(富含超详细注释的完整代码)
摘要:
本实训报告聚焦于运用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 站服务条款与网络爬虫行业规范:
- 合规数据采集:优先使用官方 API 接口,规避对网页的直接爬取,减少服务器负载压力。
- 模拟正常访问:通过设置合理的User-Agent与Referer请求头信息,模拟真实用户访问行为,维护平台数据安全与服务稳定性。
- 频率控制策略:尽管本次实训数据请求规模较小,但在实际应用场景中,将建立动态请求频率控制机制,防止因过度请求影响平台正常运营。
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函数围绕数据质量提升与价值挖掘,构建了完整的数据预处理体系:
- 结构化转换:将原始数据列表转化为pandas DataFrame格式,实现数据的结构化存储与高效管理。
- 数据概览分析:运用df.shape、df.columns及describe()方法,快速掌握数据集规模、特征构成及数值分布情况。
- 索引优化处理:通过set_index方法将 “排名” 字段设为索引,提升数据查询与分析效率。
- 精准数据筛选:结合iloc位置索引与条件表达式,实现数据的灵活筛选与定向提取。
- 指标衍生计算:借助numpy向量化运算,精准计算互动量、互动率等衍生指标,并妥善处理除零异常场景。
- 数据质量净化:通过fillna填充缺失值、drop_duplicates去除重复记录,显著提升数据完整性与准确性。
- 分组聚合洞察:基于作者与视频时长维度进行分组聚合,深度挖掘不同群体的创作特征与受众反馈差异。
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可视化库,将抽象数据转化为直观图表:
- 播放量分布洞察:
通过sns.histplot绘制带核密度曲线的直方图,直观呈现播放量数据的分布形态与集中趋势。
- 排名趋势分析:
借助sns.lineplot生成排名 - 播放量趋势折线图,清晰展现二者的动态关联与变化规律。
- 互动指标对比:
利用df[['点赞数', '收藏数', '弹幕数']].mean().plot(kind='bar')绘制柱状图,实现不同互动指标的横向对比分析
- 互动率关联探索:
通过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()
更多推荐
所有评论(0)