如何使python解释器正确处理string操作中的非ASCII字符?

我有一个string,看起来像这样:

6Â 918Â 417Â 712 

修剪这个string的明确方法(正如我所理解的Python),简单的说这个string是在一个名为s的variables中,我们得到:

 s.replace('Â ', '') 

这应该够了吧。 但是当然它抱怨文件blabla.py中的非ASCII字符'\xc2'没有被编码。

我从来没有完全理解如何在不同的编码之间切换。

这是代码,它和上面的代码是一样的,但现在是在上下文中。 该文件被保存为记事本中的UTF-8,并具有以下标题:

 #!/usr/bin/python2.4 # -*- coding: utf-8 -*- 

代码:

 f = urllib.urlopen(url) soup = BeautifulSoup(f) s = soup.find('div', {'id':'main_count'}) #making a print 's' here goes well. it shows 6Â 918Â 417Â 712 s.replace('Â ','') save_main_count(s) 

它不会比s.replace

Python 2使用ascii作为源文件的默认编码,这意味着您必须在文件的顶部指定另一种编码,才能在文本中使用非ASCII字符。 Python 3使用utf-8作为源文件的默认编码,所以这不是一个问题。

请参阅: http : //docs.python.org/tutorial/interpreter.html#source-code-encoding

为了启用utf-8源编码,这将在两行之一中进行:

 # -*- coding: utf-8 -*- 

以上是在文档中,但这也起作用:

 # coding: utf-8 

其他注意事项

  • 源文件也必须在文本编辑器中使用正确的编码进行保存。

  • 在Python 2中,unicode文字在它之前必须有一个u ,如s.replace(u"Â ", u"")但是在Python 3中,只需使用引号。 在Python 2中,你可以from __future__ import unicode_literals来获得Python 3的行为,但是要注意这影响了整个当前模块。

  • 如果s不是一个unicodestrings.replace(u"Â ", u"")也会失败。

  • string.replace返回一个新的string,并不在原位编辑,所以确保你也使用了返回值

 def removeNonAscii(s): return "".join(filter(lambda x: ord(x)<128, s)) 

编辑:我的第一个冲动是总是使用一个filter,但生成器expression更有效率(和更短的内存)…

 def removeNonAscii(s): return "".join(i for i in s if ord(i)<128) 

请记住,这可以保证与UTF-8编码一起工作(因为多字节字符中的所有字节都将最高位设置为1)。

 >>> unicode_string = u"hello aåbäcö" >>> unicode_string.encode("ascii", "ignore") 'hello abc' 

以下代码将用问号replace所有非ASCII字符。

 "".join([x if ord(x) < 128 else '?' for x in s]) 

使用正则expression式:

 import re strip_unicode = re.compile("([^-_a-zA-Z0-9!@#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)") print strip_unicode.sub('', u'6Â 918Â 417Â 712') 

答案太晚了,但原来的string是UTF-8,'\ xc2 \ xa0'是没有空格的UTF-8。 只需将原始string解码为s.decode('utf-8') (\ xa0在解码错误时显示为空格,如Windows-1252或latin-1:

示例(Python 3)

 s = b'6\xc2\xa0918\xc2\xa0417\xc2\xa0712' print(s.decode('latin-1')) # incorrectly decoded u = s.decode('utf8') # correctly decoded print(u) print(u.replace('\N{NO-BREAK SPACE}','_')) print(u.replace('\xa0','-')) # \xa0 is Unicode for NO-BREAK SPACE 

产量

 6Â 918Â 417Â 712 6 918 417 712 6_918_417_712 6-918-417-712 
 #!/usr/bin/env python # -*- coding: utf-8 -*- s = u"6Â 918Â 417Â 712" s = s.replace(u"Â", "") print s 

这将打印出6 918 417 712

我知道这是一个古老的线程,但我感到不得不提到翻译方法,它总是一个很好的方式来取代128以上的所有字符代码(或其他如果需要的话)。

用法 :str。 translate表[,deletechars]

 >>> trans_table = ''.join( [chr(i) for i in range(128)] + [' '] * 128 ) >>> 'Résultat'.translate(trans_table) 'R sultat' >>> '6Â 918Â 417Â 712'.translate(trans_table) '6 918 417 712' 

Python 2.6开始,您也可以将表设置为None,并使用deletechars删除不需要的字符,如http://docs.python.org/library/stdtypes中的标准文档中所示。; HTML 。

使用unicodestring时,转换表不是256个字符的string,而是以相关字符的ord()作为关键字的字典。 但是无论如何,从unicodestring中获得一个合适的asciistring是很简单的,使用上面提到的truppo方法,即:unicode_string.encode(“ascii”,“ignore”)

作为一个总结,如果由于某种原因,你绝对需要得到一个asciistring(例如,当你用raise Exception, ascii_message引发一个标准exception),你可以使用下面的函数:

 trans_table = ''.join( [chr(i) for i in range(128)] + ['?'] * 128 ) def ascii(s): if isinstance(s, unicode): return s.encode('ascii', 'replace') else: return s.translate(trans_table) 

翻译的好处在于,您可以将重音字符实际转换为相关的非重音ASCII字符,而不是简单地删除它们或将其replace为“?”。 这通常是有用的,例如用于索引目的。

 s.replace(u'Â ', '') # u before string is important 

并使您的.py文件unicode。

这是一个肮脏的黑客,但可能工作。

 s2 = "" for i in s: if ord(i) < 128: s2 += i 

对于它的价值,我的字符集是utf-8并且包含了经典的“ # -*- coding: utf-8 -*- ”这一行。

但是,我发现从网页上读取这些数据时我没有Universal Newlines。

我的文本有两个词,用“ \r\n ”分隔。 我只是分裂\n并replace"\n"

有一次,我看了一下这个字符集,发现了错误。

所以,它也可以在ASCII字符集内,但是你没有想到的字符。