requests请求库之文件下载

您所在的位置:网站首页 秦plus模式转换 requests请求库之文件下载

requests请求库之文件下载

#requests请求库之文件下载| 来源: 网络整理| 查看: 265

前言: 1、普通下载

①对于非文本请求,我们可以通过 Response 对象的 content 属性以字节的方式访问请求响应体。

【注意】这种模式只能下载小文件。因为在这种模式下,从服务器接收到的数据是一直储存在内存中,只有当 write 时才写入硬盘,如果文件很大,那么所占用的内存也是很大的。

②下面将一张网络上的图片下载到本地并保存(文件名不变):

复制代码 import requests url = 'http://www.hangge.com/blog/images/logo.png' response = requests.get(url) # 此时在内存为response响应对象开辟空间,从服务器返回的数据也是一直存储在内存中中 with open("logo.png", "wb") as code: code.write(response.content) # 调用write方法时将内存中的二进制数据写入硬盘 复制代码

代码运行后可以看到图片已经成功下载下来。

2、流式下载:详细见下面的方法二

下面代码我们改成流式下载,即边下载边保存。这种方式适合用来下载大文件。

复制代码 import requests url = 'http://www.hangge.com/blog/images/logo.png' r = requests.get(url, stream=True) with open("logo.png", "wb") as f: for bl in r.iter_content(chunk_size=1024): if bl: f.write(bl) 复制代码 3、带进度的文件下载

①如果文件体积很大,下载时我们最好能实时显示当前的下载进度。

为方便使用应该封装一个下载方法(内部同样使用流式下载的方式)

复制代码 import requests from contextlib import closing # 文件下载器 def down_load(file_url, file_path): with closing(requests.get(file_url, stream=True)) as response: chunk_size = 1024 # 单次请求最大值 content_size = int(response.headers['content-length']) # 内容体总大小 data_count = 0 with open(file_path, "wb") as file: for data in response.iter_content(chunk_size=chunk_size): file.write(data) data_count = data_count + len(data) now_jd = (data_count / content_size) * 100 print("\r 文件下载进度:%d%%(%d/%d) - %s" % (now_jd, data_count, content_size, file_path), end=" ") if __name__ == '__main__': fileUrl = 'http://www.hangge.com/hangge.zip' # 文件链接 filePath = "logo.zip" # 文件路径 down_load(fileUrl, filePath) 复制代码

运行效果如下,可以看到在文件下载的过程会实时显示当前的进度:

4、带下载速度显示的文件下载

对上面的方法做个改进,增加实时下载速度的计算和显示:

复制代码 import requests import time from contextlib import closing # 文件下载器 def down_load(file_url, file_path): start_time = time.time() # 文件开始下载时的时间 with closing(requests.get(file_url, stream=True)) as response: chunk_size = 1024 # 单次请求最大值 content_size = int(response.headers['content-length']) # 内容体总大小 data_count = 0 with open(file_path, "wb") as file: for data in response.iter_content(chunk_size=chunk_size): file.write(data) data_count = data_count + len(data) now_jd = (data_count / content_size) * 100 speed = data_count / 1024 / (time.time() - start_time) print("\r 文件下载进度:%d%%(%d/%d) 文件下载速度:%dKB/s - %s" % (now_jd, data_count, content_size, speed, file_path), end=" ") if __name__ == '__main__': fileUrl = 'http://www.hangge.com/hangge.zip' # 文件链接 filePath = "hangge.zip" # 文件路径 down_load(fileUrl, filePath) 复制代码 方法一:

使用python的内置 urllib 模块提供的 urlretrieve() 函数。

urlretrieve() 方法直接将远程数据下载到本地。

urlretrieve(url, [filename=None, [reporthook=None, [data=None]]]) 请求url不可为空: urlretrieve(url)  下载后的文件保存路径可为空: urlretrieve(url, [filename=None])  传输到服务器的数据data可为空: urlretrieve(url, [filename=None, [reporthook=None, [data=None]]]) 

解释说明:

参数  finename 指定了保存本地路径(如果参数未指定,urllib库 将会生成一个临时文件用以保存数据。)

参数  reporthook 是一个回调函数,当连接上服务器、以及相应的数据块传输完毕时会触发该回调,我们可以利用这个回调函数来显示当前的下载进度。

参数  data 是请求数据,该方法返回一个包含两个元素的 (filename, headers) 元组, filename  表示保存到本地的路径, header 表示服务器的响应头。 

实例:

复制代码 from urllib import request load_url = 'http://docs.python-requests.org/zh_CN/latest/_static/requests-sidebar.png' def Schedule(a,b,c): ''' a:已经下载的数据块 b:数据块的大小 c:远程文件的大小 ''' per = 100.0 * a * b / c if per > 100 : per = 100 print('%.2f%%' % per) request.urlretrieve(url=load_url,filename='d:\\python.png',reporthook=Schedule) 复制代码 方法二:

使用python第三方requests库。

使用该方法下载大文件可以防止占用过多的内存,因为每次只下载小部分数据。

复制代码 import requests load_url = 'http://docs.python-requests.org/zh_CN/latest/_static/requests-sidebar.png' r = requests.get(url=load_url, stream=True) with open("D:\\python.png","wb") as f: for chunk in r.iter_content(chunk_size=1024): f.write(chunk) 复制代码

 stream 参数默认为False,它会立即开始下载文件并放到内存中,如果文件过大,有可能导致内存不足。

 stream 参数设置成True时,它不会立即开始下载,当你使用 iter_content 或 iter_lines 遍历二进制响应内容或访问内容属性时才开始下载。

 iter_content :一块一块的遍历要下载的内容

 iter_lines :一行一行的遍历要下载的内容

关于requests请求时的stream参数详解:

默认情况下,进行网络请求后,接口响应体会立即被下载。(当响应体数据量过大时,立即下载会占用系统大量内存)【当响应体数据量并不是很大时,可以不用考虑内存,即可以直接使用 response.content 下载】

可以通过 stream 参数覆盖该行为,推迟下载响应体直到访问 Response.content 属性:(请求后不立即下载响应体,而是先下载响应头)【当访问 resonse.content 字节码内容的时候才会下载响应体】

import requests tarball_url = 'https://github.com/kennethreitz/requests/tarball/master' r = requests.get(tarball_url, stream=True)

注意,此时仅有响应头被下载下来了,连接保持打开状态,因此允许我们可以根据某些限制条件获取接口响应二进制内容:

if int(r.headers['content-length'])


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3