前言 MATS在bilibili当UP主(MATSD10S )发布了不少视频,他告诉我第二天要删掉一些早期视频,吓得我想立刻把他的视频都下载下来好好收藏,于是这个程序就出来了
想法 我知道有这么一款命令行式的工具 特别方便,叫做you-get (使用python编写),下载视频相当方便,如果直接使用它,能够省下不少功夫
使用程序调用you-get,只需要一个个自动填入视频ID下载就行了
为保证you-get能使用,请使用pip或其它方法安装you-get
为了迅速完成,我选择了Python3进行程序编写
运行截图 我已经把他的视频都下载下来了,如果你想收藏你喜欢的UP主的视频,这个程序或许对你有些帮助
运行中
完成任务
开始介绍 有兴趣的话建议先跳到本文的“相关知识 ”处再返回此处,无兴趣的话可以直接跳到“完整程序 ”复制程序使用
什么!你都不需要?那就随便看看吧,关掉这个页面也行
第一步 确定思路:
1、you-get只能下载一个页面中的视频,下载一个UP主的所有视频,就一次次调用you-get
2、调用you-get需要提供页面网址(可简化为视频ID),那么就要获取所有视频ID
3、猜想有输入UP主ID 的接口可以调用,直接获取所有视频ID
验证:
完全可行,相关信息可见本文的“相关知识 ”处
第二步 选择程序语言
为保证较短时间完成,使用Python3作为编写语言
第三步 开始编写程序
获取获取所有视频ID
注意页面数需试出来,返回的JSON信息没有提到页面总数(**#遍历所有页面** 处)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 json_headers_setting = {"user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" } def get_json_use_id (inf_setup ): req_s = requests.Session() json_all_data = req_s.get("https://api.bilibili.com/x/space/arc/search?mid={}" .format (inf_setup), headers=json_headers_setting).text del req_s return json_all_data dict_json_d = [] for i in range (1 , 1000 ): data_id_all = json.loads(get_json_use_id("{}&pn={}" .format (up_id, i))) if data_id_all["data" ]["list" ]["vlist" ] == []: break dict_json_d.append(data_id_all)
获取视频清晰度、格式信息
1 2 3 4 5 6 7 8 9 process = subprocess.Popen("you-get --json " + url_set, shell=True , stdout=subprocess.PIPE, stderr=subprocess.STDOUT) r_json = str (process.stdout.read().decode('utf-8' )) json_d_inf = json.loads(r_json) down_command = "" for i in json_d_inf["streams" ]: data_j_get = json_d_inf["streams" ][str (i)]
选择最高清晰度、MP4格式
1 2 3 4 5 6 7 8 9 10 11 12 process = subprocess.Popen("you-get --json " + url_set, shell=True , stdout=subprocess.PIPE, stderr=subprocess.STDOUT) r_json = str (process.stdout.read().decode('utf-8' )) json_d_inf = json.loads(r_json) down_command = "" for i in json_d_inf["streams" ]: data_j_get = json_d_inf["streams" ][str (i)] down_command = str (i) if data_j_get["container" ] == "mp4" : break
注意判断是否为多P视频,多P视频会有提示信息在开头 或者结尾 出现导致JSON无法被正确加载
变量d_ctl就是为了指示是否不是 多P视频
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 d_ctl = True if r_json[0 :1 ] != "{" : count_a = 0 for a in r_json: if a == "{" or a == "[" : break else : count_a += 1 ppp = "-p" d_ctl = False r_json = r_json[count_a:] if r_json[-3 :-2 ] != "}" : ppp = "-p" d_ctl = False r_json = r_json[:r_json.rindex("}" )+1 ]
第四步 前面信息已经准备完了,直接开始下载
1 2 3 4 if d_ctl: os.system("you-get --format={} {}" .format (down_command, url_set) else : os.system("you-get --playlist {}" .format (url_set))
所有步骤就到这里了
完整程序 程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 import jsonimport subprocessimport osimport requestsfrom datetime import datetimeup_id = "102067913" down_work_dir = "./video" json_headers_setting = {"user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" } if os.path.isdir(down_work_dir) == False : os.mkdir(down_work_dir) def down_when_vid_set (url_set ): process = subprocess.Popen("you-get --json " + url_set, shell=True , stdout=subprocess.PIPE, stderr=subprocess.STDOUT) r_json = str (process.stdout.read().decode('utf-8' )) ppp = "" d_ctl = True if r_json[0 :1 ] != "{" : count_a = 0 for a in r_json: if a == "{" or a == "[" : break else : count_a += 1 ppp = "-p" d_ctl = False r_json = r_json[count_a:] if r_json[-3 :-2 ] != "}" : ppp = "-p" d_ctl = False r_json = r_json[:r_json.rindex("}" )+1 ] json_d_inf = json.loads(r_json) title_get = json_d_inf["title" ] down_command = "" for i in json_d_inf["streams" ]: data_j_get = json_d_inf["streams" ][str (i)] down_command = str (i) if data_j_get["container" ] == "mp4" : break now_ttime = datetime.now().strftime('%a,%b%d,%H-%M-%S' ) dir_set = "{}/{}{}" .format (down_work_dir, now_ttime, ppp) os.mkdir(dir_set) if d_ctl: os.system("you-get --format={} {} -o {}" .format (down_command, url_set, dir_set)) else : os.system("you-get --playlist {} -o {}" .format (url_set, dir_set)) def get_json_use_id (inf_setup ): req_s = requests.Session() json_all_data = req_s.get("https://api.bilibili.com/x/space/arc/search?mid={}" .format (inf_setup), headers=json_headers_setting).text del req_s return json_all_data dict_json_d = [] for i in range (1 , 1000 ): data_id_all = json.loads(get_json_use_id("{}&pn={}" .format (up_id, i))) if data_id_all["data" ]["list" ]["vlist" ] == []: break dict_json_d.append(data_id_all) count_all = 0 count_q = 0 for i in dict_json_d: for ii in i["data" ]["list" ]["vlist" ]: count_all += 1 for i in dict_json_d: for ii in i["data" ]["list" ]["vlist" ]: count_q += 1 if count_q > 0 : print("Process at {:.1f}%" .format ((count_q/count_all)*100 )) try : print("At " , ii["bvid" ]) down_when_vid_set("https://www.bilibili.com/video/{}" .format (ii["bvid" ])) except : print("Error at " , ii["bvid" ]) os.mkdir(ii["bvid" ])
使用方法 修改此处,改成需要的UP主
1 up_id = "102067913" #设置UP主的ID
然后运行程序
相关知识 一些知识 了解you-get简单使用 简单用法 使用如下命令可以获取一个视频的可下载列表
下载单个视频 按照上图它提示的**you-get –format= [URL]**就可以开始选择需要的清晰度开始下载啦
按JSON返回信息 根据you-get的使用提示,还可以使用
来获取可下载列表,这样可以方便程序处理
下载多P视频 考虑到B站存在视频分Part
当遇到多P视频时使用这个命令下载省事很多,需要注意的是,下载的是FLV格式视频
设置下载存储文件夹
如上就是本文所涉及的所有you-get使用方法
在Python3中 requests库的部分用法 发起GET请求 只需要GET就能获取指定JSON,所以这里不提POST用法
1 2 3 4 import requestsreq_s = requests.Session() json_all_data = req_s.get("https://api.bilibili.com/" ) del req_s
设置请求头(伪造请求头) 为了防止网站认为是脚本进行抓取而拒绝访问,伪造请求头来假装自己是浏览器
设置header
1 json_headers_setting = {"user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" }
headers=
1 2 3 4 import requestsreq_s = requests.Session() json_all_data = req_s.get("https://api.bilibili.com/" , headers=json_headers_setting) del req_s
获取回复信息 .text
1 2 3 4 import requestsjson_all_data = req_s.get("https://api.bilibili.com/" , headers=json_headers_setting).text print(json_all_data) del req_s
安装requests库 如果提示requests无法调用,你可能还没有安装,可以使用pip进行安装
目录 操作需要os库
目录创建 有时可能会操作失败,最好使用try方法执行此语句
目录存在判断 此语句 目录存在就不新建目录 时会使用
运行命令行(CMD或shell) 用于调用you-get,当然也可以import you-get而不使用2这个方法
无输出(但可以将运行结果赋值给字符串)
演示运行ls命令
1 2 3 import subprocessprocess = subprocess.Popen("ls" , shell=True , stdout=subprocess.PIPE, stderr=subprocess.STDOUT) r_json = process.stdout.read().decode('utf-8' )
直接运行
1 2 import osos.system("ls" )
当前时间获取 使用python3自带的datetime库
1 2 3 from datetime import datetimenow_ttime = datetime.now().strftime('%a,%b%d,%H-%M-%S' ) print(now_ttime)
运行上述程序可以获得类似输出
JSON的使用 加载JSON 1 2 import jsonjson.loads()
读取JSON 1 2 3 4 import jsonj = '{"a" : "123abc"}' aaa = json.loads(j) print(aaa["a" ])
一些必须提前获取的东西 获取一个UP主所有的视频ID 根据请求追踪,我找到了这个网址
1 https://api.bilibili.com/x/space/arc/search?mid=
把UP主的ID填上去就能获取一串JSON,不过只记录了第一页的视频ID
想获取所有视频ID就得传入页数了
获取ID的示例链接 示例 示例如下,可以获取该UP主第二页的视频
1 https://api.bilibili.com/x/space/arc/search?mid=102067913&pn=2
注意 但是如果超过了UP主发布的视频页数,返回的JSON里的视频ID就会为空 ,所以需要注意
获取允许下载的视频参数 Bilibili上的视频是有清晰度 的,而且还分FLV和MP4 两种格式,所以使用you-get下载前最好先获取清晰度,再按此清晰度进行操作,否则会出错而无法下载
前面提过you-get可以返回json信息方便处理