【问题标题】:Python unicode accent a (à) hexPython unicode 重音 (à) 十六进制
【发布时间】:2018-10-17 07:37:51
【问题描述】:

我有一个来自 bs4 的字符串

s = "vinili-disponibili/311-canzoniere-del-lazio-lassa-st\u00c3\u00a0-la-me-creatura.html"

\u00c3\u00a0应该是重音a(à)我已经让它在控制台中显示部分正确

vinili-disponibili/311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html

str2 = u'%s' % s
print(str2.encode('utf-8').decode('unicode-escape'))

但它分别解码 c3 和 a0,所以我得到的是波浪号 A 而不是重音 a。我知道 c3 a0 是重音 a 的十六进制 utf-8。我不知道发生了什么,我使用谷歌和我得到的答案的组合方法来到这里。这整个字符编码的事情对我来说似乎是一团糟。

应该是这样的

311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html

编辑: Andrey 的方法在打印出来时有效,但尝试将 urlopen 与我得到的字符串一起使用 UnicodeEncodeError: 'ascii' codec can't encode character '\xe0' in position 60: ordinal not in range(128)

使用unquote(str,":/") 后,它会给出UnicodeEncodeError: 'ascii' codec can't encode characters in position 56-57: ordinal not in range(128)

【问题讨论】:

  • 这里有问题。你是怎么得到这样的字符串的?我很确定你已经做错了什么,在上游解决问题比追溯清理烂摊子要好。
  • 原始数据是用什么编码创建的? ISO-8859-1?应该在 HTML 文件的顶部定义。
  • input.encode('latin-1').decode('raw_unicode_escape').encode('latin-1').decode('utf-8') 有效,似乎与建议的副本相同。 @Aran-Fey 如果损坏的上游来源是 Facebook 本身,修复可能会很困难。
  • 它来自一个网站的 bs4 抓取。该站点调用了一个后端 php 脚本,该脚本输出 html 正文,但所有的 '\' 作为 '\\' 和一堆 '\\t' 和 '\\n'。我只是对整个事情进行正则表达式以使'\\'变为'\',但我无法控制它们的编码。我无法从头部获取编码,因为脚本只生成 html 正文。 @AndreyTyukin 的建议虽然适用于我的数据。

标签: python unicode character-encoding


【解决方案1】:

使用 .encode('latin-1') 将字符串转换回字节,然后解码 unicode-escapes \u,使用“错误”'latin-1' 编码再次将所有内容转换为字节,最后“正确”解码为 'utf-8'

s = "vinili-disponibili/311-canzoniere-del-lazio-lassa-st\u00c3\u00a0-la-me-creatura.html"
s.encode('latin-1').decode('raw_unicode_escape').encode('latin-1').decode('utf-8')

给予:

'vinili-disponibili/311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html'

它的工作原理与this answer 中解释的相同。

【讨论】:

    【解决方案2】:

    假设 Python 2:

    这是一个带有 Unicode 转义的字节字符串。为某些 UTF-8 编码的数据错误地生成了 Unicode 转义:

    >>> s = "vinili-disponibili/311-canzoniere-del-lazio-lassa-st\u00c3\u00a0-la-me-creatura.html"
    >>> s.decode('unicode-escape')
    u'vinili-disponibili/311-canzoniere-del-lazio-lassa-st\xc3\xa0-la-me-creatura.html'
    

    现在它是一个 Unicode 字符串,但现在出现错误解码,因为代码点类似于 UTF-8 字节。它转而输出 latin1(也称为 iso-8859-1)编解码器将前 256 个代码点直接映射到字节 0-255,因此使用此技巧将其转换回字节字符串:

    >>> s.decode('unicode-escape').encode('latin1')
    'vinili-disponibili/311-canzoniere-del-lazio-lassa-st\xc3\xa0-la-me-creatura.html'
    

    现在可以正确解码为 UTF-8:

    >>> s.decode('unicode-escape').encode('latin1').decode('utf8')
    u'vinili-disponibili/311-canzoniere-del-lazio-lassa-st\xe0-la-me-creatura.html'
    

    它是一个 Unicode 字符串,因此 Python 显示它的 repr() 值,它将 U+007F 以上的代码点显示为转义码。 print 查看实际值,假设您的终端正确配置了支持打印字符的编码:

    >>> print(s.decode('unicode-escape').encode('latin1').decode('utf8'))
    vinili-disponibili/311-canzoniere-del-lazio-lassa-stà-la-me-creatura.html
    

    理想情况下,首先解决错误生成此字符串的问题,而不是解决混乱问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-04
      • 2020-02-06
      • 2014-12-28
      • 2020-02-12
      • 2018-04-19
      • 1970-01-01
      • 2013-01-18
      • 2021-04-30
      相关资源
      最近更新 更多