stream=True 让处理在经代理返回的响应正文尚未完整下载前就开始。对 CSV,把文本行迭代器交给 csv.reader,这样引号内的分隔符和多行记录仍然是 CSV 数据。

以下是一个使用分号的 UTF-8 示例文件:

import csv
import requests

routes = {'https': 'http://proxy.example:8080'}
with requests.get(
    'https://data.example/observations.csv',
    proxies=routes,
    stream=True,
    timeout=(5, 30),
) as response:
    response.raise_for_status()
    response.encoding = 'utf-8'
    lines = (
        line + '\n'
        for line in response.iter_lines(
            chunk_size=65536, decode_unicode=True)
    )
    for record in csv.reader(lines, delimiter=';'):
        if record and record[0] == 'wanted':
            print(record)
            break

应选择文件实际的编码与方言。若要在获准的公共代理线路上下载公开 CSV,HTTP 代理列表可为 routes 的 URL 提供候选。此版本把物理行尾规范化为 LF:iter_lines 去掉它们,生成器再为 CSV 解析器补回换行。当带引号的字段延续到下一物理行时,这一点很关键。

如果工作流需要按字节原样保留内嵌的 CRLF 字符,请改用能保留这些行尾的流式文本包装方案。示例中有意做的规范化适合以记录为单位的处理,此时 LF 就是预期的表示形式。

一次响应,多次读取

该迭代器消费的是同一个 HTTP 响应的分块,不会为每一行发起新请求。HTTP Range 请求是另一套机制,并不能自然地界定 CSV 记录边界。

调用 response.text 或把所有行收集进列表,会把完整内容重新拉回内存。流式处理仍然需要空间容纳传输缓冲区和当前记录,而单条记录本身可能包含很大的字段。

响应上下文在循环退出时关闭正文,提前命中时也一样。读取超时限定的是等待传入数据的时间,而不是大文件传输的总时长。

相关文章