我在处理从不同网页(在不同的网站上)获取的文本中的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)
我怀疑这是因为某些页面(或者更具体地说,来自某些网站的页面)可能是编码的,而其他页面可能是未编码的。所有的网站都设在英国,并提供英国消费的数据,因此不存在与内化或处理非英语文本相关的问题。
有没有人对如何解决这个问题有什么想法,以便我能够始终如一地解决这个问题?
这里是一些其他所谓的“逃避”答案的翻版。尽管这里有抗议声,但在某些情况下,扔掉麻烦的字符/字符串是一个很好的解决方案。
def safeStr(obj):
try: return str(obj)
except UnicodeEncodeError:
return obj.encode('ascii', 'ignore').decode('ascii')
except: return ""
测试:
if __name__ == '__main__':
print safeStr( 1 )
print safeStr( "test" )
print u'98\xb0'
print safeStr( u'98\xb0' )
结果:
1
test
98°
98
更新:我最初的答案是为Python 2编写的。对于Python 3:
def safeStr(obj):
try: return str(obj).encode('ascii', 'ignore').decode('ascii')
except: return ""
注:如果你愿意留下?指示“不安全”unicode字符所在的位置,请在调用中指定替换而不是忽略,以对错误处理程序进行编码。
建议:您可能希望将此函数命名为Ascii?这是一个偏好问题。。。
最后,这里有一个更强大的PY2/3版本,它使用了六个,我选择使用替换,并添加了一些字符交换,以用作为ascii集合一部分的简单垂直引号来替换花哨的unicode引号和撇号,这些引号或撇号向左或向右卷曲。您可以自己扩展此类掉期:
from six import PY2, iteritems
CHAR_SWAP = { u'\u201c': u'"'
, u'\u201D': u'"'
, u'\u2018': u"'"
, u'\u2019': u"'"
}
def toAscii( text ) :
try:
for k,v in iteritems( CHAR_SWAP ):
text = text.replace(k,v)
except: pass
try: return str( text ) if PY2 else bytes( text, 'replace' ).decode('ascii')
except UnicodeEncodeError:
return text.encode('ascii', 'replace').decode('ascii')
except: return ""
if __name__ == '__main__':
print( toAscii( u'testin\u2019' ) )