2024-06-16 16:27:42 发布
网友
我有很多外部文件的XML文档和文件名,它们有各种形式的文本损坏或Mojibake,在导入过程中会导致数据质量问题。我读过很多关于StackOverflow的文章,关于如何纠正字符串,但是他们没有真正概述如何以系统的方式清理文本,python的decode,encode似乎也帮不上忙。如何使用python2.7恢复包含拉丁语-1(ISO-8859-1)范围内字符但通常具有混合编码的XML文件和文件名?在
decode
encode
如果你不能对你将要遇到的信件做出假设,你可能就有麻烦了。因此,在我们的文档中,我们可以合理地假设挪威字母A-Å。没有什么神奇的工具可以自动更正您遇到的每个文档。在
A-Å
因此,在这个域中,我们知道一个文件可能包含å,其UTF-8 2字节表示0xc3 0xa5或{a1},Latin-1和{a3}将其表示为0xe5。一般来说,这个character lookup非常好,如果你发现自己在研究一个字符,它可能会成为一个很好的书签。在
å
0xc3 0xa5
0xe5
Ã¥
您可以在这个方便的debugging chart中找到这类问题的长列表。在
如果你知道到底是什么地方出了问题,这是最简单的方法把绳子打回原形。在
our_broken_string = 'Ã¥' broken_unicode = our_broken_string.decode('UTF-8') print broken_unicode # u'\xc3\xa5' yikes -> two different unicode characters down_converted_string = broken_unicode.encode('LATIN-1') print down_converted_string # '\xc3\xa5' those are the right bytes correct_unicode = down_converted_string.decode('UTF-8') print correct_unicode # u'\xe5' correct unicode value
在处理文档时,可以做出一些相对较好的假设。单词、空格和行。即使文档是XML,您仍然可以将其视为单词,而不必太担心标记,或者如果单词确实是单词,则只需要能找到的最小单元。我们还可以假设,如果文件有文本编码问题,它可能也有行尾问题,这取决于有多少不同的操作系统损坏了该文件。我将在行尾中断rstrip,并使用print将数组重新组合到StringIO文件句柄。在
rstrip
StringIO
在保留空白时,通过一个漂亮的print函数运行XML文档可能很诱人,但是您不应该这样做,我们只想在不改变任何其他内容的情况下更正小文本单元的编码。一个好的起点是看看是否可以逐行逐字地阅读文档,而不是在任意的字节块中,而忽略您正在处理的是XML。在
在这里,我利用这样一个事实:如果文本超出UTF-8的范围,那么您将得到unicodedecoderrors,然后尝试使用拉丁语-1。这在这个文件中起作用了。在
如果你的问题是真的Mojibake,比如一个错误的文件名。您可以使用FTFY尝试试探性地更正您的问题。同样,我会采取逐字逐句的方法来获得最佳效果。在
import os import sys import ftfy import unicodedata if __name__ == '__main__': path = sys.argv[1] file_system_encoding = sys.getfilesystemencoding() unicode_path = path.decode(file_system_encoding) for root, dirs, files in os.walk(unicode_path): for f in files: comparable_original_filename = unicodedata.normalize('NFC', f) comparable_new_filename = ftfy.fix_text(f, normalization='NFC') if comparable_original_filename != comparable_new_filename: original_path = os.path.join(root, f) new_path = os.path.join(root, comparable_new_filename) print "Renaming:" + original_path + " to:" + new_path os.rename(original_path, new_path)
这通过目录更正了很多更丑陋的错误,其中å被拼成了{}。这是什么?大写字母A+COMBINING LETTER TILDE0xcc 0x83是使用unicode equivalence表示Ã的几种方法之一。这确实是FTFY的一项工作,因为它实际上将执行一个启发式的任务,并解决这些类型的问题。在
A
COMBINING LETTER TILDE
Ã
另一种方法是使用unicode的规范化来获得正确的字节。在
import unicodedata a_combining_tilde = 'A\xcc\x83' # Assume: Expecting UTF-8 unicode_version = a_combining_tilde.decode('UTF-8') # u'A\u0303' and this cannot be converted to LATIN-1 and get à normalized = unicodedata.normalize('NFC', unicode_version) # u'\c3' broken_but_better = normalized.encode('UTF-8') # '\xc3\x83` correct UTF-8 bytes for Ã.
总之,如果将其作为UTF-8编码的字符串A\xcc\x83\xc2\xa5,对其进行规范化,然后向下转换为拉丁语-1字符串,然后再返回到UTF-8,您将获得正确的unicode。在
A\xcc\x83\xc2\xa5
你需要注意操作系统是如何编码文件名的。您可以通过以下方式检索该信息:
file_system_encoding = sys.getfilesystemencoding()
假设file_system_encoding是{},对吗?然后比较两个看起来完全相同的unicode字符串,结果它们不相等!FTFY,默认规格化为NFC,HFS规范化为NFD的旧版本。因此,仅仅知道编码是相同的是不够的,你必须用同样的方式规范化比较才能有效。在
file_system_encoding
NFC
NFD
在节点.js有关于dealing with different filesystems的好指南。总之,规范化是为了比较,不要任意地重新规范化文件名。在
在XML d中文档您将得到这样的东西,它应该通知XML解析器有关文本编码的信息。在
<?xml version="1.0" encoding="ISO-8859-1"?>
如果你看到了这一点,在被证明是真的之前,它应该被视为谎言。在将此文档交给XML解析器之前,您需要验证和处理编码问题,并且需要更正声明。在
字节顺序标记听起来是个不错的主意,但就像它们的XML声明一样,它们是文件编码情况的完全不可靠的指示器。Within UTF-8, BOMs are NOT recommended并且对于字节顺序没有意义。它们唯一的值是指示某些东西是用UTF-8编码的。但是,考虑到文本编码的问题,默认值是而且应该是预期的UTF-8。在
你必须做出假设
如果你不能对你将要遇到的信件做出假设,你可能就有麻烦了。因此,在我们的文档中,我们可以合理地假设挪威字母
A-Å
。没有什么神奇的工具可以自动更正您遇到的每个文档。在因此,在这个域中,我们知道一个文件可能包含
å
,其UTF-8 2字节表示0xc3 0xa5
或{a1},Latin-1和{a3}将其表示为0xe5
。一般来说,这个character lookup非常好,如果你发现自己在研究一个字符,它可能会成为一个很好的书签。在示例
Ã¥
您可以在这个方便的debugging chart中找到这类问题的长列表。在
基本Python编码、解码
如果你知道到底是什么地方出了问题,这是最简单的方法把绳子打回原形。在
文件
在处理文档时,可以做出一些相对较好的假设。单词、空格和行。即使文档是XML,您仍然可以将其视为单词,而不必太担心标记,或者如果单词确实是单词,则只需要能找到的最小单元。我们还可以假设,如果文件有文本编码问题,它可能也有行尾问题,这取决于有多少不同的操作系统损坏了该文件。我将在行尾中断
rstrip
,并使用print将数组重新组合到StringIO
文件句柄。在在保留空白时,通过一个漂亮的print函数运行XML文档可能很诱人,但是您不应该这样做,我们只想在不改变任何其他内容的情况下更正小文本单元的编码。一个好的起点是看看是否可以逐行逐字地阅读文档,而不是在任意的字节块中,而忽略您正在处理的是XML。在
在这里,我利用这样一个事实:如果文本超出UTF-8的范围,那么您将得到unicodedecoderrors,然后尝试使用拉丁语-1。这在这个文件中起作用了。在
^{pr2}$处理Mojibake
如果你的问题是真的Mojibake,比如一个错误的文件名。您可以使用FTFY尝试试探性地更正您的问题。同样,我会采取逐字逐句的方法来获得最佳效果。在
这通过目录更正了很多更丑陋的错误,其中}。这是什么?大写字母
å
被拼成了{A
+COMBINING LETTER TILDE
0xcc 0x83是使用unicode equivalence表示Ã
的几种方法之一。这确实是FTFY的一项工作,因为它实际上将执行一个启发式的任务,并解决这些类型的问题。在用于比较和文件系统的Unicode规范化
另一种方法是使用unicode的规范化来获得正确的字节。在
总之,如果将其作为UTF-8编码的字符串
A\xcc\x83\xc2\xa5
,对其进行规范化,然后向下转换为拉丁语-1字符串,然后再返回到UTF-8,您将获得正确的unicode。在你需要注意操作系统是如何编码文件名的。您可以通过以下方式检索该信息:
假设},对吗?然后比较两个看起来完全相同的unicode字符串,结果它们不相等!FTFY,默认规格化为
file_system_encoding
是{NFC
,HFS规范化为NFD
的旧版本。因此,仅仅知道编码是相同的是不够的,你必须用同样的方式规范化比较才能有效。在在节点.js有关于dealing with different filesystems的好指南。总之,规范化是为了比较,不要任意地重新规范化文件名。在
最后说明
谎言、该死的谎言和XML声明
在XML d中文档您将得到这样的东西,它应该通知XML解析器有关文本编码的信息。在
如果你看到了这一点,在被证明是真的之前,它应该被视为谎言。在将此文档交给XML解析器之前,您需要验证和处理编码问题,并且需要更正声明。在
谎言,该死的谎言和BOM标记
字节顺序标记听起来是个不错的主意,但就像它们的XML声明一样,它们是文件编码情况的完全不可靠的指示器。Within UTF-8, BOMs are NOT recommended并且对于字节顺序没有意义。它们唯一的值是指示某些东西是用UTF-8编码的。但是,考虑到文本编码的问题,默认值是而且应该是预期的UTF-8。在
相关问题 更多 >
编程相关推荐