写一个Python脚本下载哔哩哔哩舞蹈区的所有视频

 更新时间:2021年05月31日 10:24:18   作者:Python 技术  
B 站大家都熟悉,尤其是它的舞蹈区.有 100W+ 的舞蹈视频.在没有 wifi 的情况下,就欣赏不了这些视频了.作为一个 python 程序员,小编就写一个 Python 脚本在晚上下载舞蹈区的所有视频,需要的朋友可以参考下

一、抓取列表

首先点开舞蹈区先选择宅舞列表。

然后打开 F12 的控制面板,可以找到一条 https://api.bilibili.com/x/web-interface/newlist?rid=20&type=0&pn=1&ps=20&jsonp=jsonp&callback=jsonCallback_bili_57905715749828263 的 url,其中 rid 是 B 站的小分类,pn 是页数。

小编试着在浏览器将地址打开居然报了 404,可是在控制面板中这个地址的返回值明明就是视频列表。试着去掉 callback 的参数,意外的得到了想要的结果。

众所周知 bid 是一个 B 站视频的唯一 ID,想要获取 bid 可以从上面 url 的返回值中提取 aid,然后将 aid 转换为 bid。

Str = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'  # 准备的一串指定字符串
Dict = {}
 
# 将字符串的每一个字符放入字典一一对应 , 如 f对应0 Z对应1 一次类推。
for i in range(58):
    Dict[Str[i]] = i
 
s = [11, 10, 3, 8, 4, 6, 2, 9, 5, 7]  # 必要的解密列表
xor = 177451812 
add = 100618342136696320  # 这串数字最后要被减去或加上
 
def algorithm_enc(av):
    ret = av
    av = int(av)
    av = (av ^ xor) + add
    # 将BV号的格式(BV + 10个字符) 转化成列表方便后面的操作
    r = list('BV          ')
    for i in range(10):
        r[s[i]] = Str[av // 58 ** i % 58]
    return ''.join(r)
 
 
def find_bid(p):
    bids = []
    r = requests.get(
            'https://api.bilibili.com/x/web-interface/newlist?&rid=20&type=0&pn={}&ps=50&jsonp=jsonp'.format(p))
      
    data = json.loads(r.text)
    archives = data['data']['archives']
 
    for item in archives:
        aid = item['aid']
        bid = algorithm_enc(aid)
        bids.append(bid)
 
    return bids

二、获取视频的 CID

想要下载 1080 的视频,光有 bid 是不够的,还需要 登录后 Cookie 中的 SESSDATA 值和 cid 。

首先登录 B 站将 Cookie 中的 SESSDATA 复制到对象头中。用地址为 https://api.bilibili.com/x/player/pagelist?bvid= url 返回 cid。

def get_cid(bid):
    url = 'https://api.bilibili.com/x/player/pagelist?bvid=' + bid
 
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
        'Cookie': 'SESSDATA=182cd036%2C1636985829%2C3b393%2A51',
        'Host': 'api.bilibili.com'
    }
 
    html = requests.get(url, headers=headers).json()
 
    infos = []
 
    data = html['data']
    cid_list = data
    for item in cid_list:
        cid = item['cid']
        title = item['part']
        infos.append({'bid': bid, 'cid': cid, 'title': title})
    return infos

三、下载视频

下载视频的 https://api.bilibili.com/x/player/playurl 来自于每次视频播放完之后的推荐列表。

最后使用 urllib.request.urlretrieve 函数下载视频。

def get_video_list(aid, cid, quality):
    url_api = 'https://api.bilibili.com/x/player/playurl?cid={}&bvid={}&qn={}'.format(cid, aid, quality)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
        'Cookie': 'SESSDATA=182cd036%2C1636985829%2C3b393%2A51',
        'Host': 'api.bilibili.com'
    }
    html = requests.get(url_api, headers=headers).json()
    video_list = []
 
    for i in html['data']['durl']:
        video_list.append(i['url'])
    return video_list
 
