代码之家  ›  专栏  ›  技术社区  ›  mipadi

如何检查Python unicode字符串是否包含非西方字母?

  •  22
  • mipadi  · 技术社区  · 14 年前

    我有一个Python Unicode字符串。我想确保它只包含罗马字母表(A到Z)中的字母,以及欧洲字母表中常见的字母,例如,,,和。应该的 包含其他字母表中的字符(中文、日文、韩文、阿拉伯文、西里尔文、希伯来文等)。做这件事最好的方法是什么?

    目前我正在使用这段代码,但我不知道这是否是最好的方法:

    def only_roman_chars(s):
        try:
            s.encode("iso-8859-1")
            return True
        except UnicodeDecodeError:
            return False
    

    6 回复  |  直到 14 年前
        1
  •  42
  •   tzot    14 年前
    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
  •  31
  •   Eli    9 年前

    @tzot对此的最佳答案是很好的,但是我认为应该有一个适用于所有脚本的库。 So, I made one

    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
  •  1
  •   John Machin Santi    14 年前

    cp1252 而不是 iso-8859-1 cp1250 同样,这也会影响到东欧国家,如波兰、捷克共和国、斯洛伐克、罗马尼亚、斯洛文尼亚、匈牙利、克罗地亚等,这些国家的字母表是以拉丁语为基础的。其他cp125x包括土耳其语和马耳他语。。。

    你也可以考虑从西里尔语到拉丁语的转录;据我所知,有几种制度,其中一种可能得到万国邮政联盟的认可。

    我对你说的“我们的运输部门不想在标签上填上中国地址”有点好奇。。。三个问题:(1)你的意思是“X国的地址”还是“用X-ese字符写的地址”(2)你的系统打印标签不是更好吗(3) 如果您的测试失败,订单如何发货?

        4
  •  1
  •   dan04    14 年前

    检查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)
    
        5
  •  1
  •   Claude Vedovini    14 年前

    签入代码 django.template.defaultfilters.slugify

    import unicodedata
    value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
    

        6
  •  1
  •   Alexander Astashov    4 年前

    标准 string 包包含所有 Latin 信件, numbers symbols . 您可以从文本中删除这些值,如果还有任何内容,则不是拉丁字符。我做到了:

    In [1]: from string import printable                                                                                                                                                                           
    
    In [2]: def is_latin(text): 
       ...:     return not bool(set(text) - set(printable)) 
       ...:                                                                                                                                                                                                        
    
    In [3]: is_latin('Hradec Králové District,,Czech Republic,')                                                                                                                                                   
    Out[3]: False
    
    In [4]: is_latin('Hradec Krlov District,,Czech Republic,')                                                                                                                                                     
    Out[4]: True
    

    我没有办法检查所有非拉丁字符,如果有人可以这样做,请让我知道。谢谢。

        7
  •  0
  •   Nikhil    14 年前

    from django.template.defaultfilters import slugify 
    
    def justroman(s):
      return len(slugify(s)) == len(s)
    
        8
  •  0
  •   Dustin Michels    3 年前

    import unicodedata as ud
    
    def is_latin(word):
        return all(['LATIN' in ud.name(c) for c in word])