如何使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字符集内,但是你没有想到的字符。