找到两个字符串的图形相似性的距离度量

时间:2018-02-08 08:46:49

标签: python string

我没有运气找到这样的包,最好是在Python中。是否有一些库允许用户以图形方式比较两个字符串?

例如,如果使用я代替R,或者更糟糕的是,使用Α(大写字母,0x0391)代替A,混淆他们的字符串。

此类软件包的界面可能类似于

distance("Foo", "Bar")  # large distance
distance("Αяe", "Are")  # small distance

谢谢!

2 个答案:

答案 0 :(得分:5)

我不知道有这样做的套餐。但是,您可以使用homoglyph attack generator,Unicode联盟confusables等工具,IDN homograph attack上维基百科页面中的参考资料或其他此类资源建立自己的外观库,并根据它建立一个分数。

编辑:看起来好像Unicode人员编写了一个很棒的大型字符数据库,看起来很像。它可用here。如果我是你,我会构建一个脚本,将其读入Python字典,然后解析字符串以进行匹配。摘录如下:

FF4A ;  006A ;  MA  # ( j → j ) FULLWIDTH LATIN SMALL LETTER J → LATIN SMALL LETTER J # →ϳ→
2149 ;  006A ;  MA  # ( ⅉ → j ) DOUBLE-STRUCK ITALIC SMALL J → LATIN SMALL LETTER J # 
1D423 ; 006A ;  MA  # (  → j ) MATHEMATICAL BOLD SMALL J → LATIN SMALL LETTER J  # 
1D457 ; 006A ;  MA  # (  → j ) MATHEMATICAL ITALIC SMALL J → LATIN SMALL LETTER J  # 

答案 1 :(得分:0)

使用@Richard中提供的信息his answer,我想出了这个实现UTS#39的简短Python 3脚本:

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
  .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
  // offset, use "-00:00" when it's zero
  .appendOffset("+HH:MM", "-00:00")
  // create formatter, always work in UTC
  .toFormatter().withZone(ZoneOffset.UTC);
String dateStringToConvert = "2016-03-12T22:00:00.000-00:00";
Instant instant = fmt.parse(dateStringToConvert, Instant::from);
String result = fmt.format(instant);
System.out.println(result);

它假定文件"""Implement the simple algorithm laid out in UTS#39, paragraph 4 """ import csv import re import unicodedata comment_pattern = re.compile(r'\s*#.*$') def skip_comments(lines): """ A filter which skip/strip the comments and yield the rest of the lines :param lines: any object which we can iterate through such as a file object, list, tuple, or generator """ for line in lines: line = comment_pattern.sub('', line).strip() if line: yield line def normalize(s): return unicodedata.normalize("NFD", s) def to_unicode(code_point): return chr(int("0x" + code_point.lower(), 16)) def read_table(file_name): d = {} with open(file_name) as f: reader = csv.reader(skip_comments(f), delimiter=";") for row in reader: source = to_unicode(row[0]) prototypes = map(to_unicode, row[1].strip().split()) d[source] = ''.join(prototypes) return d TABLE = read_table("confusables.txt") def skeleton(s): s = normalize(s) s = ''.join(TABLE.get(c, c) for c in s) return normalize(s) def confusable(s1, s2): return skeleton(s1) == skeleton(s2) if __name__ == "__main__": for strings in [("Foo", "Bar"), ("Αяe", "Are"), ("j", "j")]: print(*strings) print("Equal:", strings[0] == strings[1]) print("Confusable:", confusable(*strings), "\n") 位于运行脚本的目录中。另外,我不得不删除该文件的第一个字节,因为它是一些奇怪的,不可打印的符号。

它只遵循第4段开头列出的简单算法,而不是4.1和4.2中列出的更复杂的整体和混合脚本混淆的案例。这是留给读者的练习。

请注意,unicode组不会将“я”和“R”视为可混淆,因此这将为这两个字符串返回confusables.txt