【问题标题】:Python requests, CSV, Sha256 and BOMPython 请求、CSV、Sha256 和 BOM
【发布时间】:2014-10-05 13:37:15
【问题描述】:

我正在使用 Requests 和 Python 2.7 为运动员收集一组 CSV。

Requests 说,这些文件由 MSFT Report Server 生成,并以 iso-8859-1 格式通过。

因为我每晚都要处理数千个问题,所以我想对文件进行 sha256 处理,并与之前的运动员哈希值进行比较。如果哈希匹配,我不会费心将文件保存到磁盘。这些文件很小——最大的大约 6K——所以没有分块/流问题。

但是,

sha256 失败了,因为这些文件的 BOM 令人讨厌。我在这里查看了 10 种不同的“解决方案”,但找不到可以通过 decode.encode 提取 BOM 以便我可以执行 sha256 的解决方案。

我可能不得不恢复的一种解决方法是,我可以将文件写入磁盘,然后在那里对其进行 sha256 处理。但这看起来很糟糕。

如果我可以在开始时去除 BOM,我将拥有一个与 sha256 一起使用的进程,从而使我免于处理多余的文件。

认为问题可能是我表面上尝试对什么是文件对象进行字符串操作。但由于对象仍然是一个 u"/... 十六进制流,我认为这些操作可以工作...

以下是详细信息:

>>> r = requests.get('http://66.73.188.164/ReportServer?%2fCPTC%2fWomens1stHalfDetail&Team=&player=17424&rs:Format=CSV')
>>> r.status_code
200
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x18afb70>
>>> r.encoding
'ISO-8859-1'
>>> print r.headers['content-type']
text/plain
>>> r.text[0]
u'\xff'

第一次转换尝试使用指定的编码类型解码失败!

>>> z = r.text
>>> z.decode('iso-8859-1').encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

事实上,z 的“类型”现在与预期不同,可能是因为 sys (mac; utf8)?

>>> type(z)
<type 'unicode'>
>>> z[0]
u'\xff'
>>> z[0:5]
u'\xff\xfem\x00a'

各种解码和编码尝试都失败了;这是许多此类尝试之一。

>>> z.decode('utf-8-sig').encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/encodings/utf_8_sig.py", line 22, in decode
(output, consumed) = codecs.utf_8_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

我确定答案是单线;我只是没看到。非常感谢任何指导。

【问题讨论】:

    标签: python csv python-requests byte-order-mark


    【解决方案1】:

    也许您可以尝试通过仅对文件的其余部分进行编码来获得 sha256 来省略 BOM?如:

    z = r.text[2:]
    z.decode ...
    

    同样的逻辑必须应用于已经存储在磁盘上的文件的哈希值,但这应该不是问题。

    【讨论】:

    • 非常接近 - 你解决了它。更新你的答案说 z = r.text[2:] 因为 BOM 是两个字节,我会给你答案/赞成票,谢谢!见:>>> r.text[0] u'\xff' >>> r.text[1] u'\xfe' >>> r.text[2] u'm'
    • @Todd Curry 我很高兴它有帮助。编辑应用:)
    【解决方案2】:

    你应该只使用r.content,例如,

    r.content.decode('utf8')
    

    或者你也可以覆盖r.encodingdoing

    r.encoding = 'utf8'
    

    然后您就可以放心使用r.text了。

    【讨论】:

    • 希望这行得通。自己试试;如果你看到不同的东西,请告诉我。 >>> r.content.decode('utf-8') Traceback(最近一次调用最后):文件“”,第 1 行,在 文件“/usr/lib/python2.7/encodings/ utf_8.py”,第 16 行,解码返回 codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0xff in position 0: invalid start byte
    • 查看响应,您为什么要尝试将其转换为 UTF8?它看起来像是一组相当随机的字节。此外,r.content[2:].decode('utf8') 不会引发异常,但我也不确定它是否符合您的要求。也就是说,如果您曾经将此代码移植到 Python 3,那么您接受的答案将是 100% 错误的。 r.text 已经是 unicode 并且在 Python 3 上没有 decode 方法。唯一的方法是使用 r.content.
    • 阅读 OP - 我正在尝试摆脱 BOM。从 Latin-1 到 UTF-8 的转换应该解决这个问题,但这是一种方法而不是目标——而且是一种行不通的方法。我在 OP 中说我使用的是 Python 2.7 谢谢。
    • r.content.decode('utf-8-sig') 适用于带有 BOM 的 utf-8。
    • 根据@SerkanYilmaz 的建议,我强制编码为“utf-8-sig”,而 r.json() 对我来说效果很好。
    猜你喜欢
    • 2021-04-12
    • 1970-01-01
    • 2021-07-10
    • 2016-05-24
    • 2013-02-10
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    相关资源
    最近更新 更多