Was ist der beste Weg, um Akzente in einer Python-Unicode-Zeichenkette zu entfernen?


Answers

Wie wäre es damit:

import unicodedata
def strip_accents(s):
   return ''.join(c for c in unicodedata.normalize('NFD', s)
                  if unicodedata.category(c) != 'Mn')

Dies funktioniert auch mit griechischen Buchstaben:

>>> strip_accents(u"A \u00c0 \u0394 \u038E")
u'A A \u0394 \u03a5'
>>> 

Die Zeichenkategorie "Mn" steht für Nonspacing_Mark , was in der Antwort von MiniQuark ähnlich ist wie unicodeata.combining (ich dachte nicht an unicodedata.combining, aber es ist wahrscheinlich die bessere Lösung, weil es expliziter ist).

Und bedenken Sie, diese Manipulationen können die Bedeutung des Textes erheblich verändern. Akzente, Umlaute etc. sind keine "Dekoration".

Question

Ich habe eine Unicode-Zeichenfolge in Python, und ich möchte alle Akzente (Diakritika) entfernen.

Ich habe im Web einen eleganten Weg gefunden, dies in Java zu tun:

  1. Konvertieren Sie die Unicode-Zeichenfolge in ihre lange normalisierte Form (mit einem separaten Zeichen für Buchstaben und diakritische Zeichen)
  2. Entfernen Sie alle Zeichen, deren Unicode-Typ "diakritisch" ist.

Muss ich eine Bibliothek wie pyICU installieren oder ist dies nur mit der Python-Standardbibliothek möglich? Und was ist mit Python 3?

Wichtiger Hinweis: Ich möchte Code mit einer expliziten Zuordnung von Akzentzeichen zu ihrem nicht akzentuierten Gegenstück vermeiden.




gensim.utils.deaccent(text) von Gensim - Thema Modellierung für Menschen :

deaccent("Šéf chomutovských komunistů dostal poštou bílý prášek") 'Sef chomutovskych komunistu dostal postou bily prasek'

Eine andere Lösung ist Unidecode .

Nicht, dass die vorgeschlagene Lösung mit UnicodeData typischerweise Akzente nur in einem bestimmten Zeichen entfernt (z. B. macht es 'ł' in '' statt in 'l' ).




Eigentlich arbeite ich an projektkompatiblen Python 2.6, 2.7 und 3.4 und ich muss IDs aus freien Benutzereinträgen erstellen.

Dank dir habe ich diese Funktion geschaffen, die Wunder wirkt.

import re
import unicodedata

def strip_accents(text):
    """
    Strip accents from input String.

    :param text: The input string.
    :type text: String.

    :returns: The processed String.
    :rtype: String.
    """
    try:
        text = unicode(text, 'utf-8')
    except (TypeError, NameError): # unicode is a default on python 3 
        pass
    text = unicodedata.normalize('NFD', text)
    text = text.encode('ascii', 'ignore')
    text = text.decode("utf-8")
    return str(text)

def text_to_id(text):
    """
    Convert input text to id.

    :param text: The input string.
    :type text: String.

    :returns: The processed String.
    :rtype: String.
    """
    text = strip_accents(text.lower())
    text = re.sub('[ ]+', '_', text)
    text = re.sub('[^0-9a-zA-Z_-]', '', text)
    return text

Ergebnis:

text_to_id("Montréal, über, 12.89, Mère, Françoise, noël, 889")
>>> 'montreal_uber_1289_mere_francoise_noel_889'



Als Antwort auf @ MiniQuarks Antwort:

Ich habe versucht, in einer csv-Datei zu lesen, die halb Französisch war (mit Akzenten) und auch einige Strings, die schließlich zu Integers und Floats werden würden. Als Test habe ich eine test.txt Datei erstellt, die wie test.txt :

Montréal, über, 12.89, Mère, Françoise, noël, 889

Ich musste Zeilen 2 und 3 einfügen, um es zum Laufen zu bringen (was ich in einem Python-Ticket gefunden habe), und auch @ Jabbas Kommentar einbeziehen:

import sys 
reload(sys) 
sys.setdefaultencoding("utf-8")
import csv
import unicodedata

def remove_accents(input_str):
    nkfd_form = unicodedata.normalize('NFKD', unicode(input_str))
    return u"".join([c for c in nkfd_form if not unicodedata.combining(c)])

with open('test.txt') as f:
    read = csv.reader(f)
    for row in read:
        for element in row:
            print remove_accents(element)

Das Ergebnis:

Montreal
uber
12.89
Mere
Francoise
noel
889

(Hinweis: Ich bin auf Mac OS X 10.8.4 und mit Python 2.7.3)




Related