【问题标题】:Python - read huge online csv through proxyPython - 通过代理读取巨大的在线 csv
【发布时间】:2020-06-22 09:18:13
【问题描述】:

我有一个 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?

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

感谢您的帮助

【问题讨论】:

标签: python python-requests


【解决方案1】:

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

然而虽然 stdlib 的 csv 模块只产生一系列列表或字典,因此很容易变得懒惰,但 pandas 返回一个非懒惰的数据帧,所以你需要 specify some special parameters 然后你会得到每个块的数据帧或看起来像的东西。

【讨论】:

  • 像魅力一样工作! 'stream=True' 选项除以 4 请求时间!如果他们需要,我只是在下面为某些用户编写我的代码!谢谢!
【解决方案2】:

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

获得部分结果并分割下载的唯一方法是添加 HTTP "range" request headers,如果服务器提供文件支持的话。 (requests 可以让你设置这些标题)。

输入请求高级用法:

好消息是请求可以在后台为您做到这一点 - 你可以在调用请求时设置stream=True参数,它甚至可以让你逐行迭代内容。 Check the documentation on that part.

这或多或少是 requests 在幕后所做的,以便您可以逐行获取内容:

它将获得合理大小的数据块,但肯定不会一次请求一行(想想约 80 字节与 100.000 字节),因为否则它需要为每行一个新的 HTTP 请求,以及开销每个请求都不是微不足道的,即使是通过同一个 TCP 连接进行的。

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

因此,要使其工作,必须是 Python 代码:

  • 如果有缓冲,则接受对 CSV 的“新行”的请求 文本行,产生下一行,
  • 否则发出 HTTP 请求 接下来的 100KB 左右
  • 将下载的数据连接到 最后下载的行的剩余部分
  • 将下载的数据拆分为 二进制数据中的最后一个换行符,
  • 保存剩余的 最后一行
  • 将您的二进制缓冲区转换为文本,(您必须采取 照顾多字节编码中的多字节字符边界 (如 utf-8)-但在换行符处剪切可能会为您节省)
  • 产生 下一个文本行

【讨论】:

【解决方案3】:

根据 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

【讨论】:

    猜你喜欢
    • 2017-08-11
    • 2016-11-26
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    相关资源
    最近更新 更多