【问题标题】:converting a string which contains both utf-8 encoded bytestrings and codepoints to utf-8 encoded string将包含 utf-8 编码的字节串和代码点的字符串转换为 utf-8 编码的字符串
【发布时间】:2011-08-16 01:46:34
【问题描述】:

我从如下所示的 API 获得 JSON 响应:

{"excerpt":"...where we\u00e2\u0080\u0099ll just have to wait and see, I\u00e2\u0080\u0099m sure official announcements with start flowing in the coming months \u2013special\u2013..."}

这是从 API 调用返回的原始 JSON 响应。现在,正如您所看到的,该 JSON 文档中有一些代码点,这是传输 unicode 数据时应该使用的代码点。但是 API 响应返回了错误的代码点,因为“摘录”在该摘录所属的原始来源处以“... where we'll ...”开头。如您所见,\u00e2\u0080\u0099 序列用于表示 ' -右单引号 - 字符,但该字符的代码点实际上是 \u2019,编码为 utf-8 的等效字节串是 \xe2\x80\x99。所以它返回相应的字节串而不是代码点。另一个问题是此响应包含正确的代码点,如上一个响应中的 \u2013 (破折号字符),它使我的代码无法处理这两种情况。

我最终必须从此响应中获取一些字段(可能使用 json.loads 并将 \u00e2\u0080\u0099 转换为 \xe2\x80\x99 但对 \u2013 没有任何作用),连接这些字段并发送结果到另一个库,该库最终使用 urllib.urlencode 将该结果编码为有效的 utf-8 url 参数,以发送另一个 API。

所以这是我的问题:有没有办法将包含 utf-8 字节串和 unicode 代码点的字符串(这是执行 json.loads 的结果)编码为另一个仅包含代码点或 utf-8 字节串的字符串所以我可以在 urllib.urlencode 中使用它,或者在做 json.loads 之前可能有解决方案? 注意:我使用的是 Python 2.6.1

我已经联系了 API 所有者并告知他们应该使用有效的代码点而不是字节串,但我不确定他们何时会联系我,所以我正在尝试针对当前情况提出解决方案。

任何帮助将不胜感激。

【问题讨论】:

  • 为了澄清,您使用的是 Python 3 吗? (我假设你是,否则 unicode 转义不应出现在返回的字符串中。)无论如何,@Mark Tolonen 的解决方案应该可以通过一些修改来工作。

标签: python unicode encoding utf-8


【解决方案1】:

您可以使用正则表达式来识别“类似 UTF-8”的 Unicode 序列并将它们处理成正确的 Unicode 字符:

import re
D = {"excerpt":"...where we\u00e2\u0080\u0099ll just have to wait and see, I\u00e2\u0080\u0099m sure official announcements with start flowing in the coming months \u2013special\u2013..."}
s = D['excerpt']
print s
s = s.decode('unicode-escape')
print s
print re.sub(ur'[\xc2-\xf4][\x80-\xbf]+',lambda m: m.group(0).encode('latin1').decode('utf8'),s)

输出:

...where we\u00e2\u0080\u0099ll just have to wait and see, I\u00e2\u0080\u0099m sure official announcements with start flowing in the coming months \u2013special\u2013...
...where weâll just have to wait and see, Iâm sure official announcements with start flowing in the coming months –special–...
...where we’ll just have to wait and see, I’m sure official announcements with start flowing in the coming months –special–...

更新...

根据您的评论,字典已经是 Unicode 字符串,因此 \u2013 字符打印正确(请参阅下面的第一个打印输出),因此可以跳过 decode('unicode-escape')re.sub 语句仍然有效:

import re
D = {u'excerpt':u'...where we\xe2\x80\x99ll just have to wait and see, I\xe2\x80\x99m sure official announcements with start flowing in the coming months \u2013special\u2013...'}
s = D[u'excerpt']
print s
print re.sub(ur'[\xc2-\xf4][\x80-\xbf]+',lambda m: m.group(0).encode('latin1').decode('utf8'),s)

输出:

...where weâll just have to wait and see, Iâm sure official announcements with start flowing in the coming months –special–...
...where we’ll just have to wait and see, I’m sure official announcements with start flowing in the coming months –special–...

【讨论】:

  • 跳过 s.decode('unicode-escape') 步骤,如果它已经是一个 Unicode 字符串。它仍然包含“类似 UTF-8”的编码序列。
猜你喜欢
  • 1970-01-01
  • 2016-10-01
  • 2011-08-09
  • 2011-12-08
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2014-06-09
相关资源
最近更新 更多