Mam w Pythonie ciąg znaków Unicode i chciałbym usunąć wszystkie akcenty (znaki diakrytyczne).
Znalazłem w sieci elegancki sposób na zrobienie tego w Javie:
- przekonwertować ciąg Unicode na jego długą znormalizowaną formę (z osobnym znakiem dla liter i znaków diakrytycznych)
- usuń wszystkie znaki, których typ Unicode jest „diakrytyczny”.
Czy muszę instalować bibliotekę, taką jak pyICU, czy jest to możliwe tylko przy użyciu standardowej biblioteki python? A co z python 3?
Ważna uwaga: chciałbym uniknąć kodu z wyraźnym odwzorowaniem znaków akcentowanych na ich nieakcentowany odpowiednik.
python
python-3.x
unicode
python-2.x
diacritics
MiniQuark
źródło
źródło
unidecode
zastępuje°
siędeg
. To coś więcej niż tylko usuwanie akcentów.Co powiesz na to:
Działa to również na litery greckie:
Kategoria charakter „Mn” oznacza
Nonspacing_Mark
, która jest podobna do unicodedata.combining w odpowiedzi MiniQuark za (nie myśleć unicodedata.combining, ale prawdopodobnie jest lepszym rozwiązaniem, ponieważ jest to bardziej wyraźne).I pamiętaj, że te manipulacje mogą znacznie zmienić znaczenie tekstu. Akcenty, umlauty itp. Nie są „dekoracją”.
źródło
unicodedata.name
, albo załamać się i użyć podobnego do stołu - który i tak potrzebujesz greckich liter (Α to po prostu „GRECKA LITERA LITEROWA ALFA”).A
. Jeśli nie chcesz, nie rób tego, ale w obu przypadkach zastępujesz łaciński (prawie) podobny wygląd.ß
nass
przykład nie przekształca się w ascii . Nadal używałbym,unidecode
aby uniknąć wypadków.Właśnie znalazłem tę odpowiedź w Internecie:
Działa to dobrze (na przykład w języku francuskim), ale myślę, że drugim krokiem (usunięcie akcentów) można by się lepiej zająć niż upuszczenie znaków spoza ASCII, ponieważ nie powiedzie się to w niektórych językach (na przykład po grecku). Najlepszym rozwiązaniem byłoby prawdopodobnie jawne usunięcie znaków Unicode oznaczonych jako znaki diakrytyczne.
Edycja : to załatwia sprawę:
unicodedata.combining(c)
zwróci true, jeśli znakc
można połączyć z poprzednim, to znaczy, jeśli jest to znak diakrytyczny.Edycja 2 :
remove_accents
oczekuje ciągu znaków Unicode , a nie ciągu bajtów. Jeśli masz ciąg bajtów, musisz go zdekodować na ciąg znaków Unicode:źródło
nkfd_form = unicodedata.normalize('NFKD', unicode(input_str, 'utf8'))
, 'utf8'
jest „siatką bezpieczeństwa” potrzebną, jeśli testujesz dane wejściowe w terminalu (który domyślnie nie używa Unicode). Ale zwykle nie musisz go dodawać, ponieważ jeśli usuwasz akcenty,input_str
najprawdopodobniej jest to już utf8. Jednak nie zaszkodzi być bezpiecznym.remove_accents
zamiast zwykłego ciągu (u „é” zamiast „é”). Przekazałeś zwykły ciąg znakówremove_accents
, więc przy próbie konwersji łańcucha na ciąg znaków Unicodeascii
użyto domyślnego kodowania. To kodowanie nie obsługuje żadnego bajtu, którego wartość wynosi> 127. Kiedy wpiszesz „é” w swojej powłoce, twój system operacyjny zakodował to, prawdopodobnie za pomocą UTF-8 lub jakiegoś kodowania strony kodowej Windows, i które zawierało bajty> 127. Zmienię swoją funkcję, aby usunąć konwersję na Unicode: będzie bombardować wyraźniej, jeśli zostanie przekazany ciąg inny niż Unicode.Właściwie pracuję nad zgodnym z projektem Pythonem 2.6, 2.7 i 3.4 i muszę tworzyć identyfikatory z wolnych wpisów użytkowników.
Dzięki tobie stworzyłem tę funkcję, która działa cuda.
wynik:
źródło
text = unicode(text, 'utf-8')
. Obejściem tego było dodanieexcept TypeError: pass
Dotyczy to nie tylko akcentów, ale także „pociągnięć” (jak w ø itp.):
Jest to najbardziej elegancki sposób, jaki mogę wymyślić (o czym wspomniała Alexis w komentarzu na tej stronie), chociaż nie sądzę, aby był on naprawdę elegancki. W rzeczywistości jest to raczej hack, jak wskazano w komentarzach, ponieważ nazwy Unicode są - tak naprawdę tylko nazwami, nie dają żadnej gwarancji, że będą spójne lub coś w tym rodzaju.
Nadal istnieją specjalne litery, które nie są przez to obsługiwane, takie jak litery odwrócone i odwrócone, ponieważ ich nazwa Unicode nie zawiera „Z”. To i tak zależy od tego, co chcesz zrobić. Czasami potrzebowałem usuwania akcentów, aby uzyskać porządek sortowania w słowniku.
EDYTUJ NOTATKĘ:
Uwzględniono sugestie z komentarzy (obsługa błędów wyszukiwania, kod Python-3).
źródło
unicode
wywołania funkcji z Pythonem 3? Myślę, że ściślejsze wyrażenie regularne zamiast tegofind
uniknęłoby wszystkich problemów wymienionych w powyższym komentarzu, a także zapamiętywanie pomogłoby w wydajności, gdy jest to krytyczna ścieżka kodu.unicode
typecast nie jest już właściwe w Pythonie 3. W każdym przypadku, w moim doświadczeniu nie ma uniwersalnego, eleganckie rozwiązanie tego problemu. W zależności od aplikacji każde podejście ma swoje zalety i wady. Dobrze prosperujące narzędzia, takie jakunidecode
oparte na ręcznie wykonanych stołach. Niektóre zasoby (tabele, algorytmy) są dostarczane przez Unicode, np. do zestawienia.W odpowiedzi na odpowiedź @ MiniQuark:
Próbowałem odczytać plik csv, który był w połowie francuski (zawierający akcenty), a także niektóre ciągi, które ostatecznie stałyby się liczbami całkowitymi i liczbami zmiennoprzecinkowymi. W ramach testu utworzyłem
test.txt
plik, który wyglądał tak:Musiałem dołączyć wiersze
2
i3
sprawić, by zadziałało (co znalazłem w bilecie Pythona), a także dołączyć komentarz @ Jabba:Wynik:
(Uwaga: korzystam z Mac OS X 10.8.4 i używam Python 2.7.3)
źródło
remove_accents
miał usunąć akcenty z ciągu znaków Unicode. W przypadku przekazania ciągu bajtów, próbuje przekonwertować go na ciąg znaków Unicode za pomocąunicode(input_str)
. Używa domyślnego kodowania Pythona, którym jest „ascii”. Ponieważ plik jest zakodowany za pomocą UTF-8, to się nie powiedzie. Linie 2 i 3 zmieniają domyślne kodowanie Pythona na UTF-8, więc działa, jak się dowiedziałeś. Inną opcją jest przekazanieremove_accents
ciągu znaków Unicode: usuń linie 2 i 3, aw ostatnim wierszu zastąpelement
jeelement.decode("utf-8")
. Testowałem: działa. Zaktualizuję moją odpowiedź, aby była jaśniejsza.iso-8859-1
którym niestety nie mogę pracować z tą funkcją!)reload(sys); sys.setdefaultencoding("utf-8")
to wątpliwy hack czasami zalecany dla systemów Windows; szczegółowe informacje można znaleźć na stronie stackoverflow.com/questions/28657010/ ...gensim.utils.deaccent (tekst) z Gensim - modelowanie tematów dla ludzi :
Innym rozwiązaniem jest kod unidecode .
Zauważ, że sugerowane rozwiązanie z unicodedata zazwyczaj usuwa akcenty tylko w niektórych postaciach (np. Zmienia się
'ł'
w''
, a nie w'l'
).źródło
deaccent
nadal dajeł
zamiastl
.NumPy
iSciPy
usuwać akcentów.Niektóre języki łączą znaki diakrytyczne jako litery języka i znaki diakrytyczne z akcentem, aby określić akcent.
Myślę, że bezpieczniej jest wyraźnie określić, jakie diactrics chcesz usunąć:
źródło