如何归一化同一内容的不同写法?咨询Django相关处理模块
Django 城市名称归一化实现方案
Django本身没有专门处理这类字符串归一化的内置模块,但可以通过自定义逻辑结合Django生态工具,轻松实现你需要的统一归一化+规则可扩展的工作流程,以下是几种实用方案:
一、自定义别名映射表(精确匹配,可控性强)
这是最直接的方案,适合需要精准规则的场景,能随时添加新的城市别名:
- 新建一个存储别名与标准名称的模型:
from django.db import models class CityAlias(models.Model): alias = models.CharField(max_length=100, unique=True) # 存储各种变体写法 standard_name = models.CharField(max_length=100) # 归一化后的标准名称 class Meta: verbose_name = "城市别名" verbose_name_plural = "城市别名"
- 在爬取数据的模型中添加自动归一化逻辑:
class ScrapedData(models.Model): raw_city = models.CharField(max_length=100) # 爬取到的原始城市名 normalized_city = models.CharField(max_length=100, blank=True) # 归一化后的结果 def save(self, *args, **kwargs): # 查找是否有匹配的别名规则 match = CityAlias.objects.filter(alias=self.raw_city).first() if match: self.normalized_city = match.standard_name else: # 没有匹配规则时,可留空或标记为待审核,后续人工添加规则后再更新 self.normalized_city = self.raw_city super().save(*args, **kwargs)
- 后续遇到新的城市写法(比如"S Diego"),直接在Django后台添加一条
CityAlias记录,后续爬取的该名称会自动归一化到标准值。
二、结合PostgreSQL模糊匹配(适配变体较多的场景)
如果城市变体写法太多,不想手动维护所有精确规则,可以利用PostgreSQL的全文搜索能力实现模糊匹配:
- 给
CityAlias模型添加搜索索引,提升匹配效率:
from django.contrib.postgres.indexes import GinIndex from django.contrib.postgres.search import SearchVectorField class CityAlias(models.Model): alias = models.CharField(max_length=100, unique=True) standard_name = models.CharField(max_length=100) search_vector = SearchVectorField(null=True) # 用于全文搜索的向量字段 class Meta: indexes = [GinIndex(fields=['search_vector'])]
- 添加信号自动更新搜索向量:
from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.postgres.search import SearchVector @receiver(post_save, sender=CityAlias) def update_search_vector(sender, instance, **kwargs): CityAlias.objects.filter(pk=instance.pk).update( search_vector=SearchVector('alias', config='english') )
- 实现模糊匹配的归一化方法:
from django.contrib.postgres.search import SearchQuery, SearchRank def normalize_city(raw_city): query = SearchQuery(raw_city, config='english') # 按匹配度排序,取最接近的结果 matches = CityAlias.objects.annotate( rank=SearchRank('search_vector', query) ).filter(rank__gt=0.1).order_by('-rank') if matches.exists(): return matches.first().standard_name return raw_city
新的变体写法如果和已有别名相似度足够高,会自动匹配到标准名称,之后可以把这个新写法添加到CityAlias中,让后续匹配更精准。
三、结合第三方字符串匹配库(处理拼写变体)
可以用fuzzywuzzy这类字符串相似度匹配库,进一步提升变体识别能力:
- 安装库后,在归一化逻辑中使用:
from fuzzywuzzy import process def normalize_city(raw_city): # 构建别名-标准名的映射字典 alias_map = {item.alias: item.standard_name for item in CityAlias.objects.all()} # 匹配最相似的别名 match, score = process.extractOne(raw_city, alias_map.keys()) # 设置相似度阈值,比如80分以上认为匹配成功 if score >= 80: return alias_map[match] return raw_city
这种方式能处理更多拼写类的变体,新增规则同样只需在CityAlias中添加记录即可。
内容的提问来源于stack exchange,提问作者Pachino
相关产品推荐
相关产品推荐