def schedule_cmd(blocknum, blocksize, totalsize):
    percent = 100.0 * blocknum * blocksize/ totalsize
    s = ('#' * round(percent)).ljust(100, '-')
    sys.stdout.write('%.2f%%' % percent + '[' + s + ']' + '\r')
    sys.stdout.flush()
 
def download(video_list, title, bid):
    for i in video_list:
        opener = urllib.request.build_opener()
        opener.addheaders = [
            ('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'),
            ('Accept', '*/*'),
            ('Accept-Language', 'en-US,en;q=0.5'),
            ('Accept-Encoding', 'gzip, deflate, br'), 
            ('Range', 'bytes=0-'),  
            ('Referer', 'https://www.bilibili.com/video/'+bid),
            ('Origin', 'https://www.bilibili.com'),
            ('Connection', 'keep-alive'),
 
        ]
 
        filename=os.path.join('D:\\video', r'{}_{}.mp4'.format(bid,title)) 
 
        try:
            urllib.request.install_opener(opener)
            urllib.request.urlretrieve(url=i, filename=filename, reporthook=schedule_cmd) 
        except:
            print(bid + "下载异常,文件:" + filename)

到此这篇关于写一个Python脚本下载哔哩哔哩舞蹈区的所有视频的文章就介绍到这了,更多相关python下载哔哩哔哩视频内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python实现C#代码生成器应用服务于Unity示例解析

    Python实现C#代码生成器应用服务于Unity示例解析

    为了满足项目需要,需要实现一个c#代码生成器,为此设计了一个语法模板适用于Unity的代码生成器。本次使用了Python的Template模板,使用python开发
    2021-10-10
  • python根据url地址下载小文件的实例

    python根据url地址下载小文件的实例

    今天小编就为大家分享一篇python根据url地址下载小文件的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • Python中getpass模块无回显输入源码解析

    Python中getpass模块无回显输入源码解析

    这篇文章主要介绍了Python中getpass模块无回显输入源码解析,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 使用Flask-Login模块实现用户身份验证和安全性

    使用Flask-Login模块实现用户身份验证和安全性

    当你想要在你的Flask应用中实现用户身份验证和安全性时,Flask-Login这个扩展将会是你的最佳伙伴,它提供了一组简单而强大的工具来处理,下面我们就来看看具体的操作方法吧
    2023-08-08
  • python删除指定类型(或非指定)的文件实例详解

    python删除指定类型(或非指定)的文件实例详解

    这篇文章主要介绍了python删除指定类型(或非指定)的文件,以实例形式较为详细的分析了Python删除文件的相关技巧,需要的朋友可以参考下
    2015-07-07
  • Python使用Kubernetes API访问集群

    Python使用Kubernetes API访问集群

    本文主要介绍了Python使用Kubernetes API访问集群,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • 使用Python Turtle库带你玩转创意绘图(画个心,写个花)

    使用Python Turtle库带你玩转创意绘图(画个心,写个花)

    Python的turtle库提供了一种有趣且易于上手的编程绘图方式,适合初学者学习,通过本文的介绍,你将了解到如何进行画布设置、画笔属性的调整、画笔的移动与控制,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-11-11
  • Python中函数eval和ast.literal_eval的区别详解

    Python中函数eval和ast.literal_eval的区别详解

    eval函数在Python中做数据类型的转换还是很有用的。它的作用就是把数据还原成它本身或者是能够转化成的数据类型。那么eval和ast.literal_val()的区别是什么呢?本文将大家介绍关于Python中函数eval和ast.literal_eval区别的相关资料,需要的朋友可以参考下。
    2017-08-08
  • python切片操作方法的实例总结

    python切片操作方法的实例总结

    所谓切片就是在某个数据里提取需要的部分,提取到的是某个索引下的值,或者索引区间的值,下面这篇文章主要给大家介绍了关于python切片操作方法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • 解决django后台样式丢失,css资源加载失败的问题

    解决django后台样式丢失,css资源加载失败的问题

    今天小编就为大家分享一篇解决django后台样式丢失,css资源加载失败的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06

最新评论