在我的Python脚本中,我从一个我没有编写的函数中获取一些字符串。它的编码方式各不相同。我需要将其转换为ASCII格式。有什么绝对可靠的方法吗?我不介意用空格或其他字符替换非ASCII字符...
repr()
函数(Python 2.X)或ascii()
函数(Python 3.x)。str
转换为unicode
类型:encoded_string = i_have_no_control()
the_encoding = 'utf-8' # for the sake of example
text = unicode(encoded_string, the_encoding)
如果你愿意,你可以将Unicode对象重新编码为ASCII。
ascii_garbage = text.encode('ascii', 'replace')
* 有启发式方法来猜测编码,但它们速度较慢且不可靠。这里是一个在Python中的优秀尝试:chardet。
我会尝试对字符串进行规范化,然后再进行编码。比如:
import unicodedata
s = u"éèêàùçÇ"
print unicodedata.normalize('NFKD',s).encode('ascii','ignore')
只有在输入为Unicode时才有效。 因此,您必须知道函数输出的编码方式并对其进行解码。如果不知道,可以使用编码检测启发式算法,但在短字符串上,这些算法不可靠。
当然,你可能会有好运,函数的输出依赖于各种未知编码,但以ASCII为代码基础,因此它们将为0到127的字节分配相同的值(例如UTF-8)。
在这种情况下,您可以使用OrderedSets过滤掉不需要的字符:
import string.printable # asccii chars
print "".join(OrderedSet(string.printable) & OrderedSet(s))
print("".join(((char if char in string.printable else " ") for char in s )))
如果你只想保留ASCII兼容字符并丢弃其余字符,那么在大多数编码中,这归结为删除所有具有高位设置的字符--即值超过127的字符。这是有效的,因为几乎所有字符集都是7位ASCII的扩展。
如果它是一个普通字符串(即不是unicode
),则需要在任意字符集(例如iso-8859-1
,因为它接受任何字节值)中进行解码,然后使用ignore
或replace
选项对错误进行ASCII编码:
>>> orig = '1ä2äö3öü4ü'
>>> orig.decode('iso-8859-1').encode('ascii', 'ignore')
'1234'
>>> orig.decode('iso-8859-1').encode('ascii', 'replace')
'1??2????3????4??'
解码步骤是必要的,因为您需要一个Unicode字符串才能使用编码。如果您已经有了一个Unicode字符串,那么就更简单了:
>>> orig = u'1ä2äö3öü4ü'
>>> orig.encode('ascii', 'ignore')
'1234'
>>> orig.encode('ascii', 'replace')
'1??2????3????4??'
'1ä2äö3öü4ü'.decode("ascii", "ignore")
。在我看来,仅仅因为你使用了简化字符集并不意味着 Unicode 类型对于文本字符串是一个不好的选择。 - u0b34a0f6ae'ignore'
可以正常工作,但是当你使用 'replace'
时,它会给你一个带有 Unicode 字符串的结果:u'1\ufffd\ufffd2\ufffd\ufffd\ufffd\ufffd3\ufffd\ufffd\ufffd\ufffd4\ufffd\ufffd'
。 - intgrucity = u"\u041c\u043e\u0441\u043a\u0432\u0430"; ''.join(chr(ord(c) & 0x7f) for c in ucity.encode('koi8_r'))
会产生 'mOSKWA'
。 - John Machin
ä
转换为a
,这显然不能通过假设您的编码每个字符占一个字节,并掩盖非ASCII字节来完成,正如您所建议的那样! - Jonathan Feinberg