Eu tenho uma string Unicode em Python e gostaria de remover todos os acentos (diacríticos).
Encontrei na Web uma maneira elegante de fazer isso em Java:
- converta a cadeia Unicode em sua forma normalizada longa (com um caractere separado para letras e diacríticos)
- remova todos os caracteres cujo tipo Unicode é "diacrítico".
Preciso instalar uma biblioteca como pyICU ou isso é possível apenas com a biblioteca padrão python? E o python 3?
Nota importante: eu gostaria de evitar código com um mapeamento explícito de caracteres acentuados para o seu equivalente não acentuado.
python
python-3.x
unicode
python-2.x
diacritics
MiniQuark
fonte
fonte
unidecode
substitui°
pordeg
. Faz mais do que apenas remover acentos.Que tal agora:
Isso funciona também com letras gregas:
A categoria de personagem "Mn" significa
Nonspacing_Mark
, que é semelhante a unicodedata.combining na resposta do MiniQuark (eu não pensei em unicodedata.combining, mas provavelmente é a melhor solução, porque é mais explícita).E lembre-se, essas manipulações podem alterar significativamente o significado do texto. Sotaques, trema etc. não são "decoração".
fonte
unicodedata.name
ou dividir e usar uma tabela parecida - que você precisaria para as letras gregas de qualquer maneira (Α é apenas "ALFA DE LETRAS DE CAPITAL GREEK").A
. Se não quiser, não faça, mas nos dois casos você substitui um latino (quase) parecido.ß
em asciiss
no exemplo. Eu ainda usariaunidecode
para evitar acidentes.Acabei de encontrar esta resposta na Web:
Funciona bem (em francês, por exemplo), mas acho que o segundo passo (remover os acentos) poderia ser melhor do que soltar os caracteres não-ASCII, porque isso falhará em alguns idiomas (grego, por exemplo). A melhor solução provavelmente seria remover explicitamente os caracteres unicode marcados como sendo diacríticos.
Edit : isso faz o truque:
unicodedata.combining(c)
retornará true se o caracterec
puder ser combinado com o caractere anterior, ou seja, se for um diacrítico.Edição 2 :
remove_accents
espera uma sequência unicode , não uma sequência de bytes. Se você tiver uma cadeia de bytes, decodifique-a em uma cadeia unicode como esta:fonte
nkfd_form = unicodedata.normalize('NFKD', unicode(input_str, 'utf8'))
, 'utf8'
é uma "rede de segurança" necessária se você estiver testando a entrada no terminal (que por padrão não usa unicode). Mas geralmente você não precisa adicioná-lo, pois se você estiver removendo sotaques,input_str
provavelmente já será utf8. Não faz mal estar seguro, no entanto.remove_accents
vez de uma string regular (u "é" em vez de "é"). Você passou uma sequência regular pararemove_accents
, portanto, ao tentar converter sua sequência em uma sequência unicode, aascii
codificação padrão foi usada. Essa codificação não suporta nenhum byte cujo valor seja> 127. Quando você digitou "é" no seu shell, seu sistema operacional codificou isso, provavelmente com UTF-8 ou alguma codificação da Página de Código do Windows, e isso incluía bytes> 127. Mudarei minha função para remover a conversão para unicode: ela bombardeará mais claramente se uma string não unicode for passada.Na verdade, eu trabalho no projeto compatível com python 2.6, 2.7 e 3.4 e tenho que criar IDs a partir de entradas gratuitas do usuário.
Graças a você, eu criei esta função que faz maravilhas.
resultado:
fonte
text = unicode(text, 'utf-8')
. Uma solução alternativa para isso era adicionarexcept TypeError: pass
Isso lida não apenas com detalhes, mas também com "traços" (como em ø etc.):
Esta é a maneira mais elegante em que consigo pensar (e foi mencionada por alexis em um comentário nesta página), embora eu não ache que seja muito elegante. De fato, é mais um truque, como apontado nos comentários, já que os nomes Unicode são - na verdade, apenas nomes, eles não dão garantia de consistência nem nada.
Ainda existem letras especiais que não são manipuladas por isso, como letras viradas e invertidas, pois o nome do unicode não contém 'WITH'. Depende do que você deseja fazer de qualquer maneira. Às vezes, eu precisava de remoção de sotaque para obter a ordem de classificação do dicionário.
EDITAR NOTA:
Sugestões incorporadas dos comentários (manipulação de erros de pesquisa, código Python-3).
fonte
unicode
chamada de função lá com python 3? Eu acho que uma expressão regular mais rigorosa no lugar defind
evitaria todos os problemas mencionados no comentário acima e também a memorização ajudaria o desempenho quando for um caminho de código crítico.unicode
typecast não é mais apropriado no Python 3. De qualquer forma, na minha experiência, não há uma solução universal e elegante para esse problema. Dependendo da aplicação, qualquer abordagem tem seus prós e contras. Ferramentas de qualidade próspera, comounidecode
são baseadas em tabelas artesanais. Alguns recursos (tabelas, algoritmos) são fornecidos pelo Unicode, por exemplo. para agrupamento.Em resposta à resposta da @ MiniQuark:
Eu estava tentando ler um arquivo CSV que era meio francês (contendo acentos) e também algumas seqüências que acabariam se tornando números inteiros e flutuantes. Como teste, criei um
test.txt
arquivo parecido com este:Eu tive que incluir linhas
2
e3
fazê-lo funcionar (que encontrei em um ticket em python), além de incorporar o comentário de @ Jabba:O resultado:
(Nota: estou no Mac OS X 10.8.4 e usando o Python 2.7.3)
fonte
remove_accents
foi criado para remover acentos de uma string unicode. Caso tenha passado uma sequência de bytes, ele tenta convertê-la em uma sequência unicodeunicode(input_str)
. Isso usa a codificação padrão do python, que é "ascii". Como seu arquivo é codificado com UTF-8, isso falhará. As linhas 2 e 3 alteram a codificação padrão do python para UTF-8, para que funcione como você descobriu. Outra opção é passarremove_accents
uma string unicode: remova as linhas 2 e 3 e, na última linha, substituaelement
porelement.decode("utf-8")
. Eu testei: funciona. Vou atualizar minha resposta para deixar isso mais claro.iso-8859-1
, que eu não posso começar a trabalhar com esta função, infelizmente!)reload(sys); sys.setdefaultencoding("utf-8")
é um hack duvidoso às vezes recomendado para sistemas Windows; consulte stackoverflow.com/questions/28657010/… para obter detalhes.gensim.utils.deaccent (texto) de Gensim - modelagem de tópicos para humanos :
Outra solução é unidecode .
Observe que a solução sugerida com dados unicoded normalmente remove acentos apenas em alguns caracteres (por exemplo, se transforma
'ł'
em''
, e não em'l'
).fonte
deaccent
ainda dá emł
vez del
.NumPy
eSciPy
remover os acentos.Alguns idiomas combinam diacríticos como letras de idioma e diacríticos de acento para especificar o acento.
Eu acho que é mais seguro especificar explicitamente quais diátricas você deseja remover:
fonte