【问题标题】:Replacing non-ascii characters in an ascii encoded string替换 ascii 编码字符串中的非 ascii 字符
【发布时间】:2015-09-22 20:42:11
【问题描述】:

我有这个代码片段(Python 2.7):

from bs4 import BeautifulSoup

content = '  foo bar';
soup = BeautifulSoup(content, 'html.parser')
w = soup.get_text()

此时w中有一个值为160的字节,但它的编码是ASCII

如何将所有 \xa0 字节替换为另一个字符?

我试过了:

w = w.replace(chr(160), ' ')
w = w.replace('\xa0', ' ')

但我得到了错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 0: ordinal not in range(128)

为什么 BS 返回一个带有无效字符的ASCII 编码字符串?

有没有办法将w 转换为“latin1”编码的字符串?

【问题讨论】:

  • 你也可以使用'hèlłø'.encode('ascii', 'replace')

标签: python string character-encoding


【解决方案1】:

此时 w 中有一个值为 160 的字节,但它的编码是 'ascii'。

你有一个 unicode 字符串:

>>> w
u'\xa0 foo bar'
>>> type(w)
<type 'unicode'>

如何将所有 \xa0 字节替换为另一个字符?

>>> x = w.replace(u'\xa0', ' ')
>>> x
u'  foo bar'

为什么 BS 会返回一个包含无效字符的 'ascii' 编码字符串?

如上所述,它不是一个ascii编码的字符串,而是一个Unicode字符串实例。

有没有办法将 w 转换为 'latin1` 编码的字符串?

当然:

>>> w.encode('latin1')
'\xa0 foo bar'

(请注意,最后一个字符串是编码字符串,不是 unicode 对象,它的表示不像前面的 unicode 对象那样以 'u' 为前缀)。

注释(已编辑):

  • 如果您在源文件中输入字符串,请注意源文件的编码很重要。 Python 将假定您的源文件是 ASCII。另一方面,命令行解释器将假定您以默认系统编码输入字符串。当然,您可以覆盖所有这些。
  • 避免使用 latin1,尽可能使用 UTF-8:即。 w.encode('utf8')
  • 在编码和解码时可以告诉 Python ignore 错误,或者 replace 无法用某些标记字符编码的字符。我不建议忽略编码错误(至少不记录它们),除非您知道存在编码错误或您需要将文本编码为更精简的字符集,需要替换代码点的极少数情况无法表示(即,如果您需要将“España”编码为 ASCII,则绝对应该替换“ñ”)。但是对于这些情况,有更好的选择,您应该研究神奇的 unicodedata 模块(请参阅https://stackoverflow.com/a/1207479/401656)。
  • 有一个 Python Unicode HOWTO:https://docs.python.org/2/howto/unicode.html

【讨论】:

  • 因此错误消息不是关于w,而是关于chr(160)'\xa0' - 这些是ascii 编解码器无法处理的字符串。对吗?
  • 没错。顺便说一句,我在答案中添加了很多信息。
  • 感谢您的帮助。老实说,我没有发现 Unicode HOWTO 对回答我的概念性问题很有帮助。 Python Unicode 支持类似于其他语言。我在这里写了另一种解释方式:(link) 欢迎评论。
  • 我很喜欢您的文章,并且认为 Unicode Howto 需要大量改进。我也曾经遭受 str 和 unicod 之间的差异,希望那时我有你的文章。让我发疯的另一件事是 strunicode 都有 encode()decode() 方法,它们的语义略有不同,这对我来说是一个陷阱。但是 Unicode 问题总是有一个陡峭的学习曲线。我也可以推荐乔尔的文章:“Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
猜你喜欢
  • 2017-04-13
  • 1970-01-01
  • 2013-06-20
  • 1970-01-01
  • 2020-02-17
  • 2013-09-08
  • 1970-01-01
  • 2015-08-14
  • 1970-01-01
相关资源
最近更新 更多