xb1 - reemplazar ñ en python
¿Cómo puedo verificar si una cadena Unicode de Python contiene letras no occidentales? (6)
Tengo una cadena Python Unicode. Quiero asegurarme de que solo contiene letras del alfabeto romano (de la A a la Z), así como letras que se encuentran comúnmente en los alfabetos europeos, como ß, ü, ø, é, à y î. No debe contener caracteres de otros alfabetos (chino, japonés, coreano, árabe, cirílico, hebreo, etc.). ¿Cuál es la mejor manera de hacer esto?
Actualmente estoy usando este bit de código, pero no sé si es la mejor manera:
def only_roman_chars(s):
try:
s.encode("iso-8859-1")
return True
except UnicodeDecodeError:
return False
(Estoy usando Python 2.5. También estoy haciendo esto en Django, por lo que si el marco de trabajo de Django tiene una forma de manejar tales cadenas, puedo usar esa funcionalidad, sin embargo, no he encontrado nada de eso).
La comprobación de ISO-8559-1 perdería caracteres occidentales razonables como ''œ'' y ''€''. La solución depende de cómo defina "Occidental" y de cómo quiera manejar las no letras. Aquí hay un enfoque:
import unicodedata
def is_permitted_char(char):
cat = unicodedata.category(char)[0]
if cat == ''L'': # Letter
return ''LATIN'' in unicodedata.name(char, '''').split()
elif cat == ''N'': # Number
# Only DIGIT ZERO - DIGIT NINE are allowed
return ''0'' <= char <= ''9''
elif cat in (''S'', ''P'', ''Z''): # Symbol, Punctuation, or Space
return True
else:
return False
def is_valid(text):
return all(is_permitted_char(c) for c in text)
La respuesta principal a esto por @tzot es excelente, pero en mi opinión, debería haber una biblioteca para esto que funcione para todos los scripts. Entonces, hice uno (basado en gran medida en esa respuesta).
pip install alphabet-detector
y luego usarlo directamente:
from alphabet_detector import AlphabetDetector
ad = AlphabetDetector()
ad.only_alphabet_chars(u"ελληνικά means greek", "LATIN") #False
ad.only_alphabet_chars(u"ελληνικά", "GREEK") #True
ad.only_alphabet_chars(u''سماوي يدور'', ''ARABIC'')
ad.only_alphabet_chars(u''שלום'', ''HEBREW'')
ad.only_alphabet_chars(u"frappé", "LATIN") #True
ad.only_alphabet_chars(u"hôtel lœwe 67", "LATIN") #True
ad.only_alphabet_chars(u"det forårsaker første", "LATIN") #True
ad.only_alphabet_chars(u"Cyrillic and кириллический", "LATIN") #False
ad.only_alphabet_chars(u"кириллический", "CYRILLIC") #True
Además, algunos métodos de conveniencia para los idiomas principales:
ad.is_cyrillic(u"Поиск") #True
ad.is_latin(u"howdy") #True
ad.is_cjk(u"hi") #False
ad.is_cjk(u''汉字'') #True
Por lo que dice que quiere hacer, su enfoque es correcto. Si está ejecutando en Windows, sugeriría usar cp1252
lugar de iso-8859-1
. También puede permitir cp1250
- esto recogería países de Europa oriental como Polonia, República Checa, Eslovaquia, Rumania, Eslovenia, Hungría, Croacia, etc., donde el alfabeto está basado en el latín. Otros cp125x incluirían turco y maltés ...
También te puede interesar considerar la transcripción del cirílico al latín; Por lo que sé, hay varios sistemas, uno de los cuales puede ser avalado por la UPU (Universal Postal Union).
Estoy un poco intrigado por su comentario "Nuestro departamento de envíos no quiere tener que llenar etiquetas con, por ejemplo, direcciones chinas" ... tres preguntas: (1) quiere decir "direcciones en el país X" o " direcciones escritas en X-ese caracteres "(2) ¿no sería mejor para su sistema imprimir las etiquetas? (3) ¿cómo se envía el pedido si falla su prueba?
Tal vez esto hará si eres un usuario de django?
from django.template.defaultfilters import slugify
def justroman(s):
return len(slugify(s)) == len(s)
verifique el código en django.template.defaultfilters.slugify
import unicodedata
value = unicodedata.normalize(''NFKD'', value).encode(''ascii'', ''ignore'')
es lo que está buscando, luego puede comparar la cadena resultante con la original
import unicodedata as ud
latin_letters= {}
def is_latin(uchr):
try: return latin_letters[uchr]
except KeyError:
return latin_letters.setdefault(uchr, ''LATIN'' in ud.name(uchr))
def only_roman_chars(unistr):
return all(is_latin(uchr)
for uchr in unistr
if uchr.isalpha()) # isalpha suggested by John Machin
>>> only_roman_chars(u"ελληνικά means greek")
False
>>> only_roman_chars(u"frappé")
True
>>> only_roman_chars(u"hôtel lœwe")
True
>>> only_roman_chars(u"123 ångstrom ð áß")
True
>>> only_roman_chars(u"russian: гага")
False