Python requests 分段下载文件

requests分段下载文件

默认情况下,requests当你进行网络请求后,响应体会立即被下载,当数据过大时会导致内存不足。

这时候可以通过 stream 参数来设置请求数据。

当在请求上设置stream=True时,这避免了立即将内容读入内存以获得较大的响应。推迟下载响应体直到访问 Response.content 属性。

如果stream=False(默认),数据将作为单个块返回。

示例:

url = 'https://www.baidu.com/'
r = requests.get(url, stream=True)

此时仅有 响应头 被下载下来了,连接保持打开状态。直到访问 Response.content

content = r.content

此时才能获取到数据。

注意:

如果你在请求中把 stream 设为 True,Requests 无法将连接释放回连接池,除非你 消耗了所有的数据,或者调用了 Response.close。 这样会带来连接效率低下的问题。如果你发现你在使用 stream=True 的同时还在部分读取请求的 body(或者完全没有读取 body),那么你就应该考虑使用 with 语句发送请求,这样可以保证请求一定会被关闭:

示例:

with requests.get(url, stream=True) as r:
    content = r.content

 

这个时候也没有解决问题。

如何一段段的请求数据呢?

1、流式请求

流式请求就是像流水一样,不是一次过来而是一点一点“流”过来。处理流式数据也是一点一点处理。

可以使用 Response.iter_lines() 或 Response.iter_content()

iter_content(chunk_size = 1 , decode_unicode = False)

迭代响应数据。这避免了立即将内容读入内存以获得较大的响应。chunk_size是它应该读入内存的字节数。chunk_size的类型必须是intNoneNone的值将根据流的值发挥不同的作用。

iter_lines(chunk_size=512decode_unicode=Nonedelimiter=None)

遍历响应数据,一次一行。

这两个都要设置 steam=True 才能使用

import requests
url = 'https://www.baidu.com/'
r = requests.get(url, stream=True)
# iter_lines
# 一行一行的读取数据
for line in r.iter_lines():
    if line:
        decoded_line = line.decode('utf-8')
        print('line:', decoded_line)

 

 

# iter_content,指定每次读取大小
for chunk in r.iter_content(chunk_size=20):
     if chunk:
            decoded_chunk = chunk.decode('utf-8')
            print(decoed_chunk)

 

2、自己设置请求位置

当设置steam=True,没有访问 Response.content时,只是得到了请求头。

在请求头里有一个参数:content-Length,可以获取文件长度。

当有content-Length时,就可以在请求头里设置每次请求位置。这要用到: Range 字段

没有content-Length不能使用

# 设置请求视频开始:start和结束:end的位置
headers = {
    'Range': f'bytes={start}-{end}',
}
r = requests.get(url, headers=headers)

 

参考链接:

https://blog.csdn.net/m0_46652894/article/details/106018558

 

posted @ 2021-07-21 00:38  neozheng  阅读(1979)  评论(0编辑  收藏  举报