我在处理从不同网页(在不同的网站上)获取的文本中的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()

下面是运行上面的代码段时在某些字符串上生成的堆栈跟踪:

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)

我怀疑这是因为某些页面(或者更具体地说,来自某些网站的页面)可能是编码的,而其他页面可能是未编码的。所有的网站都设在英国,并提供英国消费的数据,因此不存在与内化或处理非英语文本相关的问题。

有没有人对如何解决这个问题有什么想法,以便我能够始终如一地解决这个问题?


当前回答

导致打印失败的一个微妙问题是环境变量设置错误,例如LC_ALL设置为“C”。在Debian中,他们不鼓励设置它:在Locale上设置Debian wiki

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà

其他回答

延迟回答,但此错误与您的终端编码不支持某些字符有关。我用以下方法在python3上修复了它:

import sys
import io

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')
print("é, à, ...")

一般情况下,如果将这个不支持的编码字符串(比如data_that_causes_ths_error)写入某个文件(例如results.txt),这是有效的

f = open("results.txt", "w")
  f.write(data_that_causes_this_error.encode('utf-8'))
  f.close()

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

不要使用str()将unicode转换为编码文本/字节。

相反,使用.encode()对字符串进行编码:

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

或完全在unicode中工作。

这里有简单的助手函数。

def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

def safe_str(obj):
    """ return the byte string representation of obj """
    try:
        return str(obj)
    except UnicodeEncodeError:
        # obj is unicode
        return unicode(obj).encode('unicode_escape')

推荐的解决方案不适用于我,我可以忍受转储所有非ascii字符,因此

s = s.encode('ascii',errors='ignore')

这给我留下了一些不会出错的东西。