Gdzie jest „najlepszy ASCII dla tej bazy danych Unicode” w Pythonie?

85

Mam trochę tekstu, który używa interpunkcji Unicode, jak lewy podwójny cudzysłów, prawy pojedynczy cudzysłów jako apostrof i tak dalej, i potrzebuję go w ASCII. Czy Python ma bazę danych tych znaków z oczywistymi substytutami ASCII, więc mogę zrobić coś lepszego niż zamienianie ich wszystkich na "?" ?

joeforker
źródło
21
Jesteś odważnym wojownikiem. Unicode to arcynemezis Pythona.
David Berger
2
Osoby, które mogą to znaleźć, mogą być zainteresowane Jaki jest najlepszy sposób usuwania akcentów w ciągu znaków Unicode w języku Python?
Martin Thoma

Odpowiedzi:

89

Unidecode wygląda na kompletne rozwiązanie. Konwertuje fantazyjne cytaty na cudzysłowy ascii, akcentowane znaki łacińskie na bez akcentów, a nawet próbuje transliteracji radzić sobie ze znakami, które nie mają odpowiedników ASCII. W ten sposób Twoi użytkownicy nie muszą widzieć wielu? kiedy trzeba było przekazać ich tekst przez starszy 7-bitowy system ascii.

>>> from unidecode import unidecode
>>> print unidecode(u"\u5317\u4EB0")
Bei Jing 

http://www.tablix.org/~avian/blog/archives/2009/01/unicode_transliteration_in_python/

joeforker
źródło
3
Hm ... niemieckie umlauty są konwertowane na swój podstawowy charakter zamiast np. Ö = oe, ä = ae itp.
ThiefMaster
4
@ThiefMaster czy te odpowiedniki są prawdziwe we wszystkich językach? Może Unidecode wybiera najniższy wspólny mianownik.
Mark Ransom
Unidecode z pewnością wybiera rozwiązanie niezależne od języka. W przypadku rozwiązania zorientowanego na język niemiecki należy przekonwertować odpowiednie znaki ręcznie ( s/ö/oe/itp.) Przed wyczyszczeniem pozostałych za pomocą unidecode.
Alexis
4
Rzeczywiście, w fińskim na przykład, podczas gdy ä -> a, ö -> ojest wręcz źle, to jest jeszcze korzystniejsze aeioe
Antti Haapala
25

W mojej pierwotnej odpowiedzi również zasugerowałem unicodedata.normalize. Jednak postanowiłem to przetestować i okazuje się, że nie działa w cudzysłowie Unicode. Wykonuje dobrą robotę tłumacząc akcentowane znaki Unicode, więc domyślam się, że unicodedata.normalizejest zaimplementowana za pomocą unicode.decompositionfunkcji, co prowadzi mnie do przekonania, że ​​prawdopodobnie obsługuje tylko znaki Unicode, które są kombinacją litery i znaku diakrytycznego, ale tak naprawdę nie jestem ekspert od specyfikacji Unicode, więc mógłbym po prostu być pełen gorącego powietrza ...

W każdym razie możesz użyć unicode.translatezamiast tego do czynienia ze znakami interpunkcyjnymi. translateMetoda bierze słownika porządkowych Unicode porządkowych Unicode, dzięki czemu można stworzyć mapowanie, które przekłada Unicode tylko interpunkcyjnych ASCII kompatybilny interpunkcji:

'Maps left and right single and double quotation marks'
'into ASCII single and double quotation marks'
>>> punctuation = { 0x2018:0x27, 0x2019:0x27, 0x201C:0x22, 0x201D:0x22 }
>>> teststring = u'\u201Chello, world!\u201D'
>>> teststring.translate(punctuation).encode('ascii', 'ignore')
'"hello, world!"'

W razie potrzeby możesz dodać więcej mapowań interpunkcyjnych, ale nie sądzę, że musisz koniecznie martwić się obsługą każdego pojedynczego znaku interpunkcyjnego Unicode. Jeśli nie trzeba akcentami uchwyt i innych znaków diakrytycznych, nadal można używać unicodedata.normalizedo czynienia z tymi postaciami.

Mike Spross
źródło
21

Interesujące pytanie.

Google pomogło mi znaleźć tę stronę, która opisuje użycie modułu unicodedata w następujący sposób:

import unicodedata
unicodedata.normalize('NFKD', title).encode('ascii','ignore')
sztaluga
źródło
3

Istnieje dodatkowa dyskusja na ten temat pod adresem http://code.activestate.com/recipes/251871/, który zawiera rozwiązanie NFKD i kilka sposobów wykonywania tabeli konwersji, na przykład ± => +/- i inne znaki niebędące literami.

Andrew Dalke
źródło