【问题标题】:How can I make 2 strings with the same word(s)/meaning, but with Unicode differences hash to the same id?如何使 2 个字符串具有相同的单词/含义,但 Unicode 差异散列到相同的 id?
【发布时间】:2021-02-23 02:30:36
【问题描述】:

对于我正在进行的网络抓取项目,我计划将实体存储在数据库中,其中它们的 ID 是其名称/标题的 md5 哈希。

但是,由于字符串中存在 Unicode,相同名称/标题的不同哈希值将存在

例如,“Kinesiology, Phys Ed\xa0and Recreation”的 md5 哈希值将不同于“Kinesiology, Phys Ed and Recreation”。

我尝试使用 Unicode 规范化,但哈希之间的差异仍然相同

import hashlib
import unicodedata


def generate_id(*args):
    """

    :param args: strings to be used to generate an id
    :return: md5 hash of the passed arguments
    """
    string = ''
    for arg in args:
        string += ' ' + arg
    hash_algorithm = hashlib.md5()
    hash_algorithm.update(string.encode('utf-8'))
    return hash_algorithm.hexdigest()


def clean_text(text):
    """
    normalizes the unicode in a text to be more readable and generate a more accurate id from
    :param text: string to be normalized
    :return: normalized version of text
    """
    return unicodedata.normalize('NFC', text)


print(generate_id(clean_text('Kinesiology, Phys Ed\xa0and Recreation'))) # hashes to acd21f3b094a77d1a2393a8daeac42d9
print(generate_id('Kinesiology, Phys Ed and Recreation')) # hashes to 5ac6bc3ca3d743d99e9b93a7a5379fe9

我能做些什么来确保两个字符串相同并且散列到相同的 id 使得“Kinesiology, Phys Ed\xa0and Recreation”与“Kinesiology, Phys Ed and Recreation”是相同的字符串和相同的散列(无论 unicode 是否存在,任何 2 个字符串都一样)?

【问题讨论】:

    标签: python unicode hash md5 python-unicode


    【解决方案1】:

    由于“具有相同的哈希”只是二进制相等的代理,因此您需要将字符串标准化为相同。

    在 Unicode 术语中,两个给定的字符串不是规范等效的,但它们是兼容的。因此,您将能够在clean_text() 函数中使用兼容性分解/组合范式(NFKDNFKC)生成相同的哈希:

    def clean_text(text):
        return unicodedata.normalize('NFKD', text)
    

    NO-BREAK SPACE (U+00A0) 字符的分解属性设置为<noBreak> SPACE (U+0020)。分解属性中存在关键字(在本例中为 <noBreak>)这一事实表明该字符与常规空格字符兼容,但不是规范等价的。


    旁注

    因为在cmets中要求,稍微澄清一下NFKC和NFKD范式的区别:

    Unicode 字符可以由多个代码点组成。某些字符可以用不同的(但规范等效的)方式表示:作为单个代码点,或作为代码点的组合。例如:é 可以表示为 ée + ◌́。规范化时,组合范式(NFC、NFKC)将尝试将序列转换为其组合形式(e + ◌́é);分解范式(NFD、NFKD)将尝试将组合字符转换为序列(ée + ◌́)。您使用哪一种完全取决于具体情况。请确保不要将苹果与橙子进行比较。

    【讨论】:

    • 适用于这种特定情况,但仍然不会将空格和制表符视为相同,例如。
    • @tripleee 确实如此。取决于 OP 是否指示这些是否应被视为相同。我不知道在需要被视为相等(字符大小写、全角与半角等)方面还有哪些进一步的规则。就 Unicode 规范化而言,对于这种特定情况,两个空格字符是兼容的,但不是规范等效的。
    • @tripleee 顺便说一下,\xa0 是一个不间断的空格,而不是换行符。
    • 啊我瞎了,我以为我在看\x0a
    • @tripleee 不用担心。您的 cmets 促进了进一步的研究,我深入了解并学到了一些新东西:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 2017-01-20
    • 2022-01-19
    • 2020-03-12
    • 1970-01-01
    • 2014-12-19
    相关资源
    最近更新 更多