对于我正在进行的web抓取项目,我计划将实体存储在数据库中,其中的I是名称/标题的md5散列。
但是,由于字符串中存在Unicode,因此将出现相同名称/标题的不同散列。
例如,“运动学、物理Ed \xa0和娱乐”的md5散列将不同于“运动学、生理Ed和娱乐”。
我尝试使用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,例如“动力学,Phys Ed \xa0和Recreation”是与‘do,Phys Ed和Recreation’相同的字符串和相同的散列(与任何2个字符串相同,无论unicode存在)?
发布于 2020-11-11 05:44:32
因为“拥有相同的散列”只是二进制等式的代理,所以您需要的是将字符串规范化为相同。
在Unicode术语中,两个给定的字符串不是规范上等效的,但它们是兼容的。因此,您将能够使用兼容性分解/组合范式(NFKD或NFKC)在clean_text()函数中生成相同的哈希:
def clean_text(text):
return unicodedata.normalize('NFKD', text)NO-BREAK SPACE (U+00A0)字符的分解属性设置为<noBreak> SPACE (U+0020)。分解属性(在本例中是<noBreak>)中存在一个关键字这一事实表明,该字符与正则空间字符兼容,但不是规范等效的。
边注
由于在评论中提出了这一要求,因此对NFKC和NFKD范式之间的区别作了一点澄清:
Unicode字符可以由多个代码点组成。某些字符可以用不同的(但规范上等效的)方式表示:或者作为单个代码点,或者作为代码点的组合。例如:é可以表示为é,也可以表示为e + ◌́。在规范化时,组合范式(NFC、NFKC)将尝试将序列转换为它们的组合形式(e + ◌́→é);分解范式(NFD、NFKD)将尝试将组合字符转换为序列(é→e + ◌́)。你用哪一种完全取决于情况。确保不要把苹果和橘子作比较。
https://stackoverflow.com/questions/64780986
复制相似问题