python - 我应该如何解决这个 utf-8 编码错误?
问题描述
所以,我有像这样的非二进制字符串,它的编码被破坏了:
La funci\xc3\xb3n est\xc3\xa1ndar 日期时间。约会时间。now() retorna la fecha y hora 实际。
该字符串应如下所示:
La función estándar 日期时间。约会时间。now() retorna la fecha y hora 实际。
在交互式控制台中,很容易修复:就像这样:
>>> 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()
在循环中使用 with:
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...
}
这简直让我大吃一惊。难道没有比这更优雅的解决方案了吗?
解决方案
当试图解开具有双重编码序列的字符串时,该字符串旨在成为转义序列(即\\
代替\
),特殊的文本编码编解码器unicode_escape
可用于将它们纠正回预期的实体以进行进一步处理。但是,鉴于输入已经是 类型str
,它需要转换为bytes
- 假设整个字符串具有完全有效的ascii
代码点,这可能是用于将初始str
输入初始转换为 的编解码器bytes
。如果utf8
在 中表示标准 unicode 代码点,则可以使用编解码器str
,因为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
,则此中间字符串可以简单地bytes
使用编解码器后解码进行编码,然后通过(或任何适当的目标)编解码器latin1
将其转换回 unicodestr
类型:utf8
>>> 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.'
根据要求,一个附录来澄清部分混乱的字符串。请注意,由于存在未转义字符,尝试broken_string2
使用编解码器进行ascii
解码将不起作用。á
>>> 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)
推荐阅读
- java - 使用 JNA 在“Internet Explorer_server”中操作 HTML 元素
- knex.js - Knex 使用一组变量进行 SELECT,另一组变量进行 JOIN
- android - Where can I find a specific class in classes.dex?
- javascript - Jasmine 期望 toEqual 但忽略实际对象上的其他属性以防止“期望......没有属性......”
- java - 从 java 库执行 ArchUnit 测试
- java - 将 2 个控制器方法映射到具有不同查询参数的同一端点
- angular - 没有使用 signalR 连接到服务器
- java - 如何在 Android 10 (Android Q) 中访问外部存储?
- c++ - 从方法返回一个类会为类变量提供错误的值
- spring-kafka - 反序列化过程中如何使用ErrorHandlingDeserializer2处理异常