1.引言

(如果要直接看结果,请直接拉到文章末尾。)

之前写过如何开发微博爬虫的文章(后台回复‘微博爬虫’获取文章),并将微博爬虫开源到了GitHub上(后台回复‘微博代码’获取代码)。

传统的视频图片的下载姿势,如果使用requests包可以简单到下面这样的一句代码:

requests.get(img_url,stream=True).content

上述代码所完成的操作:

(1)打开网络流;

(2)读取返回的内容。

为了突出重点,这里省略了代理(proxies)、Header、以及超时(timeout)的设置。

但这样做不能分辨出假死的情况,尤其是微博这种视频图片居多的网站,很有可能卡在抓取视频图片的过程中一动不动。或者在下载大文件的时候,虽然文件一直在下载,但我们却不知道文件到底下载了多少,还要下载多少时间。

所以在实际爬虫开发过程中,如果能动态的展示视频或图片的下载过程对于监控爬虫运行是非常必要的。

python progressbar下载大文件带进度条 python安装进度条不动_python 获取文件大小

图表 1迅雷下载中的进度条

2.正文

要做到为下载过程添加进度条,首先需要了解requests.get()方法和tqdm包。

2.1 tqdm包

tqdm来自阿拉伯文中taqaddum,意思是‘进度’,也是西班牙语中的tequiero demasiado缩写,意思是‘我非常爱你’。tqdm提供一种简单易用的方式用来显示进度。

2.1.1 安装

使用conda方式:

conda install -c conda-forge tqdm

使用pip方式:

pip install tqdm

2.1.2 使用

tqdm使用起来也非常方便,最简单的用法如下:

from tqdm import tqdm#导入相应的方法for i in tqdm(range(10000)):#tqdm()方法      pass

只需要引入tqdm方法,然后使用将可迭代(iterable)的对象传入tqdm()方法即可。

复杂一点的用法如下:

with tqdm(total=100) as pbar:#tqdm方法设置进度条长度    for i inrange(10):        sleep(0.1)       pbar.update(10)#手动更新进度

相较于简单的用法,复杂一点的方式需要手动的去更新进度。

2.2 requests

2.2.1 get方法

本文获取文件长度通过requests.get()方法。requests.get()方法中stream参数当stream=True的时候,get()方法只下载Header部分,如果要下载Body部分,需要读取content属性视频图片才会下载。所以我们可以利用这一点来完成对视频图片的下载进行动态监控。获取文件大小的方法如下:

response=requests.get(img_url,stream=True)file_size=response.headers['Content-length']

2.2.2 iter_content

  iter_content方法用于分块读取get()方法返回的流,避免因一次性读取消耗大量内存。

for chunk in response.iter_content(chunk_size=1024):  pass

3.为视频图片下载添加进度条

基于以上的分析,可以得出添加进度条的整个步骤如下:

(1)获取Header,使用requests.get()方法;

(2)获取文件大小,使用response的‘Content-length’属性;

(3)初始化tqdm;

(4)分块读取文件并更新进度条,使用iter_content()方法;

(5)关闭进度条,使用close()方法。

完整的代码如下:

import requestsimport tqdmimg_url='http://122.51.50.206:8088/imgs/63943f53ly1gjgojmh9zaj222o0yi7wq.jpg'response=requests.get(img_url,stream=True)file_size=response.headers['Content-length']print(file_size)pbar=tqdm.tqdm(total=int(file_size),unit='B',unit_scale=True,desc=img_url.split('/')[-1])with(open('1.jpg','wb')) as f:    for chunk in response.iter_content(chunk_size=1024):        if  chunk:            f.write(chunk)            pbar.update(1024)pbar.close()