在Python 3中将Unicode序列转换为字符串

时间:2015-11-01 22:59:28

标签: string unicode python-3.4

在Bash CLI中解析HTML响应以使用 Python 3.4 在Kubuntu 15.10上提取数据时,使用print()我得到如下输出:

\u05ea\u05d4 \u05e0\u05e9\u05de\u05e2 \u05de\u05e6\u05d5\u05d9\u05df

如何在我的应用程序中输出实际文本本身?

这是生成字符串的代码:

response = requests.get(url)
messages = json.loads( extract_json(response.text) )

for k,v in messages.items():
    for message in v['foo']['bar']:
        print("\nFoobar: %s" % (message['body'],))

以下是从HTML页面返回JSON的函数:

def extract_json(input_):

    """
    Get the JSON out of a webpage.
    The line of interest looks like this:
    foobar = ["{\"name\":\"dotan\",\"age\":38}"]
    """

    for line in input_.split('\n'):
        if 'foobar' in line:
            return line[line.find('"')+1:-2].replace(r'\"',r'"')

    return None

在Google上搜索问题时,我发现quite a bit information Python 2bobince相关,但是 Python 3 完全改变了字符串的方式,特别是Unicode在Python中处理。

如何在Python 3中将示例字符串(\u05ea)转换为字符(ת)?

附录:

以下是有关message['body']的一些信息:

print(type(message['body']))
# Prints: <class 'str'>

print(message['body'])
# Prints: \u05ea\u05d4 \u05e0\u05e9\u05de\u05e2 \u05de\u05e6\u05d5\u05d9\u05df

print(repr(message['body']))
# Prints: '\\u05ea\u05d4 \\u05e0\\u05e9\\u05de\\u05e2 \\u05de\\u05e6\\u05d5\\u05d9\\u05df'

print(message['body'].encode().decode())
# Prints: \u05ea\u05d4 \u05e0\u05e9\u05de\u05e2 \u05de\u05e6\u05d5\u05d9\u05df

print(message['body'].encode().decode('unicode-escape'))
# Prints: תה נשמע מצוין

请注意,最后一行按预期工作,但它有一些问题:

  • 使用unicode-escape解码字符串文字是错误的,因为Python转义与许多字符的JSON转义不同。 (谢谢你bobince
  • encode()依赖于默认编码,这是一件坏事。(谢谢\ud83d\ude03
  • encode()在某些较新的Unicode字符上失败,例如{{3}},UnicodeEncodeError&#34;代理人不允许&#34;。

1 个答案:

答案 0 :(得分:2)

看来您的输入使用反斜杠作为转义字符,您应该在将文本传递给json之前取消该文本:

>>> foobar = '{\\"body\\": \\"\\\\u05e9\\"}'
>>> import re
>>> json_text = re.sub(r'\\(.)', r'\1', foobar) # unescape
>>> import json
>>> print(json.loads(json_text)['body'])
ש

不要在JSON文本上使用'unicode-escape'编码;它可能产生不同的结果:

>>> import json
>>> json_text = '["\\ud83d\\ude02"]'
>>> json.loads(json_text)
['']
>>> json_text.encode('ascii', 'strict').decode('unicode-escape') #XXX don't do it
'["\ud83d\ude02"]'

'' == '\U0001F602'U+1F602 (FACE WITH TEARS OF JOY)