吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11040|回复: 36
收起左侧

[Python 原创] B站视频多线程最高可达10倍速下载!

  [复制链接]
xccxvb 发表于 2020-6-18 21:12
本帖最后由 xccxvb 于 2020-6-18 21:12 编辑

B站视频多线程10倍速下载!哔哩哔哩bilibili。
先上成果图
NnuHSJ.png
NnuXex.png
线程数由你下载的文件大小决定的,小文件一个线程就够了,大文件最多会开启10个线程,也就是10倍速下载!
代码分两个文件,一个是主文件,一个是写多线程的
这是主文件

import requests
import re
import json
from multithreading import thread

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
}

url = input("请输入视频地址:")
with open('SESSDATA.txt', 'r') as f:
    SESSDATA = f.read()
if SESSDATA == '0':
    print('检测到您未设置SESSDATA,最高只能下载480p画质哦!')
#获取BV号
if '?' in url:
    url = url.split('?')[0]
    print(url)
bvid = re.search(r'BV.*', url).group()
print('BV号:'+bvid)
#获取cid
cid_json = requests.get('https://api.bilibili.com/x/player/pagelist?bvid={}&jsonp=jsonp'.format(bvid)).text
cid = re.search(r'{"cid":(\d+)', cid_json).group()[7:]
print('CID:'+cid)

#获取视频的av号
rsp = requests.get(url, headers=headers)
aid = re.search(r'"aid":(.*?),"', rsp.text).group()[6:-2]
print('AV号:'+aid)

#抓取视频真实地址,清晰度
qn = 16 #先设置一个默认低清晰度
headers['Referer'] = url
api_url = 'https://api.bilibili.com/x/player/playurl?cid={}&avid={}&qn={}&otype=json&requestFrom=bilibili-helper'.format(cid, aid, qn)
qn_dict = {}#用来存放清晰度选择参数
rsp = requests.get(api_url, headers=headers).content
rsp = json.loads(rsp)
qn_accept_description = rsp.get('data').get('accept_description')
qn_accept_quality = rsp.get('data').get('accept_quality')
print('下载视频清晰度选择')
for i, j, xuhao in zip(qn_accept_description, qn_accept_quality, range(len(qn_accept_quality))):
    print(str(xuhao+1)+':'+i)
    qn_dict[str(xuhao+1)] = j
xuhao = input('请选择(输入清晰度前的标号):')
qn = qn_dict[xuhao]
print('清晰度参数qn:'+str(qn))
api_url = 'https://api.bilibili.com/x/player/playurl?cid={}&avid={}&qn={}&otype=json&requestFrom=bilibili-helper'.format(cid, aid, qn)
#print('api_url='+api_url)
cookies = {}
cookies['SESSDATA'] = SESSDATA #这里输入你的SESSDATA
rsp = requests.get(api_url, headers=headers, cookies=cookies).content #这里代cookies才能得到会员或者登录后才能下载的视频的链接
rsp = json.loads(rsp)
real_url = rsp.get('data').get('durl')[0].get('url')
print('成功获取视频直链!')
print('正在开启多线程极速下载……')
thread(real_url, url, 'b站视频.flv')#多线程下载

#把上面那行删掉,把下面注释去掉就是单线程下载
#content = requests.get(real_url, headers=headers).content
#with open('1.flv', 'wb') as f:
#    f.write(content)

这是多线程文件:

import requests
import threading
import datetime
import time
#改headers参数和url就好了
def thread(url, Referer, file_name):
  # print(r.status_code, r.headers)
  headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
      'Referer': Referer
  }
  r = requests.get(url, headers=headers, stream=True, timeout=30)
  all_thread = 1
  # 获取视频大小
  file_size = int(r.headers['content-length'])
  # 如果获取到文件大小,创建一个和需要下载文件一样大小的文件
  if file_size:
    fp = open(file_name, 'wb')
    fp.truncate(file_size)
    print('视频大小:' + str(int(file_size / 1024 / 1024)) + "MB")
    fp.close()
  # 每个线程每次下载大小为5M
  size = 5242880
  # 当前文件大小需大于5M
  if file_size > size:
    # 获取总线程数
    all_thread = int(file_size / size)
    # 设最大线程数为10,如总线程数大于10
    # 线程数为10
    if all_thread > 10:
      all_thread = 10
  part = file_size // all_thread
  threads = []
  starttime = datetime.datetime.now().replace(microsecond=0)
  for i in range(all_thread):
    # 获取每个线程开始时的文件位置
    start = part * i
    # 获取每个文件结束位置
    if i == all_thread - 1:
      end = file_size
    else:
      end = start + part
    if i > 0:
      start += 1
    headers = headers.copy()
    headers['Range'] = "bytes=%s-%s" % (start, end)
    t = threading.Thread(target=Handler, name='线程-' + str(i),
               kwargs={'start': start, 'end': end, 'url': url, 'filename': file_name, 'headers': headers})
    t.setDaemon(True)
    threads.append(t)
  # 线程开始
  for t in threads:
    time.sleep(0.2)
    t.start()
  # 等待所有线程结束
  print('正在下载……')
  for t in threads:
    t.join()
  endtime = datetime.datetime.now().replace(microsecond=0)
  print('下载完成!用时:%s' % (endtime - starttime))
def Handler(start, end, url, filename, headers={}):
  tt_name = threading.current_thread().getName()
  print(tt_name + ' 已启动')
  r = requests.get(url, headers=headers, stream=True)
  total_size = end - start
  downsize = 0
  startTime = time.time()
  with open(filename, 'r+b') as fp:
    fp.seek(start)
    var = fp.tell()
    for chunk in r.iter_content(204800):
      if chunk:
        fp.write(chunk)
        downsize += len(chunk)
        line = tt_name + '-downloading %d KB/s - %.2f MB, 共 %.2f MB'
        line = line % (
          downsize / 1024 / (time.time() - startTime), downsize / 1024 / 1024,
          total_size / 1024 / 1024)
        print(line, end='\r')
if __name__ == '__main__':
  url = input('输入视频链接(请输入视频原链):')
  thread(url)

这个代码太多了,我就用注释来解释,不单独说明了,如果有不会的就在帖子下面留言,我会的都会帮你解答的。
成品在这里:https://www.52pojie.cn/thread-1203083-1-1.html

免费评分

参与人数 12威望 +1 吾爱币 +20 热心值 +12 收起 理由
yjn866y + 1 + 1 我很赞同!
sam喵喵 + 1 热心回复!
可控核聚变 + 1 + 1 谢谢@Thanks!
听雨长风 + 1 + 1 谢谢@Thanks!
caozhe01 + 1 + 1 谢谢@Thanks!
端木竹 + 1 + 1 谢谢@Thanks!
kyrzy0416 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 1 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hj170520 + 1 + 1 谢谢@Thanks!
dajiaoban99 + 1 + 1 我很赞同!
jshon + 1 + 1 用心讨论,共获提升!
yuze0804007 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

microjun 发表于 2020-6-20 12:35
感谢楼主,楼主辛苦了。看源码发现下载后的命名都是B站视频,所以我做了一下改进,仅改了视频保存的名称,其他核心功能并没有动。新引入了BeautifulSoup库,对视频地址url进行了解析,抽取得到视频的名称name,并进行保存。
[Python] 纯文本查看 复制代码
import re
import json
from multiprocessing import thread
import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36',
}

url = input("请输入视频地址:")
with open('SESSDATA.txt', 'r') as f:
    SESSDATA = f.read()
if SESSDATA == '0':
    print('检测到您未设置SESSDATA,最高只能下载480p画质哦!')

# 获取视频名称
r = requests.get(url)
r.encoding = 'utf-8'
soup = BeautifulSoup(r.text, 'html.parser')
name = soup.title.text.split('_')[0]
print(name)

# 获取BV号
if '?' in url:
    url = url.split('?')[0]
    print(url)
