在 Python 中解码双重编码的 utf8

Posted

技术标签:

【中文标题】在 Python 中解码双重编码的 utf8【英文标题】:Decoding double encoded utf8 in Python 【发布时间】:2010-11-13 17:18:39 【问题描述】:

我从我的一个客户通过 xmlrpc 获得的字符串有问题。他向我发送了编码两次的utf8字符串:(所以当我在python中获取它们时,我有一个必须再解码一次的unicode对象,但显然python不允许这样做。我注意到我的客户但是我需要在他修复它之前先做一个快速的解决方法。

来自 tcp 转储的原始字符串:

<string>Rafa\xc3\x85\xc2\x82</string>

这被转换成:

u'Rafa\xc5\x82'

我们得到的最好的是:

eval(repr(u'Rafa\xc5\x82')[1:]).decode("utf8") 

这导致正确的字符串是:

u'Rafa\u0142' 

然而,这工作很丑陋,不能在生产代码中使用。 如果有人知道如何以更合适的方式解决此问题,请写信。 谢谢, 克里斯

【问题讨论】:

【参考方案1】: >>> s = u'拉法\xc5\x82' >>> s.encode('raw_unicode_escape').decode('utf-8') u'拉法\u0142' >>>

【讨论】:

@partisnn:整洁!我不知道 raw_unicode_escape (显然是 8-) 感谢党派,我也不知道。 愿您的名声超出预期,即使过了这么多年! :) 似乎你没有回答这个问题,你不是从一个双重编码的 utf-8 字符串开始的,它以欧元符号失败:python -c 'import sys; print sys.argv[1].encode("raw_unicode_escape")' $'\xc3\xa2\xc2\x82\xc2\xac' 序数不在范围内(128) @JulienPalard 在 python 2.x 中,您必须手动解码 str 对象以获取 unicode 字符串。 2.x 修复:[etc.]argv[1].decode("utf-8").encode("raw_[etc.]。在 3.x 中,str 已经是 unicode,解释器会自动从系统的默认编码解码它。修复 3.x:print 周围的括号,使用 python3 运行。【参考方案2】:

哟,真有趣!

>>> original = "Rafa\xc3\x85\xc2\x82"
>>> first_decode = original.decode('utf-8')
>>> as_chars = ''.join([chr(ord(x)) for x in first_decode])
>>> result = as_chars.decode('utf-8')
>>> result
u'Rafa\u0142'

所以你进行第一次解码,得到一个 Unicode 字符串,其中每个字符实际上是一个 UTF-8 字节值。您通过每个字符的整数值返回一个真正的 UTF-8 字符串,然后您可以正常解码。

【讨论】:

你没有收到AttributeError: 'str' object has no attribute 'decode'吗?【参考方案3】:
>>> weird = u'Rafa\xc5\x82'
>>> weird.encode('latin1').decode('utf8')
u'Rafa\u0142'
>>>

latin1 只是 Richie'snut'n'bolts method 的缩写。

非常奇怪的是,严重低估的raw_unicode_escape 编解码器在这种情况下给出了与latin1 相同的结果。他们总是给出相同的结果吗?如果是这样,为什么要有这样的编解码器?如果不是,最好确切地知道 OP 的客户端是如何从 'Rafa\xc5\x82' 转换为 u'Rafa\xc5\x82' 然后完全反转该过程 - 否则如果在双重编码之前出现不同的数据,我们可能会陷入困境固定。

【讨论】:

当您的字符串仅包含代码点 0-255 时,它总是相同的。区别在于上面的字符; raw_unicode_escape 将逃避它们,例如。 \u1234,其中 latin1 将抛出 UnicodeEncodeError。 (解码有对称的区别——raw_unicode_escape 解码 \u1234 转义,latin1 没有,但它只是在这里编码。)它们在这里是等价的,但我会坚持使用 latin1,因为这与转义无关,而 latin1 是一种更广泛理解的编码。 谢谢格伦,午夜过后想想反斜杠把我的大脑变成了南瓜:-)

以上是关于在 Python 中解码双重编码的 utf8的主要内容,如果未能解决你的问题,请参考以下文章

Rollo的Python之路Python 编码与解码

编码方式:

关于Dart中字符串编码/解码的困惑

使用 Doctrine 2 强制编码和解码

C#对字符串进行编码解码

解码 Base64 / Quoted Printable 编码的 UTF8 字符串