2012-02-10 78 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']