Подтвердить что ты не робот

Как я могу проверить, содержит ли строка юникода 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 есть способ обрабатывать такие строки, я могу использовать эту функциональность - я не сталкивался с чем-либо подобным, однако.)

4b9b3361

Ответ 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)