|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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 |
|