如何检查Python unicode字符串是否包含非西方字母?
我有一个Python Unicode字符串。我想确保它只包含罗马字母表中的字母(A到Z),以及欧洲字母表中常见的字母,如ß、ü、ø、é、á和î。它不应包含来自其他字母表(汉语、日语、韩语、阿拉伯语、西里尔语、希伯来语等)的字符。做这件事最好的方法是什么 目前我正在使用这段代码,但我不知道这是否是最好的方法:如何检查Python unicode字符串是否包含非西方字母?,python,django,unicode,Python,Django,Unicode,我有一个Python Unicode字符串。我想确保它只包含罗马字母表中的字母(A到Z),以及欧洲字母表中常见的字母,如ß、ü、ø、é、á和î。它不应包含来自其他字母表(汉语、日语、韩语、阿拉伯语、西里尔语、希伯来语等)的字符。做这件事最好的方法是什么 目前我正在使用这段代码,但我不知道这是否是最好的方法: def only_roman_chars(s): try: s.encode("iso-8859-1") return True except
def only_roman_chars(s):
try:
s.encode("iso-8859-1")
return True
except UnicodeDecodeError:
return False
(我正在使用Python2.5。我也在Django中这样做,因此如果Django框架碰巧有一种处理此类字符串的方法,我可以使用该功能——但是我没有遇到类似的情况。)检查
Django.template.defaultfilters.slugify中的代码
import unicodedata
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
就是您要寻找的,然后您可以将结果字符串与原始字符串进行比较对于您所说的您想要做的事情,您的方法是正确的。如果您在Windows上运行,我建议使用cp1252
而不是iso-8859-1
。您还可以允许cp1250
——这将包括波兰、捷克共和国、斯洛伐克、罗马尼亚、斯洛文尼亚、匈牙利、克罗地亚等东欧国家,这些国家的字母表是以拉丁语为基础的。其他cp125x将包括土耳其语和马耳他语
你也可以考虑从西里尔到拉丁语的转录;据我所知,有几种系统,其中一种可能得到万国邮政联盟(万国邮政联盟)的认可
我对你的评论有点好奇,“我们的运输部门不想在标签上填上,例如,中文地址”。。。三个问题:(1)您的意思是“X国的地址”还是“用X-ese字符书写的地址”(2)您的系统打印标签不是更好吗?(3) 如果订单未通过测试,如何发货?检查ISO-8559-1将丢失合理的西文字符,如“œ”和“欧元”。解决方案取决于您如何定义“Western”,以及您希望如何处理非字母。这里有一种方法:
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)
导入Unicode数据
def是允许的字符(字符):
cat=unicodedata.category(char)[0]
如果cat='L':#字母
返回Unicode数据中的“拉丁语”。名称(字符“”).split()
elif cat=='N':#编号
#只允许数字0-数字9
返回“0”如果您是django用户,这是否可以
from django.template.defaultfilters import slugify
def justroman(s):
return len(slugify(s)) == len(s)
@tzot对此的最佳答案非常好,但在我看来,应该有一个适用于所有脚本的库。(主要基于这个答案)
然后直接使用它:
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
标准的字符串
包包含所有拉丁字母
数字
和符号
。您可以从文本中删除这些值,如果还有剩余内容,则不是拉丁字符。我做到了:
[1]中的:从字符串导入可打印
在[2]中,def是拉丁语(文本):
…:返回非布尔值(集合(文本)-集合(可打印))
...:
在[3]中:是拉丁语(“捷克共和国赫拉代克·克拉洛夫区”)
Out[3]:False
在[4]中:是拉丁语(“捷克共和国赫拉德克洛夫区”)
Out[4]:正确
我没有办法检查所有非拉丁字符,如果有人能做到,请告诉我。谢谢。使用内置unicodedata库简单地回答tzot的问题,这似乎对我有用:
将Unicode数据导入为ud
def是拉丁语(单词):
返回全部(['LATIN'在ud.name(c)中表示word中的c])
过滤这些字符的目标是什么?我想不出一个好的理由来这样做,这不是代码库中其他地方出错的症状。过滤邮件地址。我们的运输部门不想在标签上填上中文地址。那你就不能用国家来代替吗?(否则,有趣的问题+1)不是真的。例如,有人可以选择“China”并仍然输入适当的地址。我不想将所有内容都变成小写或将空格转换为破折号,只需检查字符串是否包含不需要的字符。我改变了问题,以避免使用“过滤器”一词。(1)返回unicodedata.name(char),).startswith('LATIN')
应该足够了(2)记忆函数结果可能是个好主意,可以通过在备忘录中预加载通常的可疑点[-a-Za-z0-9,./')等来改进。(3)符号/标点比较宽(4)类别空间是否应替换为“\x20”?(1)后者(以X-ese字符书写的地址)。(2) 也许吧。现在,它没有。表单是web应用程序的一部分;数据被完全分流到另一个系统,该系统处理订单管理等。(3)表单未通过验证并提示用户输入适当的地址。我建议无论您是否在windows上,都不要使用cp125x,因为它与适当的标准化字符集和编码不兼容。它将合法的西文字符放在Unicode和ISO中保留的“C1”控制字符范围内。古老的“CP”代码页编码是有限字符集空间的一种解决方法,在所有现代代码中都应该避免使用。@StephenP:OP已经有Unicode字符串;我建议他认为角色的可能性很强。
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