马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
import os
import time
from concurrent.futures import ThreadPoolExecutor, wait
from requests import get, head
import sys
class Downloader:
def __init__(self, url, nums, file):
self.url = url
self.num = nums
self.name = file
self.getSize = 0
self.info = {
'main' : {
'progress' : 0,
'speed' : ''
},
'sub' : {
'progress' : [0 for i in range(nums)],
'stat' : [1 for i in range(nums)]
}
}
r = head(self.url)
while r.status_code == 302:
self.url = r.headers['Location']
print("该url以重定向至{}".format(self.url))
r = head(self.url)
self.size = int(r.headers['Content-Length'])
print("该文件大小为: {} bytes".format(self.size))
def down(self, start, end, thread_id, chunk_size=10240):
raw_start = start
for _ in range(10):
try:
headers = {'Range' : 'bytes={}-{}'.format(start, end)}
r = get(self.url, headers=headers, timeout=10, stream=True)
print(f"线程{thread_id}链接成功")
size = 0
with open(self.name, 'rb+') as fp:
fp.seek(start)
for chunk in r.iter_content(chunk_size=chunk_size):
if chunk:
self.getSize += chunk_size
fp.write(chunk)
start += chunk_size
size += chunk_size
progress = round(size / (end - raw_start) * 100, 2)
self.info['sub']['progress'][thread_id - 1] = progress
self.info['sub']['stat'][thread_id - 1] = 1
return
except Exception as e:
print(e)
self.down(start, end, thread_id)
print(f"{start}-{end}, 下载失败")
self.info['sub']['stat'][thread_id - 1] = 0
def show(self):
while True:
speed = self.getSize
time.sleep(0.5)
speed = int((self.getSize - speed) * 2 / 1024)
if speed > 1024:
speed = f"{round(speed / 1024, 2)} M/s"
else:
speed = f"{speed} KB/s"
progress = round(self,getsize / self.size * 100, 2)
self.info['main']['progress'] = progress
self.info['main']['speed'] = speed
print(self.info)
if progress >= 100:
break
def run(self):
fp = open(self.name ,'wb')
print(f"正在初始化下载文件: {self.name}")
fp.truncate(self.size)
print("初始化文件完成")
start_time = time.time()
fp.close()
part = self.size // self.num
pool = ThreadPoolExecutor(max_workers=self.num + 1)
futures = []
for i in range(self.num):
start = part * i
if i == self.num - 1:
end = self.size
else:
end = start + part - 1
futures.append(pool.submit(self.show))
printf(f'正在使用{self.num}个线程下载……')
wait(futures)
end_time = time.time()
speed = int(self.size / 1024 / (end_time - start_time))
if speed > 1024:
speed = f"{round(speed / 1024, 2)} M/s"
else:
speed = f"{speed} KB/s"
print(f"{self.name} 下载完成, 平均速度: {speed}")
if __name__ == '__main__':
debug = 1
if debug:
url = 'https://www.bilibili.com/read/cv6032187'
down = Downloader(url, 8, os.path.basename(url))
else:
url = sys.argv[1]
file = sys.argv[2]
thread_num = int(sys.argv[3])
down = Downloader(url, thread_num, file)
down.run()
报错如下:
Traceback (most recent call last):
File "g:\Programming\Python\text.py", line 105, in <module>
down = Downloader(url, 8, os.path.basename(url))
File "g:\Programming\Python\text.py", line 29, in __init__
self.size = int(r.headers['Content-Length'])
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\structures.py", line
54, in __getitem__
return self._store[key.lower()][1]
KeyError: 'content-length'
大佬指导指导@zltzlt @qiuyouzhi |