【问题标题】:How to fix incorrectly UTF-8 decoded string?如何修复错误的 UTF-8 解码字符串?
【发布时间】:2019-11-04 09:12:56
【问题描述】:

我正在使用来自 RESTful API 的数据,它会返回字符串和整数值。但是,它似乎返回了一些错误编码/解码的字符串值(可能)。

预期的字符串:

criança

收到的字符串:

criança

这是我的代码:

url = "https://analytics.us.algolia.com/2/searches?index={index}&startDate={yesterday}".format(index=index, yesterday=yesterday)
headers = { 'X-Algolia-Application-Id': app_id,
            'X-Algolia-API-Key': app_key,
            'Content-Type': 'application/json; charset=utf-8'}

response = requests.get(url, headers=headers)
response_json = json.loads(response.text)

print(response_json)

这是一个 Python 3.6.x 脚本,该脚本将从 Algolia 的 RESTful API 获取数据并将其存储在 Amazon Redshift 中。我在 Ubuntu 18.04 上编写这个脚本,我的终端字符编码集是 pt_BR.UTF-8 (echo $LANG) 和 UTF-8 (locale charmap)。

当我在将其存储到数据库之前打印接收到的数据时,我发现接收到的数据是错误的——数据库设置为使用charset=utf8。我也可以通过SELECT 语句在数据库中看到这个错误的数据。

我发现了这个UTF-8 Encoding Debugging Chart,它指出可能是因为 UTF-8 字节被解释为 Windows-1252(或 ISO 8859-1)字节。

如何使用一些 Python 函数/lib 来处理它?

【问题讨论】:

  • 这意味着响应被视为 ASCII 而不是 UTF8。这不是编码的问题。您现在阅读的页面是 UTF8,但是,如果您检查源代码,您会发现不涉及任何编码。请发布您的代码。很可能那里有一个尝试“解码”或将该字符串转换为其他内容的调用,从而导致问题
  • 另一种可能性是字符串是正确的,但您检查的方式却不是。如果您的终端或控制台未设置为 UTF8,则 UTF8 字节将显示为 ASCII 字符,而表示 ç 的两个字节将显示为 ç。如果您将数据保存到文件中,您可能会将其读取为 ASCII 而不是 UTF8
  • @PanagiotisKanavos,感谢您的支持。我检查了我的终端字符编码,它设置为 UTF-8。我应该明确做任何设置来使 Python 与 UTF-8 一起工作吗?
  • 没什么。它不需要任何东西。发布您的代码。 it 以某种方式将响应视为 ASCII 而不是 UTF8。或者可能是响应在Content-Type 标头中包含错误的charset。当您尝试检索 this 页面时会发生什么?
  • @GabrielAtaide Content-Type 仅允许在 PUT/POST 请求中使用。在 GET 中,它只能显示为 response 标头。使用 Accept-Charset 请求 UTF8 响应。我怀疑你调用的 HTTP 服务默认为 Latin1(又名 1252,ISO-8859-1)

标签: python utf-8


【解决方案1】:

requests 库尝试使用guess the encoding of the responserequests 可能将响应解码为 cp1252(又名 Windows-1252)。

我猜这是因为如果您将该文本编码回cp1252,然后将其解码为utf-8,您将看到正确的文本:

>>> 'criança'.encode('cp1252').decode('utf-8')
'criança'

基于此,我猜如果你问你的响应对象它猜到了什么编码,它会告诉你cp1252

>>> response.encoding
'cp1252'

强制requests 解码为utf-8,这样可能会解决您的问题:

>>> response.encoding = 'utf-8'

【讨论】:

  • Windows 没有默认编码,除非您指的是 UTF16。 Windows 中的字符串是 UTF16。 用户的系统的 语言环境影响如何处理*非*Unicode 文本。无论如何,OP提到使用Ubuntu,$LANG环境变量(pt_BR.UTF-8)不应该引起问题
  • @PanagiotisKanavos 我写的不清楚。我并不是要暗示操作系统编码很重要。 requests 库使用一些启发式方法来猜测编码(我刚刚添加了一个指向该文档的链接)。它可能已经猜到了 Windows-1252 编码,可能是基于不正确的 HTTP 标头。
  • @TreyHunner,谢谢!有效!尽管如此,当我收到像criança 这样的正确字符串时,还是会引发异常:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe7 in position 5: invalid continuation byte。因此,我必须添加一个try 来使用您的解决方案,并且对于正确接收字符串的场景,一个except 包含:text = text.encode('cp1252').decode('latin-1').encode('utf-8').decode('utf-8')。这样,无论如何我都可以将响应视为 utf-8。
  • @GabrielAtaide,听起来您有时会收到实际上正确编码为 utf-8 的字节。在这种情况下,编码为 cp1252 然后解码为 utf-8 会导致像您链接的错误一样。您可能想阅读response.content 并使用chardet 库为您猜测编码,然后手动解码字节。这样您就可以避免重新编码错误猜测的字节并希望获得最好的结果。
【解决方案2】:

如果问题仍然存在,请将您的项目复制到其他文件夹,并使用不同的项目文件名重新导入您的项目。首先重启你的Android Studio,然后从不同的文件夹导入项目,你应该已经解决了这个问题!

【讨论】:

    猜你喜欢
    • 2014-05-20
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 2022-07-26
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2019-08-29
    相关资源
    最近更新 更多