猿问

Python - 通过代理读取巨大的在线csv

我有一个huuuuuge csv在线,我不想逐行阅读它,下载它。但此文件位于代理后面。我写了这个代码:


import requests

import pandas as pd

import io


cafile = 'mycert.crt'


proxies = {"http":"http://ipproxy:port", "https":"http://ipproxy:port"}

auth = HttpNtlmAuth('Username','Password')

url = 'http://myurl/ressources.csv'


content = requests.get(url, proxies=proxies, auth=auth, verify=cafile).content

csv_read = pd.read_csv(io.StringIO(content.decode('utf-8')))

pattern = 'mypattern'


for row in csv_read:

    if row[0] == pattern:

        print(row)

        break

上面的这段代码有效,但“content = requests.get(...”行需要很多时间!由于 csv 文件的大小。


所以我的问题是:是否可以通过代理逐行读取在线csv?


以最好的方式,我希望阅读第一行,检查它是否等于我的模式,如果是=中断,如果不是=读取第二行和依此类推。


感谢您的帮助


Qyouu
浏览 133回答 3
3回答

慕的地8271018

您可以传递给 ,以避免立即获取整个结果。在这种情况下,您可以通过 访问伪文件对象,您可以基于此构建CSV阅读器(或者,响应对象具有和方法,但我不知道将其提供给CSV解析器有多容易)。stream=Truerequests.getresponse.rawiter_contentiter_lines然而,虽然stdlib的模块只是生成一系列列表或字典,因此很容易懒惰,但pandas返回一个不懒惰的数据帧,所以你需要指定一些特殊参数,然后你得到每个块的数据帧或它看起来像什么。csv

红糖糍粑

无论如何,该调用将为您提供整个文件。您需要实现自己的HTTP代码,直至套接字级别,以便能够在内容进入时以普通的HTTP Get方法进行处理。requests.get获取部分结果并对下载进行切片的唯一方法是添加HTTP“范围”请求标头,如果服务器提供文件支持。(可以让您设置这些标头)。requests输入请求高级用法:好消息是,请求可以在后台为您做到这一点 - 您可以在调用请求时设置参数,它甚至可以让您逐行迭代内容。请查看该部分的文档。stream=True以下是或多或少在引擎盖下的作用,以便您可以逐行获取内容:requests它将获得重新调整大小的数据块,但肯定不会一次保留一行(想想~80字节与100.000字节),因为否则它需要为每行一个新的HTTP请求,并且每个请求的开销不是微不足道的,即使通过相同的TCP连接进行。无论如何,由于CSV是一种文本格式,在相应地设置范围标题之前,请求或任何其他软件都无法知道行的大小,甚至不知道要读取的“下一个”行的确切大小。因此,要使此功能起作用,必须使用Python代码才能:接受对 CSV 的“新行”的请求(如果有缓冲文本行),则生成下一行,否则,为下一个 100KB 左右的 HTTP 请求将下载的数据连接到上次下载行的其余部分在二进制数据中的最后一个换行符处拆分下载的数据,保存最后一行的其余部分将二进制缓冲区转换为文本,(您必须在多字节编码(如utf-8)中处理多字节字符边界 - 但是在换行符处剪切可能会节省您)生成下一个文本行

婷婷同学_

根据Masklinn的答案,我的代码现在看起来像这样:import requestscafile = 'mycert.crt'proxies = {"http":"http://ipproxy:port", "https":"http://ipproxy:port"}auth = HttpNtlmAuth('Username','Password')url = 'http://myurl/ressources.csv'pattern = 'mypattern'r = requests.get(url, stream=True, proxies=proxies, verify=cafile)if r.encoding is None:    r.encoding = 'ISO-8859-1'for line in r.iter_lines(decode_unicode=True):    if line.split(';')[0] == pattern:        print(line)        break
随时随地看视频慕课网APP

相关分类

Python
我要回答