如何在Python中找到正确的编码?

2 投票
2 回答
6346 浏览
提问于 2025-04-17 16:48

我正在尝试去掉文本文件中的重音符号。我用一个工具把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 个回答

1

如果你已经读取了一些字节,并想把它们当作一个 unicode 字符串来理解,那么你需要使用 .decode(),而不是 encode()

就像 @delnan 在评论中提到的,我希望你知道这些字节的编码方式。如果不知道,猜测也没关系,只要你修正使用的函数就行。

顺便说一下,即使那个词里面只有 ASCII 字符,为什么不也用 .decode() 呢?这样你到处都有相同的数据类型(unicode),这会让你的程序更简单。

1

请编辑你的问题,告诉我们你使用的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。请在写函数时考虑进行单元测试;这样后期调试会快很多。

注意 latin1iso-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' 的存在就足够证明这一点。只需给我们看看你的代码和结果。

撰写回答