requests库之文件下载


方法一:

使用 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 指 post 到服务器的数据,该方法返回一个包含两个元素的(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)

方法二:

使用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参数详解:

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

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

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

此时仅有响应头被下载下来了,连接保持打开状态,因此允许我们根据条件获取内容:

if int(r.headers['content-length']) < TOO_LONG:
  content = r.content # 此时开始下载响应体
  ...

解释:

归功于 urllib3,同一会话内的持久连接是完全自动处理的!同一会话内你发出的任何请求都会自动复用恰当的连接。

只有所有的响应体数据被读取完毕连接才会被释放为连接池;以下是释放连接池的两种情况:

  1. 所以当requests请求时设置的参数stream为False时【requests请求时,stream默认为False】,所有的响应体数据被读取完之后立即释放连接池。
  2. 或者当requests请求时设置的参数stream为True时,当访问r.content属性且读取下载响应体数据之后也会立即释放连接池。

当然:如果你在请求中把  stream  设为 True 的时候,且不访问任何方法,那么Requests 无法将连接释放回连接池,除非你消耗了所有的数据,或者调用了  Response.close 。 否则这样会带来连接效率低下的问题。

关于Response.iter_content的详解

Response.iter_content是可迭代对象。

一块一块的遍历要下载的内容【可以理解为一块一块的下载服务器返回的数据量过大的响应体数据】,然后通过对文件流的操作按块逐一写入指定的路径文件中。

在请求中设置stream = True时,可以避免将内容一次性读入内存以获得较大的响应。块大小是它应该循环每次读入内存的字节数【即chunk_size=1024]


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM