thepoy 发表于 2019-7-19 21:56

bilibili批量获取视频下载链接脚本,请大家指教

本帖最后由 thepoy 于 2019-9-19 10:50 编辑

首先要找到视频的唯一ID,翻来翻去才找到。

本人刚玩B站,不是很了解,不知道这个 aid 是不是传说中的番号

以链接 https://www.bilibili.com/video/av14184325/ 为例,共536个视频。
红框里可以看见每个视频都有唯一的ID——cid。
接下来就简单了,正则表达式(bs4也可以),将所有的视频信息都挑出来。    *   不知道这种情况用正则表达式好还是bs4好,请大佬指教!

在kanbilibili上找到下载链接



----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我想直接通过python进行视频下载,实时显示下载进度和网速,但是能力有限,不知道怎么敲代码。


请问大佬们,应该怎么实现呢?
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面是下载和重命名的代码,运行完下载脚本后,会在脚本所在的目录下生成一个存储你所选择的集数范围的下载链接的txt和一个存储所有视频文件名的txt。

需要注意的是:
    1、解释器的路径(就是第一行#!/usr....)需要改成自己电脑上python的路径
    2、下载脚本第92行,会在你指定的路径下创建一个以aid命名的目录,一定要改成你自己想要保存的路径。   
    3、重命名脚本第27行,改成与第2条里相同的路径。

下载code:
#!/usr/local/Cellar/python/3.7.4/bin/python3
# -*- coding: utf-8 -*-

import requests
import json
import re
import os

# 获取所有的视频信息
def videos_info(headers, aid):
    # av后面的数字就是 aid
    b_url = 'https://api.bilibili.com/x/web-interface/view?aid=' + aid
    web_data = requests.get(b_url,headers=headers)
    all_info = json.loads(web_data.text)
    return all_info['data']['pages']

# 从kanbilibili中找到包含每一个视频的下载链接的链接
def videos_url(start, end, all_info, aid):
    if end == 0:
      end = len(all_info)
    while True:
      choice = input('你是否要下载 %d 集到 %d 集的视频?(Y/n)' % (start, end))
      if choice == 'Y' or choice == 'y':
            break
      elif choice == 'N' or choice == 'n':
            pass
      else:
            print('你的选择有误,选择指令["Y"]为是,["n"]为否,请重新选择!')
            continue
      start = input('请重新输入你要从哪一集开始下载:(默认:1)')
      if start == '':
            start = 1
      else:
            start = int(start)
      end = input('请重新输入到哪一集结束(默认:最后一集):')
      if end == '':
            end = len(all_info)
      else:
            end = int(end)
    urls = []
    print('正在获取所选视频的下载链接,请稍候...')
    # start-1是要下载的第一个视频的索引(下标),end本身到不了,不需要-1
    for i in all_info:
      page = str(all_info.index(i) + start)
      # 到这步的时候我才发现之前的videos_info可以完全不通过B站搞定,B站爬数据还得用cookie
      # 有kanbilibili这种神奇的网哪里用那么麻烦
      # 在kanbilibili上选择好清晰度「quality」只有三个值:32(480p), 64(720p), 80(1080p)]
      # 我用的是80,可以自己设置
      url = 'https://www.kanbilibili.com/api/video/' + aid + '/download?cid=' + str(i['cid']) + '&quality=80&page=' + page
      urls.append(url)
    return urls

# 真正的视频下载链接
def down_urls(urls,headers):
    down_urls = []
    for i in urls:
      down_web = requests.get(i,headers=headers)
      tmp = json.loads(down_web.text)
      # 一大堆字典里挑出有用的数据对我来说是最头疼的事,我是一点一点肉眼找的,不知道有没有好的办法
      down_url = tmp['data']['durl']['url']
      down_urls.append(down_url)
    return down_urls

def main():
    while True:
      url = input('请随便输入一集你要下载的视频的链接:')
      if url == '':
            print('您的输入为空,请重新输入!')
            continue
      else:
            break
    headers = {
      'UserAgent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
      'Cookie': "你自己的cookie"
    }
    aid = re.search(r'av(\d*)', url).group(1)
    all_info = videos_info(headers, aid)
    print('此专辑共有 %d 集视频。' % all_info[-1]['page'])
    start = input('你要从哪一集开始下载?(默认:1)')
    if start == '':
      start = 1
    else:
      start = int(start)
    end = input('你想下到哪一集结束?(默认:最后一集)')
    if end == '':
      end = 0
    else:
      end = int(end)
    all_urls = videos_url(start, end, all_info, aid)
    urls = down_urls(all_urls, headers)
    try:
      os.mkdir('/Volumes/MAC专用/前端/' + str(aid))
    except FileExistsError:
      pass
    # 记录所有视频的名字和cid到aid.txt中,方便为下载的所有视频重命名
    with open(str(aid) + '.txt', 'w') as f:
      for i in all_info:
            f.write('%d %s,%d\n' % (all_info.index(i) + 1, i['part'], i['cid']))
    # 将所有链接存放进cid_down.txt中,方便后续下载
    with open(str(aid) + '_down.txt', 'w') as f:
      for i in urls:
            f.write(i + '\n')
    print('已获取全部的下载链接,请查看当前目录下的 %s_down.txt 获取。' % str(aid))

if __name__ == '__main__':
    main()


批量重命名code:
#!/usr/local/Cellar/python/3.7.4/bin/python3
# -*- coding: utf-8 -*-

import os
import requests
import json

all_files = os.listdir()
first_dir = os.getcwd()
files = []
for i in all_files:
    prefix = i.split('.')
    if prefix.isdigit():
      files.append(i)
for i in files:
    os.chdir(first_dir)
    file_name_web = requests.get('https://api.bilibili.com/x/web-interface/view?aid=' + i[:8])
    file_name_data = json.loads(file_name_web.text)
    file_name = file_name_data['data']['title']
    name_file = open(i)
    names = {}
    for j in name_file:
      info = j.split(',')
      key = info[-1].split()
      name = info + '.flv'
      names = name
    files_dir = '/Volumes/MAC专用/前端/' + i[:8]
    os.chdir(files_dir)
    all_files = os.listdir(os.getcwd())
    for k in all_files:
      if '-1-80' in k or '-1-64' in k:
            #有的文件名需要用 '-' 切割,如果按通用条件没能完成全部重命名的话,可以试试
            if '_' in k:
                cid = k.split('_')
            else:
                cid = k.split('-')
            for l in names:
                if cid == l:
                  os.rename(k, names)
    os.rename(files_dir, files_dir[:-8] + file_name)

仙水 发表于 2019-7-19 23:11

不懂,纯支持一下。不过最近也在恶补这方面的知识来着

thepoy 发表于 2019-7-21 13:22

天域至尊 发表于 2019-7-21 10:19
推荐你在最后抛出下载的时候做下优化,可以让用户选择直接抛出系统链接,由默认下载器自己接。同时把下载链 ...

下载链接已经保存到txt里了,之前用wget试了试,下载速度不理想啊,我同样也是linux小白,正在学习linux,看能不能让wget速度快一点。
另外就是,你说的“让用户选择直接抛出系统链接,由默认下载器自己接”,请问怎么才能让下载器自己接呢?

逍遥一仙 发表于 2019-7-19 22:22

正则?这个不是标准的JSON格式吗

jidesheng6 发表于 2019-7-19 22:26

不用正则,你直接在新标签页打开网页,里面的response拿去json解析网站解析一下看看

jidesheng6 发表于 2019-7-19 22:28

既然已经有链接了,还有规定了范围,那就直接用request.get.content把返回来的字节文件保存起来就行了

jidesheng6 发表于 2019-7-19 22:30

python有进度条模块,但是放心吧,你用pip下载的时候那个进度条就是python的一个库

好好阳光 发表于 2019-7-19 23:25

学习了高手解释还得消化{:1_901:}

lajihongqi 发表于 2019-7-19 23:41

我还以为是福利来了哈哈

cwtzero 发表于 2019-7-19 23:50

这个确实不错,但是很多老旧的都看不了呢

lonely_coder 发表于 2019-7-20 00:58

现在哪是B站下不了东西,是B站没东西下啊
页: [1] 2
查看完整版本: bilibili批量获取视频下载链接脚本,请大家指教