【问题标题】:In what world would \\u00c3\\u00a9 become é?\\u00c3\\u00a9 在什么世界会变成é?
【发布时间】:2014-12-24 05:04:15
【问题描述】:

我有一个可能来自我无法控制的来源的编码不正确的 json 文档,其中包含以下字符串:

d\u00c3\u00a9cor

business\u00e2\u20ac\u2122 active accounts 

the \u00e2\u20ac\u0153Made in the USA\u00e2\u20ac\u009d label

据此,我收集到他们打算将 \u00c3\u00a9 转换为 é,即 utf-8 hex C3 A9。这有点道理。对于其他人,我假设我们正在处理某些类型的方向引号。

我的理论是,这要么使用了我以前从未遇到过的某种编码,要么以某种方式进行了双重编码。我很好地编写了一些代码来将他们损坏的输入转换为我能理解的东西,因为如果我引起他们的注意,他们不太可能修复系统。

有什么想法可以强制他们输入我能理解的内容吗?作为记录,我正在使用 Python。

【问题讨论】:

  • 看起来像 unicode ...
  • @JoranBeasley:它们是 JSON unicode 转义,是的,但是对于无效的代码点。
  • 这 3 个是单独的字符串吗?你知道制作这些的平台吗?
  • 是的,我现在看到了......这看起来像是一路上的错误编码
  • 我对用于生成它的代码平台一无所知——但使用它们并不愉快。

标签: python encoding utf-8 mojibake


【解决方案1】:

你应该试试ftfy 模块:

>>> print ftfy.ftfy(u"d\u00c3\u00a9cor")
décor
>>> print ftfy.ftfy(u"business\u00e2\u20ac\u2122 active accounts")
business' active accounts
>>> print ftfy.ftfy(u"the \u00e2\u20ac\u0153Made in the USA\u00e2\u20ac\u009d label")
the "Made in the USA" label
>>> print ftfy.ftfy(u"the \u00e2\u20ac\u0153Made in the USA\u00e2\u20ac\u009d label", uncurl_quotes=False)
the “Made in the USA” label

【讨论】:

  • “你看,我突然想到,有时候一个具有读心能力的女孩可能会在我们的工作中派上用场……”- Malcolm Reynolds
【解决方案2】:

你在这里有Mojibake data;使用错误编解码器从字节解码的 UTF-8 数据。

诀窍是在生成 JSON 输出之前找出 用于解码的编码。如果您假设编码是 Windows 代码页 1252,则可以修复前两个示例:

>>> sample = u'''\
... d\u00c3\u00a9cor
... business\u00e2\u20ac\u2122 active accounts 
... the \u00e2\u20ac\u0153Made in the USA\u00e2\u20ac\u009d label
... '''.splitlines()
>>> print sample[0].encode('cp1252').decode('utf8')
décor
>>> print sample[1].encode('cp1252').decode('utf8')
business’ active accounts 

但是这个编解码器在第 3 次失败:

>>> print sample[2].encode('cp1252').decode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/cp1252.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_table)
UnicodeEncodeError: 'charmap' codec can't encode character u'\x9d' in position 24: character maps to <undefined>

前 3 个“奇怪”字节肯定是 U+201C LEFT DOUBLE QUOTATION MARK 代码点的 CP1252 Mojibake:

>>> sample[2]
u'the \xe2\u20ac\u0153Made in the USA\xe2\u20ac\x9d label'
>>> sample[2][:22].encode('cp1252').decode('utf8')
u'the \u201cMade in the USA'

所以另一个组合可能是U+201D RIGHT DOUBLE QUOTATION MARK,但后一个字符会导致 CP1252 中通常不存在的 UTF-8 字节:

>>> u'\u201d'.encode('utf8').decode('cp1252')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/cp1252.py", line 15, in decode
    return codecs.charmap_decode(input,errors,decoding_table)
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 2: character maps to <undefined>

这是因为 CP1252 编解码器中没有 16 进制 9D 位置,但是代码点 确实 进入了 JSON 输出:

>>> sample[2][22:]
u'\xe2\u20ac\x9d label'

ftfy library Ned Batchelder 非常有帮助地提醒我使用“草率”的 CP1252 编解码器来解决该问题,将不存在的字节一对一映射(UTF-8 字节到 Latin-1 Unicode 点)。生成的“花式引号”然后由库映射到 ASCII 引号,但您可以将其关闭:

>>> import ftfy
>>> ftfy.fix_text(sample[2])
u'the "Made in the USA" label'
>>> ftfy.fix_text(sample[2], uncurl_quotes=False)
u'the \u201cMade in the USA\u201d label'

由于此库为您自动执行此任务,并且比标准 Python 编解码器在此处为您完成的工作做得更好,您应该安装它,并将其应用到这个 API 交给您的混乱中。但是,如果您有一半的机会,请不要犹豫地斥责将这些数据交给您的人。他们制作了一个可爱的混蛋。

【讨论】:

  • 第三个好像cp936,但是python的编解码器好像不支持€。
  • @IgnacioVazquez-Abrams:不,它是 CP1252,强制通过未知字节。
  • 据我所知,这种方式是有意与其他地方的一些旧的凌乱巨人进行互操作的。
猜你喜欢
  • 2015-05-28
  • 2011-08-07
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多