如何在Python中找到正确的编码?
我正在尝试去掉文本文件中的重音符号。我用一个工具把PDF文件转换成了文本,这个工具不是我自己做的。我没能搞清楚他们使用了什么编码。文本是用纳瓦特尔语写的,拼写上和西班牙语有点像。
我把文本转换成了字符串列表。现在我想做的是:
# check whether there is a not-ascii character in the item
def is_ascii(word):
check = string.ascii_letters + "."
if word not in check:
return False
return True
# if there is a not ascii-character encode the string
def to_ascii(word):
if is_ascii(word) == False:
newWord = word.encode("utf8")
return newWord
return word
我想要的是字符串的unicode版本。但到目前为止都不行,我尝试了几种编码方式,比如latin1、cp1252、iso-8859-1。结果却是这样:有人能告诉我我哪里出错了吗?
我该怎么找出正确的编码呢?
谢谢!
编辑: 我联系了开发这个转换器(pdf-txt)的人,他们说他们已经在使用unicode了。所以约翰·马钦在他的回答中提到的(1)是对的。 正如我在某个评论中提到的,这让我感到困惑,因为在Eclipse调试器中,列表本身显示了一些unicode符号,而其他的则没有。如果我单独查看这些项目,它们都以某种方式解码,所以我实际上看到了unicode。
谢谢你的帮助!
2 个回答
如果你已经读取了一些字节,并想把它们当作一个 unicode
字符串来理解,那么你需要使用 .decode()
,而不是 encode()
。
就像 @delnan 在评论中提到的,我希望你知道这些字节的编码方式。如果不知道,猜测也没关系,只要你修正使用的函数就行。
顺便说一下,即使那个词里面只有 ASCII 字符,为什么不也用 .decode()
呢?这样你到处都有相同的数据类型(unicode
),这会让你的程序更简单。
请编辑你的问题,告诉我们你使用的Python版本。根据你的代码来猜测版本是不可能的。你是用Python 3.X还是2.X,这个很重要。以下内容假设你在使用Python 2.x。
你似乎已经确定你的文本是UTF-8编码的。试试 the_text.decode('utf8')
。注意是解码,不是编码。
如果用UTF-8解码没有出现 UnicodeDecodeError
错误,并且你的文本长度不是特别短,那么可以很肯定地说UTF-8是正确的编码。
如果以上方法不行,给我们看看 print repr(the_text)
的结果。
注意,检查文件是否是ASCII编码是没有意义的——因为ASCII是UTF-8的一个子集。在Python 2.x中,把一些数据留作 str
对象,其他的留作 unicode
对象会很麻烦,而在Python 3.X中是行不通的。
无论如何,你的第一个函数并没有做你想的事情;对于任何长度为2或以上的输入字符串,它都会返回 False
。请在写函数时考虑进行单元测试;这样后期调试会快很多。
注意 latin1
和 iso-8859-1
是相同的编码。因为 latin1
编码了Unicode中前256个字符,并且顺序是一样的,所以用 text.decode('latin1')
不可能引发 UnicodeDecodeError
。在这种情况下,“没有错误”没有任何诊断价值。
更新,回应OP的评论:
我使用的是Python 2.7。如果我使用
text.decode("utf8")
,会出现以下错误:UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2014' in position 0: ordinal not in range(256).
这可能有两种情况:
(1) 在像 foo = text.decode('utf8')
这样的单个语句中,text
已经是一个unicode对象,所以Python 2.X尝试用默认编码(latin-1 ???)来编码它。
(2) 可能是两个不同的语句,首先是 foo = text.decode('utf8')
,其中 text
是一个用UTF-8编码的 str
对象,这个语句没有引发错误,接着是类似 print foo
的语句,而你的 sys.stdout.encoding 是 latin-1
(???)。
我无法想象你为什么会把我的回答标记为正确。现在还没有人知道问题是什么呢!
请编辑你的问题,展示你的代码(在 text.decode("utf8")
这一行之前插入 print repr(text)
),以及运行结果。展示 repr() 的结果和完整的错误追踪(这样我们可以确定是哪一行导致了错误)。
我再问一次:你能把你的文件提供出来让我们分析吗?
顺便说一下, u'\u2014'
是一个“长破折号”,在 cp1252
中是一个有效字符(但在 latin-1
中不是,正如你从错误信息中看到的)。你使用的是什么版本的操作系统?
还有,回答你最后的问题,不,你绝对不应该尝试用所有已知的编码来解码你的文本。你已经得到了合理的Unicode;某些东西(你的代码?)正在以某种方式解码某些东西——u'\u2014'
的存在就足够证明这一点。只需给我们看看你的代码和结果。