将包含utf-8编码的字节串和代码点的字符串转换为utf-8编码的字符串

时间:2011-04-30 13:41:49

标签: python unicode encoding utf-8

我从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响应返回错误的代码点,因为'摘录'在此摘录所属的原始源处开始为“......我们将...”。正如您所看到的那样,序列用于表示'-right单引号 - 字符,但该字符的代码点实际上是\ u2019,而编码为utf-8的等效字节字符串是\ xe2 \ x80 \ x99。所以它返回相应的bytestring而不是codepoint。另一个问题是,这个响应包含正确的代码点,就像上一个响应中的\ 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所有者,并通知他们应该使用有效的代码点而不是字节串,但我不确定他们什么时候会联系我,所以我想为当前情况提出一个解决方案。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:7)

您可以使用正则表达式来识别“类似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–...