协慌网

登录 贡献 社区

UnicodeEncodeError:'ascii' 编解码器无法对位置 20 中的字符 u'\ xa0' 进行编码:序数不在范围内(128)

我在处理从不同网页(在不同网站上)获取的文本中的 unicode 字符时遇到问题。我正在使用 BeautifulSoup。

问题是错误并不总是可重现的; 它有时适用于某些页面,有时候,它会通过抛出UnicodeEncodeError 。我已经尝试了几乎所有我能想到的东西,但是我没有找到任何可以持续工作的东西而不会抛出某种与 Unicode 相关的错误。

导致问题的代码部分之一如下所示:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

以下是运行上述代码段时在 SOME 字符串上生成的堆栈跟踪:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)

我怀疑这是因为某些页面(或更具体地说,来自某些站点的页面)可能被编码,而其他页面可能是未编码的。所有这些网站都位于英国,并提供供英国消费的数据 - 因此,没有与内部化或处理用英语以外的任何文字处理的文本相关的问题。

有没有人有任何想法如何解决这个问题,以便我可以一致地解决这个问题?

答案

您需要阅读 Python Unicode HOWTO 。这个错误是第一个例子

基本上,停止使用str从 unicode 转换为编码的文本 / 字节。

相反,正确使用.encode()来编码字符串:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

或者完全以 unicode 工作。

这是一个经典的 python unicode 痛点!考虑以下:

a = u'bats\u00E0'
print a
 => batsà

到目前为止一切都很好,但如果我们调用 str(a),让我们看看会发生什么:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

噢,这不会对任何人有任何好处!要修复错误,请使用. encode 显式编码字节并告诉 python 要使用的编解码器:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil \ u00E0!

问题是,当你调用 str()时,python 使用默认的字符编码来尝试编码你给它的字节,在你的情况下有时代表 unicode 字符。要解决这个问题,你必须告诉 python 如何使用. encode('whatever_unicode')处理你给它的字符串。大多数时候,使用 utf-8 应该没问题。

有关此主题的精彩论述,请参阅 Ned Batchelder 的 PyCon 演讲: http//nedbatchelder.com/text/unipain.html

我发现优雅的工作方法可以删除符号并继续将字符串保存为字符串如下:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

重要的是要注意使用 ignore 选项是危险的,因为它会静默地从使用它的代码中删除任何 unicode(和国际化)支持,如此处所示(转换 unicode):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'