我该如何解决这个 utf-8 编码错误?
How am I supposed to fix this utf-8 encoding error?
所以,我有像这样的非二进制字符串,它的编码被破坏了:
La funci\xc3\xb3n est\xc3\xa1ndar datetime. datetime. now() retorna la fecha y hora actual.
此字符串应如下所示:
La función estándar datetime. datetime. now() retorna la fecha y hora actual.
在交互式控制台中,修复起来很容易:就像这样:
>>> b'La funci\xc3\xb3n est\xc3\xa1ndar datetime. datetime. now() retorna la fecha y hora actual.'.decode('utf-8')
这将输出正确解码的字符串。但是,在我尝试构建的脚本中,这个字符串就像您在第一个示例中看到的那样,但是是 unicode,而不是二进制。
我已经尝试了我能想到的所有技巧(除了硬编码等价字典并将其与 replace()
一起使用,如果可以的话我宁愿不这样做):我最疯狂的事情试过的是:
# Just to clarify the format of the broken strings, I declare this one here
broken_string = 'La funci\xc3\xb3n est\xc3\xa1ndar datetime. datetime. now() retorna la fecha y hora actual.'
match = re.findall(r'\x[a-z0-9][a-z0-9]', broken_string)
for e in match:
broken_string = str(broken_string.encode().replace( e.encode(), str(chr(int(e[-2:], 16))).encode() ))
好吧,实际上这个循环最终把字符串搞得更糟了:-$
这个可怕的火车残骸只是我能向你展示的最疯狂的想法。实际上,我已经尝试了很多东西,以至于我不记得所有的东西。但你可能会在这里看到我的意图。
我似乎无法以一种优雅的方式解决这个问题,而不必硬编码这种风格的字典以便在循环中与 str.replace()
一起使用,这真的很有趣:
dict_for_fix = {
'\xc3\xb3' : b'\xc3\xb3'.decode('utf-8'),
# I mean, I would have to brute-force hardcode lots of combinations this way...
}
这让我大吃一惊。难道没有比这更优雅的解决方案吗?
当试图解开一个具有双重编码序列的字符串时,该字符串旨在作为转义序列(即 \
而不是 \
),可以使用特殊的 text encoding codec unicode_escape
将它们纠正回预期的实体以进行进一步处理。但是,鉴于输入已经是 str
类型,需要将其转换为 bytes
- 假设整个字符串具有完全有效的 ascii
代码点,这可能是用于将初始 str
输入初始转换为 bytes
的编解码器。如果 str
中有标准的 unicode 代码点,则可以使用 utf8
编解码器,因为 unicode_escape
序列不会影响这些代码点。示例:
>>> broken_string = 'La funci\xc3\xb3n est\xc3\xa1ndar datetime.'
>>> broken_string2 = 'La funci\xc3\xb3n estándar datetime.'
>>> broken_string.encode('ascii').decode('unicode_escape')
'La función estándar datetime.'
>>> broken_string2.encode('utf8').decode('unicode_escape')
'La función estándar datetime.'
假设 unicode_escape
编解码器假设解码为 latin1
,这个中间字符串可以简单地使用 latin1
编解码器 post 编码为 bytes
] 解码,然后通过 utf8
(或任何合适的目标)编解码器将其转回 unicode str
类型:
>>> broken_string.encode('ascii').decode('unicode_escape').encode('latin1').decode('utf8')
'La función estándar datetime.'
>>> broken_string2.encode('utf8').decode('unicode_escape').encode('latin1').decode('utf8')
'La función estándar datetime.'
根据要求,一个附录来澄清部分混乱的字符串。请注意,由于存在未转义的 á
字符,因此尝试使用 ascii
编解码器解码 broken_string2
将不起作用。
>>> broken_string2.encode('ascii').decode('unicode_escape').encode('latin1').decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\xe1' in position 21: ordinal not in range(128)
所以,我有像这样的非二进制字符串,它的编码被破坏了:
La funci\xc3\xb3n est\xc3\xa1ndar datetime. datetime. now() retorna la fecha y hora actual.
此字符串应如下所示:
La función estándar datetime. datetime. now() retorna la fecha y hora actual.
在交互式控制台中,修复起来很容易:就像这样:
>>> b'La funci\xc3\xb3n est\xc3\xa1ndar datetime. datetime. now() retorna la fecha y hora actual.'.decode('utf-8')
这将输出正确解码的字符串。但是,在我尝试构建的脚本中,这个字符串就像您在第一个示例中看到的那样,但是是 unicode,而不是二进制。
我已经尝试了我能想到的所有技巧(除了硬编码等价字典并将其与 replace()
一起使用,如果可以的话我宁愿不这样做):我最疯狂的事情试过的是:
# Just to clarify the format of the broken strings, I declare this one here
broken_string = 'La funci\xc3\xb3n est\xc3\xa1ndar datetime. datetime. now() retorna la fecha y hora actual.'
match = re.findall(r'\x[a-z0-9][a-z0-9]', broken_string)
for e in match:
broken_string = str(broken_string.encode().replace( e.encode(), str(chr(int(e[-2:], 16))).encode() ))
好吧,实际上这个循环最终把字符串搞得更糟了:-$
这个可怕的火车残骸只是我能向你展示的最疯狂的想法。实际上,我已经尝试了很多东西,以至于我不记得所有的东西。但你可能会在这里看到我的意图。
我似乎无法以一种优雅的方式解决这个问题,而不必硬编码这种风格的字典以便在循环中与 str.replace()
一起使用,这真的很有趣:
dict_for_fix = {
'\xc3\xb3' : b'\xc3\xb3'.decode('utf-8'),
# I mean, I would have to brute-force hardcode lots of combinations this way...
}
这让我大吃一惊。难道没有比这更优雅的解决方案吗?
当试图解开一个具有双重编码序列的字符串时,该字符串旨在作为转义序列(即 \
而不是 \
),可以使用特殊的 text encoding codec unicode_escape
将它们纠正回预期的实体以进行进一步处理。但是,鉴于输入已经是 str
类型,需要将其转换为 bytes
- 假设整个字符串具有完全有效的 ascii
代码点,这可能是用于将初始 str
输入初始转换为 bytes
的编解码器。如果 str
中有标准的 unicode 代码点,则可以使用 utf8
编解码器,因为 unicode_escape
序列不会影响这些代码点。示例:
>>> broken_string = 'La funci\xc3\xb3n est\xc3\xa1ndar datetime.'
>>> broken_string2 = 'La funci\xc3\xb3n estándar datetime.'
>>> broken_string.encode('ascii').decode('unicode_escape')
'La función estándar datetime.'
>>> broken_string2.encode('utf8').decode('unicode_escape')
'La función estándar datetime.'
假设 unicode_escape
编解码器假设解码为 latin1
,这个中间字符串可以简单地使用 latin1
编解码器 post 编码为 bytes
] 解码,然后通过 utf8
(或任何合适的目标)编解码器将其转回 unicode str
类型:
>>> broken_string.encode('ascii').decode('unicode_escape').encode('latin1').decode('utf8')
'La función estándar datetime.'
>>> broken_string2.encode('utf8').decode('unicode_escape').encode('latin1').decode('utf8')
'La función estándar datetime.'
根据要求,一个附录来澄清部分混乱的字符串。请注意,由于存在未转义的 á
字符,因此尝试使用 ascii
编解码器解码 broken_string2
将不起作用。
>>> broken_string2.encode('ascii').decode('unicode_escape').encode('latin1').decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\xe1' in position 21: ordinal not in range(128)