Bilibili.com(B站)数据下载工具包。若您在使用过程中发现BUG或有可以改进之处,欢迎提交Issue或邮件(mailto@wolfbolin.com)与我联系。如果觉得还不错,欢迎Star和Fork支持一下(两百个Star冲鸭)。
特别提醒:鉴于B站快速的发展,目前代码包中仍在使用一些新版中废弃的接口,如果某日B站关闭了旧接口服务,可能会导致本函数包不可用(虽然已经找到了新的获取方式,但是懒得改代码了,非Json接口获取成本++)
特性
- 用户与频道内视频批量下载
- 支持360P至4K全部画质下载
- 开放灵活详细的API编程接口
- 多链接分块下载与自动合成
常见问题请参考Q&A | BUG修复请参考更新日志 | 新的疑问请参考反馈列表
一、安装方式
二、使用样式
三、接口文档
四、Q&A
六、更新日志
本工具包采用pip方式发布,并需要调用本地aria2c与ffmpeg插件,工具包启动前将根据环境变量检查环境是否可用,当环境中缺少相关插件时,部分类将不会导入。
Step 1: 使用pip安装
pip install BiliUtil
Step 2: 安装Aria2c插件
Step 3: 安装FFmpeg插件
插件官网:https://ffmpeg.org/
获取视频信息并下载视频
import BiliUtil
from cookie import cookie_info
if __name__ == '__main__':
# DNA视频下载
album = BiliUtil.Album("170001")
# album = BiliUtil.Album("av170001")
# album = BiliUtil.Album("BV17x411w7KC")
# album.set_album("456025297")
# album.set_album("av456025297")
# album.set_album("BV17x411w7KC")
# album.set_by_url("https://www.bilibili.com/video/av170001")
# album.set_by_url("https://www.bilibili.com/video/BV17x411w7KC")
# 4K视频下载测试
# album = BiliUtil.Album("BV1QV411R7d1")
album_info = album.sync()
print(album_info)
video_list = album.get_video_list()
print(video_list)
for video in video_list:
video.sync(cookie=cookie_info)
task = BiliUtil.Task(video, 'D:/BiliUtil', album.aid)
task.start()
获取用户信息并下载所有视频
import BiliUtil
if __name__ == '__main__':
cookie = "SESSDATA=abcd68fd..."
cache = "D:/BiliUtil"
user = BiliUtil.User(20165629) # 他发的太多了,建议换个人尝试
# user.set_user(user)
# user.set_by_url("https://space.bilibili.com/20165629")
user_info = user.sync()
print(user_info)
fetcher = BiliUtil.Fetcher(user)
av_list = fetcher.fetch_all(cookie, BiliUtil.Config.SET_AS_NAME)
print(av_list)
positive_list, negative_list = fetcher.load_exist(cache)
print(positive_list)
print(negative_list)
task_id = fetcher.load_task(cache, positive_list, cache)
download_list = fetcher.pull_all()
print('完成{}个视频下载:{}'.format(len(download_list), download_list))
高配版示例程序请见example3.py和example4.py,其中example4.py是我个人自测自用程序,涉及大多数使用场景,可靠性与适用性MAX
在第四章Q&A中将讲解常见问题与逻辑结构,如有需要请移步第四章,那里可能有你想问的。本章仅讲解工具包的使用方法,简单粗暴便于理解。
常量中包含了文件命名方式的定义,画质信息的定义,全局代理设置的定义等内容。
常量 | 值 | 含义 |
---|---|---|
命名方式 | ||
SET_AS_NAME | 1 | 以视频名称命名 |
SET_AS_CODE | 2 | 以对象编号命名 |
SET_AS_PAGE | 3 | 以分P文件命名 |
网络代理 | ||
HTTP_PROXY | 例http://user:pass@1.2.3.4:5678 | HTTP代理设置 |
HTTPS_PROXY | 例https://user:pass@1.2.3.4:5678 | HTTPS代理设置 |
视频画质 | ||
Quality.V360P | ('16', '流畅 360P') | 360P |
Quality.V480P | ('32', '清晰 480P') | 480P |
Quality.V720P | ('64', '高清 720P') | 720P(登录) |
Quality.V720P60 | ('74', '高清 720P60') | 720P60(会员) |
Quality.V1080P | ('80', '高清 1080P') | 1080P(登录) |
Quality.V1080Px | ('112', '高清 1080P+') | 1080P+(会员) |
Quality.V1080P60 | ('116', '高清 1080P60') | 1080P60(会员) |
Quality.V4K | ('120', '超清 4K') | 4K(会员) |
该函数可将形如av170001
,170001
的av号转化为形如BV17x411w7KC
的新编码方式
编码转换算法代码参考来源:https://blog.csdn.net/jkddf9h8xd9j646x798t/article/details/105124465
该函数可将形如BV17x411w7KC
的bv号转化为形如170001
的旧编码方式
编码转换算法代码参考来源:https://blog.csdn.net/jkddf9h8xd9j646x798t/article/details/105124465
该函数可识别av、bv号并都转化为bv号的编码形式
该函数可识别av、bv号并都转化为av号的编码形式
__init__(uid=None)
你可以为每一个用户声明一个对象实例,在声明时你可以指定用户uid或在同步数据前设定用户uid。
user = BiliUtil.User('20165629')
每个实例中将包含以下成员变量,你可以在sync()
操作后读取这些信息。
成员变 | 变量含义 |
---|---|
uid | 用户uid |
name | 用户昵称 |
birthday | 用户生日 |
title | 用户身份 |
face | 用户头像 |
time | 创号时间(可能为0) |
level | 用户级别 |
sex | 用户性别 |
sign | 用户签名 |
vip | 大会员 |
set_user(uid)
你可以使用该函数设定用户uid或重新指定用户uid。该操作不会重置成员变量。
user.set_user('20165629')
set_by_url(url)
你可以通过该函数以url解析的方式指定对象的用户uid。该操作不会重置成员变量。
user.set_by_url('https://space.bilibili.com/20165629?from=search')
sync(cookie=None)
你可用通过该操作更新对象的成员变量,如果你感觉信息不够丰满,请与开发者联系。
user_info = user.sync(cookie='SESSDATA=abcd68fd...')
get_channel_list(cookie=None)
你可以通过该操作获取用户公开的全部频道,返回值中将储存本工具包中频道类的对象。
channel_list = user.get_channel_list(cookie='SESSDATA=abcd68fd...')
get_album_list(cookie=None)
你可以通过该操作获取用户公开的全部视频,返回值中将储存本工具包中稿件类的对象。
get_album_list(cookie='SESSDATA=abcd68fd...')
__init__(uid=None, cid=None)
你可以为每一个用户声明一个对象实例,在声明时你可以指定用户uid、频道cid或在同步数据前设定用户uid、频道cid。
channel = BiliUtil.Channel(uid='20165629', cid='9108')
每个实例中将包含以下成员变量,你可以在get_album_list()
操作后读取这些信息。
成员变量 | 变量含义 | 默认值 |
---|---|---|
uid | 用户uid | None |
cid | 频道cid | None |
name | 频道名称 | None |
cover | 频道封面 | None |
count | 频道内稿件数量 | None |
set_channel(uid, cid)
你可以使用该函数设定频道cid或重新指定频道cid,同时必须指定频道对应用户uid。该操作不会重置成员变量。
channel.set_channel('20165629', '9108')
set_by_url(url)
你可以通过该函数以url解析的方式指定对象的用户uid和频道cid。该操作不会重置成员变量。
channel.set_by_url('https://space.bilibili.com/20165629/channel/detail?cid=9108')
get_album_list(cookie=None)
你可用通过该操作获取该频道中的全部稿件对象,返回值中将储存本工具包中稿件类的对象。
channel_info = channel.get_album_list(cookie='SESSDATA=abcd68fd...')
__init__(aid=None)
你可以为每一个稿件声明一个对象实例,在声明时你可以指定稿件aid(av号),或者同步数据前设定稿件aid(av号)。关于稿件与视频的区别请参考Q&A加强对名词的理解。
album = BiliUtil.Album('3947271')
每个实例中将包含以下成员变量,你可以在sync()
操作后读取这些信息。
成员变量 | 变量含义 | 默认值 |
---|---|---|
aid | 稿件aid(av号) | None |
num | 包含视频数量 | None |
type | 分区名称 | None |
cover | 封面链接 | None |
name | 视频名称 | None |
time | 发布时间 | None |
desc | 稿件描述 | None |
view | 观看人数 | None |
danmu | 弹幕数量 | None |
reply | 回复数量 | None |
favorite | 收藏数量 | None |
coin | 硬币数量 | None |
share | 分享数量 | None |
like | 点赞数量 | None |
cid_list | 视频cid编号列表 | None |
set_album(aid)
你可以使用该函数设定稿件aid或重新指定稿件aid,该操作不会重置成员变量。
album.set_user('3947271')
set_by_url(url)
你可以通过该函数以url解析的方式指定对象的稿件aid,该操作不会重置成员变量。
album.set_by_url('https://www.bilibili.com/video/av3947271')
album_name(name_pattern=Util.Config.SET_AS_CODE)
你可以通过该操作获取标准化的稿件名称,同时你可以通过参数的方式生成不同命名方式的名称
album_name = album.album_name()
sync(cookie=None)
你可用通过该操作更新对象的成员变量,如果你感觉信息不够丰满,请与开发者联系。
album_info = album.sync(cookie='SESSDATA=abcd68fd...')
get_video_list(cookie=None)
你可以通过该操作获取每个稿件中的视频对象,返回值中将储存本工具包中视频类的对象。
get_video_list(cookie='SESSDATA=abcd68fd...')
__init__(aid=None, cid=None)
不建议使用者自行创建视频对象,请使用稿件类的get_video_list()
操作获取视频类对象实例列表。
每个实例中将包含以下成员变量,你可以在sync()
操作后读取这些信息。
成员变量 | 变量含义 | 默认值 |
---|---|---|
album | 稿件对象 | None |
cid | 视频cid | None |
name | 视频名称(分P名称) | None |
page | 视频编号(分P序号) | None |
quality | 视频画质 | None |
length | 视频长度 | None |
format | 视频格式 | None |
height | 视频高度 | None |
width | 视频宽度 | None |
level | 视频版本 | None |
video | 视频链接 | list() |
audio | 视频链接 | list() |
video_name(name_pattern=Util.Config.SET_AS_CODE)
你可以通过该操作获取标准化的视频名称,同时你可以通过参数的方式生成不同命名方式的名称
video_name = video.video_name(Util.Config.SET_AS_PAGE)
sync(cookie=None, quality=None)
你可用通过该操作更新对象的成员变量,如果你感觉信息不够丰满,请与开发者联系。
你可以在同步视频信息时选择需要获取的视频画质,如果不指定,将默认按照可获取到的最高画质获取信息。
最高画质的获取与传入的Cookie信息有密切联系,有关Cookie与画质的关系请查阅Q&A
video_info = video.sync(
cookie='SESSDATA=abcd68fd...',
quailty=BiliUtil.Config.Quality.V1080P
)
该类的设计是针对有批量下载视频需求而设计,避免使用者自行完成所有下载流程的编写。请关注该类的使用流程与使用示例,奇怪的使用方式可能会触发不知道什么情况的BUG。
__init__(obj)
你可以使用用户类或频道类来初始化一个抓取器对象实例,不建议开发者操作实例中的对象数据。
fetch_all(cookie=None, name_pattern=SET_AS_CODE, quality=None)
请在初始化之后使用该函数获取对象名下所有的视频列表,并储存在对象内部变量中,为后续操作提供数据。
当初始化对象为用户类时,将自动获取用户名下的所有视频。当初始化对象为频道类时,将自动获取该频道中的所有视频。当文件命名命名方式为以名字命名时(SET_AS_NAME
),程序将自动调用视频对象的sync()
函数获取该视频的名称。你还可以传入视频质量的枚举以调整视频的最高质量,若无该参数则按照最高视频质量下载。
load_exist(ouput)
你可以使用该函数加载输出目录中已经存在的视频列表,返回值分为乐观策略和悲观策略。在乐观策略状态下稿件实例有存在视频即认为存在, 在悲观策略状态下稿件实例所有视频都存在才认为存在。
该函数的设计是为了避免在视频下载时程序重复下载视频浪费流量与时间,也避免过多请求被官方风控。
load_task(output, exclude=None, v_filter=None)
该函数可以帮助你在抓取器对象中生成一个任务列表,在任务列表中主要包含了任务类对象实例。
该函数提供了两个可选参数
pull_all(show_process=True, no_repeat=True)
在一切都准备好之后,你可以调用该函数完成视频的批量下载,程序将自动调用每一个任务实例中的start()
函数开始,函数的两个参数也将透传给任务对象。
__init__(video, output, name, cover=None)
在初始化任务类时,需要传入一个视频对象,输出文件夹路径,封面链接与视频命名。如果你觉得非常麻烦,请使用抓取器自动生成单个视频的下载任务。
start(show_process=True, no_repeat=True)
该函数将启动任务的下载流程,程序将按照实例化对象时的参数调用Aria2c完成视频与封面的下载。
关于在视频下载流程中会发生什么,请参考Q&A中关于视频下载的相关解释。
函数提供两个可选参数
__init__(quality=None, length=None, height=None, width=None, page=None, ratio=None)
你可以初始化一个过滤器对象用于过滤批量下载过程中不符合条件的视频(部分参数仅针对新类型的视频有效)
该函数提供了多个可选参数
你也可以使用set加对应参数名修改对象实例中的参数信息。
目前已完成开发的模块
目前尚存在缺陷的功能
期望或将要开发的功能
使用者在下载的过程中一般遵循一下步骤:初始化对象-->获取视频对象-->创建任务-->开始下载
在创建任务的过程中,程序将处理视频的储存位置与下载后视频名称的问题,并将不同层级的对象统一转化为任务,将任务作为下载的最小单元,方便编程与管理。
在下载过程中,程序将主要处理文件夹的建立,封面的下载、音画下载与音画合并。其中在核心的下载过程中,程序将根据情况自动采用多线程多连接的下载方式,并且减少分片大小,相比于v1.x的速度有大幅提高,不再会产生挂机一晚也下载不到视频的情况。
cookie信息不影响除视频画质外其他信息的获取。
通过cookie信息,你可以在下载视频的时候获取到更高清的视频数据,也可以手动指定视频清晰度。
设定cookie信息时,类似于_uuid=B45CF1AB-xxx; LIVE_BUVID=AUTO76154xxx; SESSDATA=abcd68fd%2C1123761144%2C38d97xyz
的cookie信息也是可以被识别的。也可以传入字典类型的cookie信息,但是cookie信息中必须包含SESSDATA
字段,该字段是提升视频质量的关键点。
不同的身份信息视频质量上限表:
未登录--->480P
已登录--->1080P
大会员--->1080P60FPS / 1080P+ / 4K120FPS
关键的cookie存在与发往*.bilibili.com
域下,发往其他域的请求中不包含该信息。至于如何在浏览器中获取Cookie,请移步:如何在浏览器中获取Cookie
首先说明这个"Album"在此不翻译为“唱片;专辑”,这个"Album"是指包含了多个视频的一个集合,在B站页面中显示为“稿件”,代表了用户的一次投稿发布。
众所周知许多Up会上传多P,多P就对应了多个视频,因此一个av号可能会对应多个视频。所以在文档中我们不能再使用“视频”这个词汇来表达一个av号所对应的资源,因此便采用了“稿件”这个词汇来表达。
我们需要为每一个资源做一个标记,官方也是这么做的。如果你真的经常使用B站,那么你一定知道UID为2的 碧诗和av号,本工具包沿用了B站的编号体系,不仅仅是用户与稿件,每一个频道与视频都是有他们自己的编号的。
当我们打开了用户或视频时,URL中就已经包含了我们生成对象所需要的信息。在声明对象实例时,我们可以利用这些信息,由于不是使用正则进行匹配的,因此你可以随心所欲的拷贝URL,包括带有参数的URL都是可以接受的。但是,请确保传入的URL是与对象类型相匹配的,否则可能会导致程序运行异常。
在B站更新了数据下发形式后,你所观看的每一个视频都由纯视频和纯音频的形式下发,因此我们在下载之后需要使用工具将这些数据封装在一起。工具的使用方法我已经封装在代码中,默认会在视频下载结束后完成合并渲染。
目前视频的版本主要分为两种,由程序内部自动判断。对于旧版视频,因为在下载前无法获取视频的具体参数,因此不可使用过滤器中的部分功能,而且旧版视频音画是在同一个视频容器中,因此无需合并数据,但同时旧版视频仅支持单链接下载,没有多服务器下发的能力。视频的下载速度可能会受到影响。
根据B站的限制,拥有不同身份的用户能够看到的视频数据有所不同,因此在下载视频时应尽量使用有大会员的用户身份进行下载。否则,即使你在程序中指定的是v1080Px也无法获取到该画质的视频。毕竟这个工具包不是搞大会员破解的。
在本工具包开发直出还没有BV号的概念,所有代码中对于一个稿件的唯一性判断都已AV号为准,因此在兼容BV号的过程中,工具包在所有可能输入BV号的入口都添加了BV=>AV转换的函数。该转换函数仅依赖本地计算即可完成,无需网络调用,不影响下载流程与性能。但是如果您需要对代码进行Debug,需要注意的是在工具包内部的函数调用与网络访问都是以AV号进行的。
其他未尽适宜请提Issue
这个包中还有很多未完成的细节,还有一些想实现的功能未完成。 欢迎有兴趣的小伙伴一次参与,反馈BUG,更新代码,提供方案,我们共同完善它。
你可以联系我:mailto@wolfbolin.com
声明:该代码库内容仅供学习参考,请勿用于商业目的
修复
新增
计划
修复
优化
缺陷
修复
新版发布
修复
修复
修复
修复
修复
新增
新增
解决ffmpeg合成阶段程序卡死。由于pipe size的大小限制,导致程序在收到超过64kb的输出时,程序会卡死不动。修改process.wait()为process.communicate()以解决该问题。
操作失误导致pip中v0.1.2版本被删除,将以v0.1.3版本发布。建议更新至最新版本后再使用。
修改:
ffmpeg
环境检测不通过的BUG,因为使用了错误的语法。aria2c
时的错误语法,解决自定义输出路径报错。新增:
修改:
(=・ω・=)
输出BiliUtil已经过基础测试,正式发布第一个版本,若要直接使用,请使用pip进行安装。