Frage

Ich habe eine Unicode-Zeichenfolge in Python und möchte alle Akzente (diakritische Zeichen) entfernen.

Ich habe im Web eine elegante Möglichkeit 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 Zeichen mit Akzent zu ihrem Gegenstück ohne Akzent vermeiden.

War es hilfreich?

Lösung

Unidecode ist die richtige Antwort für diese. Es transliteriert alle Unicode-String in die nächste mögliche Darstellung in ASCII-Text.

Beispiel:

accented_string = u'Málaga'
# accented_string is of type 'unicode'
import unidecode
unaccented_string = unidecode.unidecode(accented_string)
# unaccented_string contains 'Malaga'and is of type 'str'

Andere Tipps

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 auf griechische Buchstaben, auch:

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

Die Zeichenkategorie "Mn" steht für Nonspacing_Mark, die unicodedata ähnlich ist .combining in MiniQuark Antwort (ich glaube nicht, von unicodedata.combining, aber es ist wahrscheinlich die bessere Lösung, weil es deutlicher ist).

Und bedenken Sie können diese Manipulationen deutlich die Bedeutung des Textes ändern. Akzente, Umlaute etc. nicht "Dekoration".

Ich habe gerade diese Antwort auf dem Web:

import unicodedata

def remove_accents(input_str):
    nfkd_form = unicodedata.normalize('NFKD', input_str)
    only_ascii = nfkd_form.encode('ASCII', 'ignore')
    return only_ascii

Es funktioniert gut (für Französisch, zum Beispiel), aber ich denke, dass der zweite Schritt (die Akzente zu entfernen) besser behandelt werden, um die Nicht-ASCII-Zeichen als fallen, da dies für einige Sprachen (Griechisch, zum Beispiel) scheitern . Die beste Lösung wäre wahrscheinlich explizit die Unicode-Zeichen zu entfernen, die als diakritische Zeichen markiert sind.

Bearbeiten : Das ist der Trick:

import unicodedata

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

unicodedata.combining(c) gibt true zurück, wenn das Zeichen c mit dem vorhergehenden Zeichen kombiniert werden kann, das heißt vor allem, wenn es ein diakritischen.

Edit 2 : remove_accents erwartet einen Unicode string, keine Byte-String. Wenn Sie ein Byte-String haben, dann müssen Sie es in ein Unicode-String wie folgt entschlüsseln:

encoding = "utf-8" # or iso-8859-15, or cp1252, or whatever encoding you use
byte_string = b"café"  # or simply "café" before python 3.
unicode_string = byte_string.decode(encoding)

Eigentlich arbeite ich an Projekt kompatibel Python 2.6, 2.7 und 3.4 und ich habe IDs von freien Benutzereinträgen erstellen.

Dank dir, ich habe 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'

Diese Griffe nicht nur Akzente, sondern auch "strokes" (wie in ø etc.):

import unicodedata as ud

def rmdiacritics(char):
    '''
    Return the base character of char, by "removing" any
    diacritics like accents or curls and strokes and the like.
    '''
    desc = ud.name(unicode(char))
    cutoff = desc.find(' WITH ')
    if cutoff != -1:
        desc = desc[:cutoff]
    return ud.lookup(desc)

Dies ist die eleganteste Art, wie ich mich vorstellen kann (und es wird von alexis in einem Kommentar auf dieser Seite erwähnt), obwohl ich nicht glaube, es in der Tat sehr elegant ist.

Es gibt noch Sonderzeichen, die durch diesen nicht behandelt werden, wie zum Beispiel gedreht und invertiert Buchstaben, da dessen Unicode-Name nicht enthält ‚mit‘. Es hängt davon ab, was Sie ohnehin tun wollen. Ich brauchte manchmal Akzent für das Erreichen Wörterbuch-Sortierreihenfolge Strippen.

Als Antwort auf @ MiniQuark Antwort:

Ich habe versucht, in einer CSV-Datei zu lesen, die halb Französisch waren (mit Akzenten) und auch die einige Saiten würden schließlich ganze Zahlen und Schwimmer werden. Als Test habe ich eine test.txt Datei, die wie folgt aussah:

  

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

Ich musste umfassen Linien 2 und 3, um es (was ich in einem Python-Ticket gefunden) zu arbeiten, sowie zu integrieren @ Jabba Kommentar:

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)

gensim.utils.deaccent(text) aus Gensim – Themenmodellierung 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 Unicode.

Nicht, dass die vorgeschlagene Lösung mit Unicodedaten Normalerweise werden Akzente nur in einigen Zeichen entfernt (z. B.es wendet sich 'ł' hinein '', anstatt in 'l').

Einige Sprachen haben diakritische Zeichen als Sprache Buchstaben und Akzent diakritische Zeichen kombinieren Akzent zu geben.

Ich denke, es sicherer ist ausdrücklich festgelegt, welche diactrics Sie entfernen lassen möchten:

def strip_accents(string, accents=('COMBINING ACUTE ACCENT', 'COMBINING GRAVE ACCENT', 'COMBINING TILDE')):
    accents = set(map(unicodedata.lookup, accents))
    chars = [c for c in unicodedata.normalize('NFD', string) if c not in accents]
    return unicodedata.normalize('NFC', ''.join(chars))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top