Eti*_*rot 33 python unicode utf-8 character-encoding
在Python 2中,Unicode字符串可能包含unicode和bytes:
a = u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \xd0\xb5\xd0\xba'
Run Code Online (Sandbox Code Playgroud)
我知道这绝对不是应该在他自己的代码中编写的东西,但这是我必须处理的字符串.
上面字符串中的字节是UTF-8 ??(Unicode \u0435\u043a).
我的目标是获得一个包含Unicode中所有内容的unicode字符串,也就是说??????? ??(\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \u0435\u043a).
将其编码为UTF-8会产生
>>> a.encode('utf-8')
'\xd0\xa0\xd1\x83\xd1\x81\xd1\x81\xd0\xba\xd0\xb8\xd0\xb9 \xc3\x90\xc2\xb5\xc3\x90\xc2\xba'
Run Code Online (Sandbox Code Playgroud)
然后从UTF-8解码后给出了包含字节的初始字符串,这不好:
>>> a.encode('utf-8').decode('utf-8')
u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \xd0\xb5\xd0\xba'
Run Code Online (Sandbox Code Playgroud)
然而,我发现了解决问题的一种黑客方法:
>>> repr(a)
"u'\\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439 \\xd0\\xb5\\xd0\\xba'"
>>> eval(repr(a)[1:])
'\\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439 \xd0\xb5\xd0\xba'
>>> s = eval(repr(a)[1:]).decode('utf8')
>>> s
u'\\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439 \u0435\u043a'
# Almost there, the bytes are proper now but the former real-unicode characters
# are now escaped with \u's; need to un-escape them.
>>> import re
>>> re.sub(u'\\\\u([a-f\\d]+)', lambda x : unichr(int(x.group(1), 16)), s)
u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \u0435\u043a' # Success!
Run Code Online (Sandbox Code Playgroud)
这很好但看起来非常hacky,因为它使用了eval,repr然后是unicode字符串表示的附加正则表达式.有更干净的方式吗?
Kar*_*tel 22
在Python 2中,Unicode字符串可能包含unicode和bytes:
不,他们可能不会.它们包含Unicode字符.
在原始字符串中,\xd0不是UTF-8编码的一部分.它是带有代码点208的Unicode字符.u'\xd0'== u'\u00d0'.碰巧的是,repr对于在Python 2 Unicode字符串更喜欢与表示字符\x逃逸在可能(即码点<256).
没有办法查看字符串并告诉该\xd0字节应该是某些UTF-8编码字符的一部分,或者它实际上代表该Unicode字符本身.
但是,如果您假设您始终可以将这些值解释为编码值,则可以尝试编写依次分析每个字符的内容(用于ord转换为代码点整数),将字符<256解码为UTF-8,并传递字符> = 256原样.
geo*_*org 12
(响应上面的评论):此代码转换看起来像utf8的所有内容并保留其他代码点:
a = u'\u0420\u0443\u0441 utf:\xd0\xb5\xd0\xba bytes:bl\xe4\xe4'
def convert(s):
try:
return s.group(0).encode('latin1').decode('utf8')
except:
return s.group(0)
import re
a = re.sub(r'[\x80-\xFF]+', convert, a)
print a.encode('utf8')
Run Code Online (Sandbox Code Playgroud)
结果:
??? utf:?? bytes:blää
Run Code Online (Sandbox Code Playgroud)
bee*_*jay 11
问题是您的字符串实际上并未以特定编码进行编码.你的示例字符串:
a = u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \xd0\xb5\xd0\xba'
Run Code Online (Sandbox Code Playgroud)
将python的unicode字符串的内部表示与utf-8编码文本混合.如果我们只考虑'特殊'字符:
>>> orig = u'\u0435\u043a'
>>> bytes = u'\xd0\xb5\xd0\xba'
>>> print orig
??
>>> print bytes
ек
Run Code Online (Sandbox Code Playgroud)
但是你说,bytes是utf-8编码:
>>> print bytes.encode('utf-8')
ек
>>> print bytes.encode('utf-8').decode('utf-8')
ек
Run Code Online (Sandbox Code Playgroud)
错误!但是关于:
>>> bytes = '\xd0\xb5\xd0\xba'
>>> print bytes
??
>>> print bytes.decode('utf-8')
??
Run Code Online (Sandbox Code Playgroud)
欢呼.
所以.这对我意味着什么?这意味着你(可能)解决了错误的问题.您应该问我们/试图弄清楚为什么你的字符串是以这种形式开始的,以及如何避免它/修复它之前你把它们全部混淆了.
您应该将unichrs 转换为chrs,然后解码它们.
u'\xd0' == u'\u00d0' 是 True
$ python
>>> import re
>>> a = u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \xd0\xb5\xd0\xba'
>>> re.sub(r'[\000-\377]*', lambda m:''.join([chr(ord(i)) for i in m.group(0)]).decode('utf8'), a)
u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \u0435\u043a'
Run Code Online (Sandbox Code Playgroud)
r'[\000-\377]*' 将匹配unichrs u'[\u0000-\u00ff]*' u'\xd0\xb5\xd0\xba' == u'\u00d0\u00b5\u00d0\u00ba'utf8编码字节作为unicode代码点(这是问题)如果我错了,请告诉我.
你已经得到了答案,但是这里有一种方法来解读类似 UTF-8的Unicode序列,这种序列不太可能错误地解码latin-1 Unicode序列.该re.sub函数:
请注意,如果只是正确的字符彼此相邻,这仍然可以匹配Unicode序列,但它不太可能.
import re
# your example
a = u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 \xd0\xb5\xd0\xba'
# printable Unicode characters < 256.
a += ''.join(chr(n) for n in range(32,256)).decode('latin1')
# a few UTF-8 characters decoded as latin1.
a += ''.join(unichr(n) for n in [2**7-1,2**7,2**11-1,2**11]).encode('utf8').decode('latin1')
# Some non-BMP characters
a += u'\U00010000\U0010FFFF'.encode('utf8').decode('latin1')
print repr(a)
# Unicode codepoint sequences that resemble UTF-8 sequences.
p = re.compile(ur'''(?x)
\xF0[\x90-\xBF][\x80-\xBF]{2} | # Valid 4-byte sequences
[\xF1-\xF3][\x80-\xBF]{3} |
\xF4[\x80-\x8F][\x80-\xBF]{2} |
\xE0[\xA0-\xBF][\x80-\xBF] | # Valid 3-byte sequences
[\xE1-\xEC][\x80-\xBF]{2} |
\xED[\x80-\x9F][\x80-\xBF] |
[\xEE-\xEF][\x80-\xBF]{2} |
[\xC2-\xDF][\x80-\xBF] # Valid 2-byte sequences
''')
def replace(m):
return m.group(0).encode('latin1').decode('utf8')
print
print repr(p.sub(replace,a))
Run Code Online (Sandbox Code Playgroud)
的u '\ u0420\u0443\u0441\u0441\u043a\u0438\u0439 \ XD0\XB5\XD0\XBA "#$%&\!'()*+, -/0123456789:;?<=> @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [ \] ^ _`ABCDEFGHIJKLMNOPQRSTUVWXYZ {|}〜\ 0x7F部分\ X80\X81\X82\X83\X84\X85\86 \的x87\X88\X89\x8a\x8b\x8c\x8d\x8e\X8F\X90\X91\X92\X93\X94\X95\X96\X97\X98\X99\x9a\x9b\x9c\x9d\x9e\x9f\XA0\XA1\XA2\XA3\XA4\xa5\xa6\XA7\xa8版权所有\ xA9 \的Xaa\XAB\XAC\XAD\XAE\XAF\XB0\XB1\XB2\XB3\XB4\XB5\XB6\XB7\XB8\xb9\XBA\XBB\XBC\XBD\XBE\XBF\XC0\XC1\XC2\XC3\XC4\XC5\XC6\xc7\xc8\xc9\XCA\XCB\XCC\XCD\XCE\XCF\XD0\XD1\XD2\XD3\XD4\XD5\XD6\XD7\XD8\xd9\XDA\XDB\XDC\XDD\XDE\XDF\xe0\XE1\XE2\XE3\XE4\xe5\XE6\XE7\xe8\xe9\XEA\XEB\XEC \固定的\ XEE\XEF\XF0\XF1\XF2\XF3\XF4\XF5\XF6\XF7\XF8\xf9\XFA\XFB\XFC\XFD\XFE\XFF\0x7F部分\ XC2\X80\XDF\XBF\xe0\XA0\X80\XF0\X90\X80\X80\XF4\X8F\XBF\XBF "
的u '\ u0420\u0443\u0441\u0441\u043a\u0438\u0439 \ u0435\u043a "#$%&\!'()*+, -/0123456789:;?<=> @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\] ^ _ `ABCDEFGHIJKLMNOPQRSTUVWXYZ {|}〜\ 0x7F部分\ X80\X81\X82\X83\X84\X85\86 \的x87\X88\X89\x8a\x8b\x8c\x8d\x8e\X8F\X90\X91\X92\X93\X94\X95\X96\X97\X98\X99\x9a\x9b\x9c\x9d\x9e\x9f\XA0\XA1\XA2\XA3\XA4\xa5\xa6\XA7\xa8版权所有\ xA9 \的Xaa\XAB\XAC\XAD\XAE\XAF\XB0\XB1\XB2\XB3\XB4\XB5\XB6\XB7\XB8\xb9\XBA\XBB\XBC\XBD\XBE\XBF\XC0\XC1\XC2\XC3\XC4\XC5\XC6\xc7\xc8\xc9\XCA\XCB\XCC\XCD\XCE\XCF\XD0\XD1\XD2\XD3\XD4\XD5\XD6\XD7\XD8\xd9\XDA\XDB\XDC\XDD\XDE\XDF\xe0\XE1\XE2\XE3\XE4\xe5\XE6\XE7\xe8\xe9\XEA\XEB\XEC \固定的\ XEE\XEF\XF0\XF1\XF2\XF3\XF4\XF5\XF6\XF7\XF8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x7f \ x80\u07ff\u0800\U00010000\U0010ffff '
| 归档时间: |
|
| 查看次数: |
53287 次 |
| 最近记录: |