一、爬取目标-B站排行榜
大家好,我是老王!
今天给大家分享一期python爬虫案例,这次爬取的对象是:B站热门排行榜数据
爬取的目标网址是:https://www.bilibili.com/v/popular/rank/all
咱们以目标为驱动,以兴趣为导向,先来看下爬虫程序运行后得到的excel文档数据:
那代码是如何实现B站排行榜数据爬取的了?下面逐一讲解一下python的实现。
二、B站排行榜网站分析
我们先来分析一下页面,这个页面包含多个分类下的排行榜的数据,首先按F12打开浏览器的抓包工具。
这里跟大家说一个抓包的技巧:先清空浏览器之前的所有请求,再点击某个分类,这样请求数会非常少,便于找到我们需要的接口
可以看到,总共发送了2个ajax请求,我们想要的数据就在这个v2的接口里。
现在我们来分析一下这个接口的请求参数:
发现有5个参数,经过老王的验证:后面3个参数不需要携带,也是可以请求成功的。
而这个rid参数,是藏在一个下面这个 popular.js 代码里的,那就好办了,下面直接开始撸代码....
三、B站排行榜爬虫代码详解
我们把上面这段js代码复制下来,放到python代码里
categorys = [{
"name": "全站",
"tid": 0,
"slug": "all"
}, {
"name": "番剧",
"type": "bangumi",
"tid": 13,
"slug": "bangumi",
"season_type": 1
}, {
"name": "国产动画",
"type": "bangumi",
"tid": 168,
"slug": "guochan",
"season_type": 4
}, {
"name": "国创相关",
"tid": 168,
"slug": "guochuang"
}, {
"name": "纪录片",
"type": "cinema",
"slug": "documentary",
"tid": 177,
"season_type": 3
}, {
"name": "动画",
"tid": 1,
"slug": "douga"
}, {
"name": "音乐",
"tid": 3,
"slug": "music"
}, {
"name": "舞蹈",
"tid": 129,
"slug": "dance"
}, {
"name": "游戏",
"tid": 4,
"slug": "game"
}, {
"name": "知识",
"tid": 36,
"slug": "knowledge"
}, {
"name": "科技",
"tid": 188,
"slug": "tech"
}, {
"name": "运动",
"tid": 234,
"slug": "sports"
}, {
"name": "汽车",
"tid": 223,
"slug": "car"
}, {
"name": "生活",
"tid": 160,
"slug": "life"
}, {
"name": "美食",
"tid": 211,
"slug": "food"
}, {
"name": "动物圈",
"tid": 217,
"slug": "animal"
}, {
"name": "鬼畜",
"tid": 119,
"slug": "kichiku"
}, {
"name": "时尚",
"tid": 155,
"slug": "fashion"
}, {
"name": "娱",
"tid": 5,
"slug": "ent"
}, {
"name": "影视",
"tid": 181,
"slug": "cinephile"
}, {
"name": "电影",
"type": "cinema",
"slug": "movie",
"tid": 23,
"season_type": 2
}, {
"name": "电视剧",
"type": "cinema",
"slug": "tv",
"tid": 11,
"season_type": 5
}, {
"name": "综艺",
"type": "cinema",
"slug": "variety",
"season_type": 7
}, {
"name": "原创",
"slug": "origin",
"tid": 0,
"rank_type": "origin"
}, {
"name": "新人",
"slug": "rookie",
"tid": 0,
"rank_type": "rookie"
}]
然后循环遍历这个分类列表,取出我们需要的tid,然后发送请求就可以了。
不过这里有一点要注意的是:这个排行榜的接口并不是固定的,他会针对不同的板块分成3个接口。下面是分别实现的代码。
板块1:全站、动画、音乐、舞蹈、游戏、知识、科技、运动、汽车、生活、美食、动物圈、鬼畜、时尚、娱乐、影视
def parse2(tid, rank_type):
"""
爬取:全站、动画、音乐、舞蹈、游戏、知识、科技、运动、汽车、生活、美食、动物圈、鬼畜、时尚、娱乐、影视
@param tid: id
@param rank_type: 类型
@return:
"""
# 发起请求,获得数据
url = "https://api.bilibili.com/x/web-interface/ranking/v2"
params = {
'rid': tid,
'type': 'all',
}
# 如果有值,则使用(针对原创、新人这2个分类)
if rank_type:
params['type'] = rank_type
resp = requests.get(url, params=params, headers=headers)
result = resp.json()
# 解析数据:标题 链接 作者 分类 发布时间 视频时长 播放数 弹幕数 回复数 点赞数 投币数 分享数 点赞数 不喜欢数 发布位置
rank_list = result["data"]["list"]
title_list = []
short_link_list = []
author_list = []
tname_list = []
pubdate_list = []
view_list = []
danmaku_list = []
reply_list = []
favorite_list = []
coin_list = []
share_list = []
like_list = []
pub_location_list = []
for rank in rank_list:
title_list.append(rank.get("title")) # 标题
short_link_list.append(rank.get("short_link_v2")) # 短链
author_list.append(rank["owner"]["name"]) # 作者
tname_list.append(rank["tname"]) # 分类
pubdate = rank["pubdate"] # 发布时间
pubdate = datetime.datetime.fromtimestamp(pubdate)
pubdate = pubdate.strftime('%Y-%m-%d %H:%M:%S')
pubdate_list.append(pubdate)
pub_location_list.append(rank.get("pub_location")) # pub_location这个键可能不存在,所以这里用get函数
stat = rank["stat"]
view_list.append(stat["view"]) # 播放数
like_list.append(stat["like"]) # 点赞数
danmaku_list.append(stat["danmaku"]) # 弹幕数
reply_list.append(stat["reply"]) # 回复数
favorite_list.append(stat["favorite"]) # 点赞数
coin_list.append(stat["coin"]) # 投币数
share_list.append(stat["share"]) # 分享数
return {
"标题": title_list,
"作者": author_list,
"链接": short_link_list,
"分类": tname_list,
"发布时间": pubdate_list,
"播放数": view_list,
"点赞数": like_list,
"弹幕数": danmaku_list,
"回复数": reply_list,
"收藏数": favorite_list,
"投币数": coin_list,
"分享数": share_list,
"发布位置": pub_location_list
}
板块2:国产动画、纪录片、电影、电视剧、综艺
def parse1(season_type):
"""
爬取:国产动画、纪录片、电影、电视剧、综艺
@param season_type: 类型
@return:
"""
url = 'https://api.bilibili.com/pgc/season/rank/web/list'
params = {
'day': '3',
'season_type': season_type,
}
resp = requests.get(url, params=params, headers=headers)
result = resp.json()
# 解析数据
rank_list = result["data"]["list"]
title_list = []
url_list = []
rating_list = []
desc_list = []
play_list = []
view_list = []
follow_list = []
danmaku_list = []
for rank in rank_list:
title_list.append(rank.get("title")) # 标题
url_list.append(rank.get("url")) # 链接
rating_list.append(rank["rating"]) # 评分
desc_list.append(rank["desc"]) # 更新至多少集
play_list.append(rank["icon_font"]["text"]) # 播放数
stat = rank["stat"]
view_list.append(stat["view"]) # 播放数
follow_list.append(stat["follow"]) # 关注数
danmaku_list.append(stat["danmaku"]) # 弹幕数
return {
"标题": title_list,
"链接": url_list,
"评分": rating_list,
"描述": desc_list,
"播放数1": play_list,
"播放数": view_list,
"关注数": follow_list,
"弹幕数": danmaku_list,
}
板块3:番剧
def parse_fanju(season_type):
"""
爬取番剧
@param season_type: 类型
@return:
"""
url = 'https://api.bilibili.com/pgc/web/rank/list'
params = {
'day': '3',
'season_type': season_type
}
resp = requests.get(url, params=params, headers=headers)
result = resp.json()
# 解析数据
rank_list = result["result"]["list"]
title_list = []
url_list = []
rating_list = []
desc_list = []
play_list = []
view_list = []
follow_list = []
danmaku_list = []
for rank in rank_list:
title_list.append(rank.get("title")) # 标题
url_list.append(rank.get("url")) # 链接
rating_list.append(rank["rating"]) # 评分
desc_list.append(rank["new_ep"]["index_show"]) # 更新至多少集
play_list.append(rank["icon_font"]["text"]) # 播放数
stat = rank["stat"]
view_list.append(stat["view"]) # 播放数
follow_list.append(stat["follow"]) # 关注数
danmaku_list.append(stat["danmaku"]) # 弹幕数
return {
"标题": title_list,
"链接": url_list,
"评分": rating_list,
"描述": desc_list,
"播放数1": play_list,
"播放数": view_list,
"关注数": follow_list,
"弹幕数": danmaku_list,
}
最后,我们将获得到的数据,调用to_csv()方法导出成文件即可:
def save_to_csv(data, csv_name):
"""
数据保存到csv
@param dms: 弹幕列表数据
@param csv_name: csv文件名字
@return:
"""
# 把列表转换成 dataframe
df = pd.DataFrame(data)
# 写入数据
df.to_csv(csv_name, index=False, encoding="utf_8_sig")
注意,此处有坑!!
to_csv的时候,一定要加上参数 encoding='utf_8_sig' 的选项,不然保存后的数据会乱码,尤其是windows系统用户!
四、B站排行榜结果
这样我们就得到了B站排行榜所有分类下的csv文件了,效果图如下:
我们随便打开一个排行榜分类来看一下
1、电影排行榜
2、游戏排行榜
3、番剧排行榜
五、python爬虫源代码获取
我是@王哪跑,持续分享python干货,各类副业技巧及软件!
附完整python源码及csv表格数据:
【看文末回复关键字"B站100",即可免费获取完整版B站热门排行榜python爬虫源码】