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

时间:2009-08-27 15:53:31

标签: python unicode

我有一个看起来像这样的字符串:

6 918 417 712

修剪此字符串的明确方法(据我理解Python)只是说字符串位于名为s的变量中,我们得到:

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 ...

11 个答案:

答案 0 :(得分:155)

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

编辑:我的第一个冲动始终是使用过滤器,但生成器表达式更高效(更短)......

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

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

答案 1 :(得分:75)

Python 2使用ascii作为源文件的默认编码,这意味着您必须在文件顶部指定另一个编码才能在文字中使用非ascii unicode字符。 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.replace(u"Â ", u"")不是unicode字符串,
  • s也会失败。

  • string.replace会返回一个新字符串,并且不会进行适当的编辑,因此请确保您也使用了返回值

答案 2 :(得分:30)

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

答案 3 :(得分:16)

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

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

答案 4 :(得分:6)

使用正则表达式:

import re

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

答案 5 :(得分:5)

答案太迟了,但是原始字符串是UTF-8而'\ xc2 \ xa0'是UTF-8,用于NO-BREAK SPACE。只需将原始字符串解码为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

答案 6 :(得分:3)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

s = u"6Â 918Â 417Â 712"
s = s.replace(u"Â", "") 
print s

这将打印出6 918 417 712

答案 7 :(得分:2)

我知道这是一个老线程,但我觉得有必要提一下翻译方法,这总是一种很好的方法来替换128以上的所有字符代码(或其他必要的话)。

用法:str。翻译 table [,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上的标准文档。

对于unicode字符串,转换表不是256个字符的字符串,而是带有相关字符的ord()作为键的字典。但无论如何从unicode字符串中获取正确的ascii字符串很简单,使用上面的truppo提到的方法,即:unicode_string.encode(“ascii”,“ignore”)

总结一下,如果由于某种原因你绝对需要获得一个ascii字符串(例如,当你使用raise Exception, ascii_message引发标准异常时),你可以使用以下函数:

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字符,而不是简单地删除它们或用'?'替换它们。这通常很有用,例如用于索引目的。

答案 8 :(得分:1)

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

并使您的.py文件为unicode。

答案 9 :(得分:1)

这是一个肮脏的黑客,但可能会有效。

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

答案 10 :(得分:0)

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

但是,我发现从网页上读取这些数据时我没有通用换行符。

我的文字有两个单词,以“\r\n”分隔。我只是在\n上拆分并替换了"\n"

一旦我循环并看到有问题的角色,我意识到了这个错误。

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