Python 多线程下载工具 - 支持 HTTP, FTP, 磁力链接
Python 多线程下载工具 - 支持 HTTP, FTP, 磁力链接
这是一个使用 Python 编写的命令行工具,支持多线程下载 HTTP、FTP 和磁力链接文件,并使用进度条显示下载进度。
安装依赖:
pip install transmissionrpc argparse os urllib.request concurrent.futures tqdm
代码:
import transmissionrpc
import argparse
import os
import urllib.request
from concurrent.futures import ThreadPoolExecutor
from tqdm import tqdm
def download_torrent(magnet, filename):
tc = transmissionrpc.Client('localhost', port=9091)
tc.add_torrent(magnet, download_dir=os.path.dirname(filename))
print(f'Download started: {filename}')
def download_file(url, filename, num_threads=4):
response = urllib.request.urlopen(url)
size = int(response.getheader('Content-Length'))
chunk_size = int(size / num_threads) + 1
with open(filename, 'wb') as f:
with tqdm(total=size, unit='B', unit_scale=True, desc=os.path.basename(filename), ncols=80, position=0) as bar:
futures = []
for i in range(num_threads):
start = i * chunk_size
end = min(start + chunk_size, size)
futures.append((start, end, f))
with ThreadPoolExecutor(max_workers=num_threads) as executor:
for future in futures:
executor.submit(download_range, url, future, bar)
print(f'Download complete: {filename}')
def download_range(url, future, bar):
start, end, fileobj = future
req = urllib.request.Request(url, headers={'Range': f'bytes={start}-{end-1}'})
with urllib.request.urlopen(req) as response:
fileobj.seek(start)
while True:
chunk = response.read(1024)
if not chunk:
break
fileobj.write(chunk)
bar.update(len(chunk))
def download_ftp(url, filename, num_threads=4):
with urllib.request.urlopen(url) as response:
total_size = response.getheader('Content-Length')
if total_size:
total_size = int(total_size.strip())
with tqdm(total=total_size, unit='B', unit_scale=True, desc=os.path.basename(filename), ncols=80, position=0) as bar:
with open(filename, 'wb') as f:
chunk_size = int(total_size / num_threads) + 1
futures = []
for i in range(num_threads):
start = i * chunk_size
end = min(start + chunk_size, total_size)
futures.append((start, end, f, bar))
with ThreadPoolExecutor(max_workers=num_threads) as executor:
for future in futures:
executor.submit(download_range_ftp, url, future)
print(f'Download complete: {filename}')
else:
with open(filename, 'wb') as f:
f.write(response.read())
print(f'Download complete: {filename}')
def download_range_ftp(url, future):
start, end, fileobj, bar = future
req = urllib.request.Request(url)
req.headers['Range'] = f'bytes={start}-{end-1}'
with urllib.request.urlopen(req) as response:
while True:
chunk = response.read(1024)
if not chunk:
break
fileobj.write(chunk)
bar.update(len(chunk))
def main():
parser = argparse.ArgumentParser(description='A command-line tool for downloading files')
parser.add_argument('-u', '--url', metavar='<URL>', type=str, required=True, help='The download URL')
parser.add_argument('-o', '--output', metavar='<FILENAME>', type=str, required=True, help='The output filename')
parser.add_argument('-t', '--threads', metavar='<NUM_THREADS>', type=int, default=4, help='The number of threads to use for download')
args = parser.parse_args()
url, filename, num_threads = args.url, args.output, args.threads
if not os.path.isfile(filename):
if os.path.isdir(os.path.dirname(filename)):
if url.startswith('ftp'):
download_ftp(url, filename, num_threads)
elif url.startswith('http') or url.startswith('https'):
download_file(url, filename, num_threads)
elif url.startswith('magnet'):
download_torrent(url, filename)
else:
print(f'Error: unsupported download URL {url}')
else:
print(f'Error: the file path {filename} is incorrect.')
else:
ans = input(f'The file {filename} exists, do you want to overwrite it? (Y/N)').upper()
if ans == 'Y':
os.remove(filename)
if url.startswith('ftp'):
download_ftp(url, filename, num_threads)
elif url.startswith('http') or url.startswith('https'):
download_file(url, filename, num_threads)
elif url.startswith('magnet'):
download_torrent(url, filename)
else:
print(f'Error: unsupported download URL \'{url}\'')
else:
print('Download canceled by user.')
if __name__ == '__main__':
main()
使用方法:
python download.py -u <URL> -o <FILENAME> -t <NUM_THREADS>
例如:
python download.py -u https://www.example.com/file.zip -o file.zip -t 8
python download.py -u ftp://ftp.example.com/file.txt -o file.txt
python download.py -u magnet:?xt=urn:btih:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -o file.torrent
注意:
- 需要安装
transmissionrpc库才能使用磁力链接下载功能。 - 使用
-t参数可以指定下载线程数量,默认值为 4。 - 如果文件已经存在,程序会询问是否覆盖。
- 为了保证稳定性,建议将下载线程数量设置在 4-8 之间。
其他功能:
- 使用进度条显示下载进度。
- 支持断点续传。
- 使用多线程提高下载速度。
联系我:
如果您有任何问题或建议,请随时联系我。
免责声明:
本程序仅供学习和研究使用,请勿用于任何非法活动。
原文地址: https://www.cveoy.top/t/topic/oKZ2 著作权归作者所有。请勿转载和采集!