Как я могу проверить, содержит ли строка юникода Python незападные буквы?
У меня есть строка Unicode Python. Я хочу убедиться, что он содержит только буквы из латинского алфавита (от A до Z), а также буквы, обычно встречающиеся в европейских алфавитах, такие как ß, ü, ø, é, à и î. Он не должен содержать символы из других алфавитов (китайский, японский, корейский, арабский, кириллический, иврит и т.д.). Какой лучший способ сделать это?
В настоящее время я использую этот бит кода, но я не знаю, лучший ли он:
def only_roman_chars(s):
try:
s.encode("iso-8859-1")
return True
except UnicodeDecodeError:
return False
(Я использую Python 2.5.Я также делаю это в Django, поэтому, если в структуре Django есть способ обрабатывать такие строки, я могу использовать эту функциональность - я не сталкивался с чем-либо подобным, однако.)
Ответы
Ответ 1
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
Ответ 2
Самый верный ответ на этот вопрос с помощью @tzot замечательный, но IMO там действительно должна быть библиотека для этого, которая работает для всех скриптов. Итак, я сделал один из них (в основном на основе этого ответа).
pip install alphabet-detector
а затем используйте его напрямую:
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
Кроме того, несколько удобных методов для основных языков:
ad.is_cyrillic(u"Поиск") #True
ad.is_latin(u"howdy") #True
ad.is_cjk(u"hi") #False
ad.is_cjk(u'汉字') #True
Ответ 3
За то, что вы говорите, вы хотите сделать, ваш подход прав. Если вы работаете в Windows, я предлагаю использовать cp1252
вместо iso-8859-1
. Вы также можете также позволить cp1250
- это заберет восточноевропейские страны, такие как Польша, Чехия, Словакия, Румыния, Словения, Венгрия, Хорватия и т.д., Где алфавит является латинским. Другие cp125x будут включать в себя турецкий и мальтийский...
Вам также может понравиться транскрипция с кириллицы на латынь; насколько я знаю, существует несколько систем, один из которых может быть одобрен ВПС (Всемирный почтовый союз).
Я немного заинтригован вашим комментарием: "Наш отдел доставки не хочет заполнять ярлыки, например, китайскими адресами"... три вопроса: (1) вы имеете в виду "адреса в стране X" "или" адреса, написанные на символах X-ese "(2), было бы лучше, если бы ваша система печатала этикетки? (3) как заказ отправляется, если он не прошел тест?
Ответ 4
проверьте код в django.template.defaultfilters.slugify
import unicodedata
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
- это то, что вы ищете, вы можете сравнить полученную строку с оригинальным
Ответ 5
Проверка на ISO-8559-1 пропустит разумные западные символы, такие как "œ" и "€". Решение зависит от того, как вы определяете "западный", и как вы хотите обрабатывать не-буквы. Здесь один подход:
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)
Ответ 6
Может быть, это произойдет, если вы пользователь django?
from django.template.defaultfilters import slugify
def justroman(s):
return len(slugify(s)) == len(s)