2012-02-10 77 views
18

我有使用utf-8编码的文本文件,其中包含'ö','ü'等字符我想解析这些文件的文本形式,但是我无法将标记器好好工作。如果我使用标准NLTK分词器:使用nltk令牌化Unicode使用nltk

f = open('C:\Python26\text.txt', 'r') # text = 'müsli pöök rääk' 
text = f.read() 
f.close 
items = text.decode('utf8') 
a = nltk.word_tokenize(items) 

输出:[u'\ufeff', u'm', u'\xfc', u'sli', u'p', u'\xf6', u'\xf6', u'k', u'r', u'\xe4', u'\xe4', u'k']

PUNKT分词似乎做的更好:

f = open('C:\Python26\text.txt', 'r') # text = 'müsli pöök rääk' 
text = f.read() 
f.close 
items = text.decode('utf8') 
a = PunktWordTokenizer().tokenize(items) 

输出:[u'\ufeffm\xfcsli', u'p\xf6\xf6k', u'r\xe4\xe4k']

有仍然'\ ufeff'之前第一个令牌,我不明白(不是我不能删除它)。我究竟做错了什么?非常感谢。

回答

19

它更可能的是,\uFEFF焦炭是从文件中读取内容的一部分。我怀疑它是由记号器插入的。 \uFEFF在文件的开头是Byte Order Mark的弃用形式。如果它出现在其他地方,那么它将被视为zero width non-break space

是由Microsoft记事本写的文件吗?从the codecs module docs

为了增加与一个UTF-8编码可检测的可靠性,微软发明UTF-8的变体(即Python 2.5的呼叫 “UTF-8-SIG”)为它的记事本程序:在将任何Unicode字符写入文件之前,会写入UTF-8编码的BOM(它看起来像字节序列:0xef,0xbb,0xbf)。

尝试使用codecs.open()来读取文件。请注意消耗BOM的"utf-8-sig"编码。

import codecs 
f = codecs.open('C:\Python26\text.txt', 'r', 'utf-8-sig') 
text = f.read() 
a = nltk.word_tokenize(text) 

实验:

>>> open("x.txt", "r").read().decode("utf-8") 
u'\ufeffm\xfcsli' 
>>> import codecs 
>>> codecs.open("x.txt", "r", "utf-8-sig").read() 
u'm\xfcsli' 
>>> 
+0

谢谢。您的代码可以剔除\ uFEFF – root 2012-02-10 14:16:40

+0

@ user1199589不客气。很高兴我能帮上忙。 – 2012-02-10 15:00:24

+0

也帮助我。非常感谢! – Pitarou 2012-11-27 03:14:03

4

的UFEE代码是“ZERO WIDTH NO-BREAK SPACE”的字符,这是不考虑由re模块的空间,所以它使用正则表达式r'\w+|[^\w\s]+'与Unicode和DOTALL标志的PunktWordTokenizer()承认这个字符作为一个字。如果你不想手动删除字符,你可以使用下面的标记生成器:

nltk.RegexpTokenizer(u'\w+|[^\w\s\ufeff]+') 
12

你应该确保你传递的Unicode字符串NLTK断词。在我的结尾处,我用以下两个标记器获得以下相同的标记:

import nltk 
nltk.wordpunct_tokenize('müsli pöök rääk'.decode('utf8')) 
# output : [u'm\xfcsli', u'p\xf6\xf6k', u'r\xe4\xe4k'] 

nltk.word_tokenize('müsli pöök rääk'.decode('utf8')) 
# output: [u'm\xfcsli', u'p\xf6\xf6k', u'r\xe4\xe4k']