吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11180|回复: 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] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
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, 2025-4-2 00:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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