从0到1手把手教你实现一个 Python 多线程下载器(二)

简介: 从0到1手把手教你实现一个 Python 多线程下载器(二)

带进度条的文件下载器

基础知识

获取文件大小 不难知道,要做一个进度条展示下载进度,我们得事先知道文件的大小以及每次写入文件的大小。还是以这个文件链接为例,展示如何获取待下载的文件大小

# 导入requests 库
import requests
# 文件下载直链
url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
# 发起 head 请求,即只会获取响应头部信息
response = requests.head(url, headers=headers)
# 文件大小,以 B 为单位
file_size = response.headers.get('Content-Length')
if file_size is not None:
    file_size = int(file_size)
print('文件大小:', file_size, 'B')

代码运行输出

文件大小: 67765560 B


分块获取响应内容


上面的文件大小为:67765560 B。如果我们一次性下载 67765560 B 这么大的文件的话,进度条的跨度显然太大了,那么做这么一个进度条的意义并不大,所以我们需要考虑通过一个循环,分多次连续地读取响应直到读取完毕。

# 导入requests 库
import requests
# 文件下载直链
url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
# 发起 head 请求,即只会获取响应头部信息
head = requests.head(url, headers=headers)
# 文件大小,以 B 为单位
file_size = head.headers.get('Content-Length')
if file_size is not None:
    file_size = int(file_size)
response = requests.get(url, headers=headers, stream=True)
# 一块文件的大小
chunk_size = 1024
# 记录已经读取的文件大小
read = 0
for chunk in response.iter_content(chunk_size=chunk_size):
    read += chunk_size
    read = min(read, file_size)
    print(f'已读取: {read} 总大小: {file_size}')


部分输出结果

已读取: 1024 总大小: 67765560
已读取: 2048 总大小: 67765560
已读取: 3072 总大小: 67765560
已读取: 4096 总大小: 67765560
已读取: 5120 总大小: 67765560
已读取: 6144 总大小: 67765560
已读取: 7168 总大小: 67765560
已读取: 8192 总大小: 67765560


通过以上操作,我们成功实现分段、连续下载文件。但是输出显然太多了,我们更希望有一个单行的进度条。 这里不得不说到 tqdm 这个进度条库

一个 tqdm 的使用例子

import time
from tqdm import tqdm
total = 100
for _ in tqdm(range(total)):
    time.sleep(0.1)

 

在终端或者jupyter运行上面的代码即可看到下面的动图如果想一次更新指定次数个进度怎么办呢?比如说进度总共是 100 ,每 10 个刷新一次进度

实现代码例子如下

mport time
from tqdm import tqdm
# 总进度
total = 100
# 每次刷新的进度
step = 10
# 总共要刷新的次数
flush_count = total//step
bar = tqdm(total=total)
for _ in range(flush_count):
    time.sleep(0.1)
    bar.update(step)
bar.close()i


以上代码可实现 每 10 个单位刷新一次直进度满 100

下面来给我们的下载器加进度条吧!

# 导入requests 库
import requests
# 导入 tqdm
from tqdm import tqdm
# 文件下载直链
url = 'https://issuecdn.baidupcs.com/issue/netdisk/yunguanjia/BaiduNetdisk_7.2.8.9.exe'
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
file_name = 'BaiduNetdisk_7.2.8.9.exe'
# 发起 head 请求,即只会获取响应头部信息
head = requests.head(url, headers=headers)
# 文件大小,以 B 为单位
file_size = head.headers.get('Content-Length')
if file_size is not None:
    file_size = int(file_size)
response = requests.get(url, headers=headers, stream=True)
# 一块文件的大小
chunk_size = 1024
bar = tqdm(total=file_size, desc=f'下载文件 {file_name}')
with open(file_name, mode='wb') as f:
    # 写入分块文件
    for chunk in response.iter_content(chunk_size=chunk_size):
        f.write(chunk)
        bar.update(chunk_size)
# 关闭进度条
bar.close()


代码运行过程如下


就这样,我们成功实现了一个带进度条的文件下载器! 为了调用方便,我们可以考虑把它封装为函数,这里我直接附上代码了


相关文章
|
25天前
|
数据采集 存储 安全
如何确保Python Queue的线程和进程安全性:使用锁的技巧
本文探讨了在Python爬虫技术中使用锁来保障Queue(队列)的线程和进程安全性。通过分析`queue.Queue`及`multiprocessing.Queue`的基本线程与进程安全特性,文章指出在特定场景下使用锁的重要性。文中还提供了一个综合示例,该示例利用亿牛云爬虫代理服务、多线程技术和锁机制,实现了高效且安全的网页数据采集流程。示例涵盖了代理IP、User-Agent和Cookie的设置,以及如何使用BeautifulSoup解析HTML内容并将其保存为文档。通过这种方式,不仅提高了数据采集效率,还有效避免了并发环境下的数据竞争问题。
如何确保Python Queue的线程和进程安全性:使用锁的技巧
|
12天前
|
API Python
探索Python中的多线程编程
探索Python中的多线程编程
33 5
|
22天前
|
调度 Python
Python 中如何实现多线程?
【8月更文挑战第29天】
40 6
|
25天前
|
API C语言 C++
C调用Python之多线程与traceback打印
C调用Python之多线程与traceback打印
26 2
|
1月前
|
数据采集 Java Python
Python并发编程:多线程(threading模块)
Python是一门强大的编程语言,提供了多种并发编程方式,其中多线程是非常重要的一种。本文将详细介绍Python的threading模块,包括其基本用法、线程同步、线程池等,最后附上一个综合详细的例子并输出运行结果。
|
29天前
|
数据采集 Java Python
Python并发编程:多线程(threading模块)
本文详细介绍了Python的threading模块,包括线程的创建、线程同步、线程池的使用,并通过多个示例展示了如何在实际项目中应用这些技术。通过学习这些内容,您应该能够熟练掌握Python中的多线程编程,提高编写并发程序的能力。 多线程编程可以显著提高程序的并发性能,但也带来了新的挑战和问题。在使用多线程时,需要注意避免死锁、限制共享资源的访问,并尽量使用线程池来管理和控制线程。
|
1月前
|
开发工具 计算机视觉 Python
大恒相机 - Python 多线程拍摄
大恒相机 - Python 多线程拍摄
33 1
|
1月前
|
调度 Python
|
23天前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
27天前
|
安全 Java Python
Python 中的多线程
【8月更文挑战第24天】
16 0