【问题标题】:Python, Unicode: Working with badly formatted stringsPython、Unicode:处理格式错误的字符串
【发布时间】:2017-10-11 14:58:06
【问题描述】:

我正在开发一个从 Redshift 数据库获取数据的 Django 应用程序。给这个 Redshift 数据库写信的人做出了一些奇怪的选择。我试图弄清楚如何处理它具有这样的字符串的事实:

Let’s play! \xe2\x9a\xbd\xef\xb8\x8f

通过 psycopg2,我将这些作为 Python 输入

u'Let\u2019s play! \\xe2\\x9a\\xbd\\xef\\xb8\\x8f'

我应该把它渲染成

来玩吧! ⚽️

它们在 Redshift 表中存储为varchar(65535)。我正在使用 pyscopg2 将它们拉入应用程序后端(Django 1.11、Python 2.7)。它们在前端使用 JavaScript 进行渲染。

任何建议都将不胜感激——我根本想不出任何解决方案。

【问题讨论】:

  • 您在数据库中有mojibake。它有多种编码。我不确定你是如何得到你在 psycopg2 中所做的结果的,因为我找不到可以返回该结果的编码器。获取 U+2019 代码点意味着使用 Windows-125x 编码器,但它们都不会在 Python 中返回 UTF-8 余数而不会出错。字符串的正确 UTF-8 编码应为 'Let\xe2\x80\x99s play! \xe2\x9a\xbd\xef\xb8\x8f'
  • 哎呀,我从 psycopg2 得到的结果是对的。更新的问题。

标签: unicode utf-8 python-unicode unicode-normalization unicode-literals


【解决方案1】:

因为有混合编码(看起来像 Windows-1252 和十六进制转义的 UTF-8),如果这种混合是一致的,您可以尝试对条目进行后处理。

下面是一个正则表达式,用于查找十六进制转义序列并将其替换为 UTF-8 解码的等价物:

import re

esc = re.compile(r'(?:\\x[0-9a-f]{2})+')

def fixer(m):
    return m.group().encode('latin1').decode('unicode-escape').encode('latin1').decode('utf8')

s = u'Let\u2019s play! \\xe2\\x9a\\xbd\\xef\\xb8\\x8f'
f = esc.sub(fixer,s)
print repr(f)
print f

输出:

u'Let\u2019s play! \u26bd\ufe0f'
Let’s play! ⚽️

【讨论】:

  • 这行得通,谢谢!接受这个答案。你能解释一下为什么要编码、解码、再次编码和再次解码吗?我已经将其视为许多 unicode 解决方案的一部分,但我不太清楚为什么。
  • @NathanHinchey 你encode 为字节,decode 为 Unicode。 .encode('latin1') 是将 U+0000 转换为 U+00FF 直接转换为字节 00-FF 的技巧,因为 latin1 字符集是 Unicode 的前 256 个代码点。所以从一个 Unicode 字符串开始,将其转为字节以便能够使用 unicode-escape 编解码器,但结果是另一个 Unicode 字符串,因此再次编码为字节并解码为 UTF8。
猜你喜欢
  • 2011-08-11
  • 2019-09-04
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
相关资源
最近更新 更多