嵌入了literal \ xhh的字节转义为unicode

时间:2018-04-16 19:52:27

标签: python unicode escaping

我有:b'{"street":"Grossk\\xc3\\xb6lnstra\\xc3\\x9fe"}'

我需要:'{"street": "Grosskölnstraße"}'

我试过了:

s.decode('utf8'): # '{"street":"Grossk\\xc3\\xb6lnstra\\xc3\\x9fe"}'
s.decode('unicode_escape'): # '{"street":"GrosskölnstraÃ\x9fe"}'

正确的方法是什么?

1 个答案:

答案 0 :(得分:6)

那是......你在那里很乱。这看起来像嵌入Python字节转义序列的UTF-8字节。

没有编解码器会再次产生字节作为输出;你需要使用unicode_escape序列然后重新编码为Latin-1以返回UTF8字节,然后解码为UTF-8:

s.decode('unicode_escape').encode('latin1').decode('utf8')

演示:

>>> s = b'{"street":"Grossk\\xc3\\xb6lnstra\\xc3\\x9fe"}'
>>> s.decode('unicode_escape').encode('latin1').decode('utf8')
'{"street":"Grosskölnstraße"}'

另一种选择是仅在正则表达式中定位\x[hexdigits]{3}模式;如果特定数据不是由错误的Python脚本生成的,那么这可能是更强大的选项:

import re
from functools import partial

escape = re.compile(rb'\\x([\da-f]{2})')
repair = partial(escape.sub, lambda m: bytes.fromhex(m.group(1).decode()))

repair()会返回bytes个对象:

>>> repair(s)
b'{"street":"Grossk\xc3\xb6lnstra\xc3\x9fe"}'
>>> repair(s).decode('utf8')
'{"street":"Grosskölnstraße"}'