默认情况下,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
这个时候也没有解决问题。
如何一段段的请求数据呢?
流式请求就是像流水一样,不是一次过来而是一点一点“流”过来。处理流式数据也是一点一点处理。
可以使用 Response.iter_lines()
或 Response.iter_content()
iter_content(chunk_size = 1 , decode_unicode = False)
迭代响应数据。这避免了立即将内容读入内存以获得较大的响应。
chunk_size
是它应该读入内存的字节数。chunk_size
的类型必须是int
或None
。None
的值将根据流的值发挥不同的作用。
iter_lines(chunk_size=512, decode_unicode=None, delimiter=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)
当设置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