为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Qyouu 2022-08-25 16:32:21
我有一个huuuuuge csv在线,我不想逐行阅读它,下载它。但此文件位于代理后面。我写了这个代码:import requestsimport pandas as pdimport iocafile = '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).contentcsv_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?以最好的方式,我希望阅读第一行,检查它是否等于我的模式,如果是=中断,如果不是=读取第二行和依此类推。感谢您的帮助
查看完整描述

3 回答

?
慕的地8271018

TA贡献1796条经验 获得超4个赞

您可以传递给 ,以避免立即获取整个结果。在这种情况下,您可以通过 访问伪文件对象,您可以基于此构建CSV阅读器(或者,响应对象具有和方法,但我不知道将其提供给CSV解析器有多容易)。stream=Truerequests.getresponse.rawiter_contentiter_lines

然而,虽然stdlib的模块只是生成一系列列表或字典,因此很容易懒惰,但pandas返回一个不懒惰的数据帧,所以你需要指定一些特殊参数,然后你得到每个块的数据帧或它看起来像什么。csv


查看完整回答
反对 回复 2022-08-25
?
红糖糍粑

TA贡献1815条经验 获得超6个赞

无论如何,该调用将为您提供整个文件。您需要实现自己的HTTP代码,直至套接字级别,以便能够在内容进入时以普通的HTTP Get方法进行处理。requests.get

获取部分结果并对下载进行切片的唯一方法是添加HTTP“范围”请求标头,如果服务器提供文件支持。(可以让您设置这些标头)。requests

输入请求高级用法:

好消息是,请求可以在后台为您做到这一点 - 您可以在调用请求时设置参数,它甚至可以让您逐行迭代内容。请查看该部分的文档stream=True

以下是或多或少在引擎盖下的作用,以便您可以逐行获取内容:requests

它将获得重新调整大小的数据块,但肯定不会一次保留一行(想想~80字节与100.000字节),因为否则它需要为每行一个新的HTTP请求,并且每个请求的开销不是微不足道的,即使通过相同的TCP连接进行。

无论如何,由于CSV是一种文本格式,在相应地设置范围标题之前,请求或任何其他软件都无法知道行的大小,甚至不知道要读取的“下一个”行的确切大小。

因此,要使此功能起作用,必须使用Python代码才能:

  • 接受对 CSV 的“新行”的请求(如果有缓冲文本行),则生成下一行,

  • 否则,为下一个 100KB 左右的 HTTP 请求

  • 将下载的数据连接到上次下载行的其余部分

  • 在二进制数据中的最后一个换行符处拆分下载的数据,

  • 保存最后一行的其余部分

  • 将二进制缓冲区转换为文本,(您必须在多字节编码(如utf-8)中处理多字节字符边界 - 但是在换行符处剪切可能会节省您)

  • 生成下一个文本行


查看完整回答
反对 回复 2022-08-25
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

根据Masklinn的答案,我的代码现在看起来像这样:


import requests


cafile = '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


查看完整回答
反对 回复 2022-08-25
  • 3 回答
  • 0 关注
  • 132 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信