I ran into an interesting problem when attempting to tokenise a french text using nltk (version 3.1, python 2.7). Here is the code snippet I am using.
#python 2.7
from __future__ import division
import nltk, re, pprint
f= open('test.txt')
raw = f.read()
print "got it!"
print type(raw)
ucoderaw=raw.decode('utf-8')
print ucoderaw
tokens = nltk.word_tokenize(ucoderaw)
print type(tokens)
words = [w.lower() for w in tokens]
print type(words)
vocab = sorted(set(words))
print "Tokens"
The document contains a french text:
J'ai lieu de croire que Mr. de Voltaire ne sera pas fâché de voir que son Manuscrit, qu'il a intitulé Abrégé de l'Histoire Universelle depuis Charlemagne jusqu'à Charles-Quint, et qu'il dit être entre les mains de trente Particuliers, soit tombé entre les miennes. Il sait qu'il m'en avait flatté dès l'année 1742, à l'occasion de son Siècle de Louis XIV, auquel je ne renonçai en 1750, que parce qu'il me dit alors à Postdam, où j'étais, qu'il l'imprimait lui-même à ses propres dépens. Ainsi il ne s'agit ici que de dire comment cet Abrégé m'est tombé entre les mains, le voici.
À mon retour de Paris, en Juin de cette année 1753, je m'arrêtai à Bruxelles, où j'eus l'honneur de voir une Personne de mérite, qui en étant le possesseur me le fit voir, et m'en fit aussi tout l'éloge imaginable, de même que l'histoire du Manuscrit, et de tout ce qui s'était passé à l'occasion d'un Avertissement qui se trouve inséré dans le second Volume du mois de Juin 1752 du Mercure de France, et répété dans l'Épilogueur du 31 Juillet de la même année, avec la Réponse que l'on y a faite, et qui se trouve dans le même Épilogueur du 7 Août suivant: toutes choses inutiles à relever ici, mais qui m'ont ensuite déterminé à acheter des mains de ce Galant-Homme le Manuscrit après avoir été offert à l'Auteur, bien persuadé d'ailleurs qu'il était effectivement de Mr. de Voltaire; son génie, son style, et surtout son orthographe s'y trouvant partout. J'ai changé cette dernière, parce qu'il est notoire que le Public a toutes les peines du monde à s'y accoutumer; et c'est ce que l'Auteur est prié de vouloir bien excuser.[1]
Je dois encore faire remarquer que par la dernière période de ce Livre, il paraît qu'elle fait la clôture de cet Abrégé, qui finit à Charles VII Roi de France, au lieu que l'Auteur la promet par son Titre jusqu'à l'Empereur Charles-Quint. Ainsi il est à présumer que ce qui devrait suivre, est cette partie différente d'Histoire qui concerne les Arts, qu'il serait à souhaiter que Mr. de Voltaire retrouvât, ou, pour mieux dire, qu'il voulût bien refaire, et la pousser jusqu'au Siècle de Louis XIV, afin de remplir son plan, et de nous donner ainsi une suite d'Histoire qui ferait grand plaisir au Public et aux Libraires.
When I attempt to tokenise that text using tokens = nltk.word_tokenize(ucoderaw)
and then subsequently print out the tokens using sorted(set(words))
I get output with broken utf-8 encoding:
u'autant', u'author', u'autres', u'aux', u'available', u'avait', u'avant', u'avec', u'avertissement', u'avoir', u'avons', u'away', u'ayant', u'barbare', u'beaucoup', u'biblioth\xe8que', u'bien', u'bnf/gallica', u'bornais', u'bruxelles', u'but', u'by', u"c'est", u'capet', u'carri\xe8re', u'ce', u'cela', u'ces', u'cet', u'cette', u'ceux', u'chang\xe9', u'chaos', u'character', u'charger', u'charlemagne', u'charlequint', u'charles-quint_', u'chartes', u'chez', u'chine', u'choses', u'chronologie', u'chronologiques', u'chr\xe9tienne', u'cl\xf4ture'
where the correct output should include accents i.e. bibliothèque and not biblioth\xe8que
I've been trying to figure out how to fix this, short of saving the output to a file and writing another program to replace \xe8 with è and so on and so forth.
Is there a simpler method?
EDIT: Not the cleanest solution, however I found that by tokenising and then saving that output to a file with the correct encoding I do (largely get the output required):
#python 2.7
#-*- coding: utf-8 -*-
from __future__ import division
import nltk, re, pprint
f= open('test.txt')
raw = f.read()
print "got it!"
#print raw
print type(raw)
#encode as utf8 before moving on.
ucoderaw=raw.decode('utf-8')
tokens = nltk.word_tokenize(ucoderaw)
print type(tokens)
words = [w.lower() for w in tokens]
print type(words)
vocab = sorted(set(words))
print "encoded raw input is"
print ucoderaw
# GET TOKENS
print vocab
#write to file with correct encoding to "fix" the problem
output_file = open('output.txt', 'w')
print len(vocab)
for words in vocab:
output_file.write(words.encode('utf-8') + "\n")
python3=) Longer answer: don't useopen, useio.open('filename.txt', 'r', encoding='utf8')Better answer: see nedbatchelder.com/text/unipain.html and then still usepython3. - alvas