bvid = re.search(r'BV.*', url).group()
print('BV号:' + bvid + "1111")
# 获取cid
cid_json = requests.get('https://api.bilibili.com/x/player/pagelist?bvid={}&jsonp=jsonp'.format(bvid)).text
print(cid_json)
cid = re.search(r'{"cid":(\d+)', cid_json).group()[7:]
print('CID:' + cid)
# 获取视频的av号
rsp = requests.get(url, headers=headers)
aid = re.search(r'"aid":(.*?),"', rsp.text).group()[6:-2]
print('AV号:' + aid)


# 抓取视频真实地址,清晰度
qn = 16  # 先设置一个默认低清晰度
headers['Referer'] = url
api_url = 'https://api.bilibili.com/x/player/playurl?cid={}&avid={}&qn={}&otype=json&requestFrom=bilibili-helper'.format(
    cid, aid, qn)
qn_dict = {}  # 用来存放清晰度选择参数
rsp = requests.get(api_url, headers=headers).content
rsp = json.loads(rsp)
qn_accept_description = rsp.get('data').get('accept_description')
qn_accept_quality = rsp.get('data').get('accept_quality')
print('下载视频清晰度选择')
for i, j, xuhao in zip(qn_accept_description, qn_accept_quality, range(len(qn_accept_quality))):
    print(str(xuhao + 1) + ':' + i)
    qn_dict[str(xuhao + 1)] = j
xuhao = input('请选择(输入清晰度前的标号):')
qn = qn_dict[xuhao]
print('清晰度参数qn:' + str(qn))


api_url = 'https://api.bilibili.com/x/player/playurl?cid={}&avid={}&qn={}&otype=json&requestFrom=bilibili-helper'.format(
    cid, aid, qn)
# print('api_url='+api_url)
cookies = {}
cookies['SESSDATA'] = SESSDATA  # 这里输入你的SESSDATA
rsp = requests.get(api_url, headers=headers, cookies=cookies).content  # 这里代cookies才能得到会员或者登录后才能下载的视频的链接
rsp = json.loads(rsp)
real_url = rsp.get('data').get('durl')[0].get('url')
print('成功获取视频直链!')
print('正在开启多线程极速下载……')
thread(real_url, url, name + '.flv')  # 多线程下载

# 把上面那行删掉,把下面注释去掉就是单线程下载
# content = requests.get(real_url, headers=headers).content
# with open('1.flv', 'wb') as f:
#    f.write(content)
dajiaoban99 发表于 2020-6-18 23:13
jshon 发表于 2020-6-18 21:26
虽然有很好的下载B站视频的工具了,但还是很厉害的,另外就是注意文件的命名,下载的命名都是B站视频,还有就是可以研究下多P下载
Ldfd 发表于 2020-6-18 21:31
楼主为何打包这么小
 楼主| xccxvb 发表于 2020-6-18 21:53
Ldfd 发表于 2020-6-18 21:31
楼主为何打包这么小

其实我还觉得挺大的了
 楼主| xccxvb 发表于 2020-6-18 21:55
jshon 发表于 2020-6-18 21:26
虽然有很好的下载B站视频的工具了,但还是很厉害的,另外就是注意文件的命名,下载的命名都是B站视频{:1_90 ...

好的,谢谢你的建议
Ldfd 发表于 2020-6-18 23:05
xccxvb 发表于 2020-6-18 21:53
其实我还觉得挺大的了

随随便便就10M唉
 楼主| xccxvb 发表于 2020-6-18 23:21
Ldfd 发表于 2020-6-18 23:05
随随便便就10M唉

哈哈毕竟多线程,其实如果宽带够高的话理论上可以30m/s,因为单线程最高是就可以达到3m/s的。
Ldfd 发表于 2020-6-18 23:23
xccxvb 发表于 2020-6-18 23:21
哈哈毕竟多线程,其实如果宽带够高的话理论上可以30m/s,因为单线程最高是就可以达到3m/s的。

emm我说的其实是文件大小
 楼主| xccxvb 发表于 2020-6-18 23:26
Ldfd 发表于 2020-6-18 23:23
emm我说的其实是文件大小

你是打包的虚拟环境有很多包吗?我打包出来只有6.7m的,你可以去看我的成品。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 21:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表