chore: initial sync
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""Normaliza el nombre de una entidad para comparacion y deduplicacion."""
|
||||
|
||||
import re
|
||||
|
||||
|
||||
_TITLES = re.compile(
|
||||
r"^\b(?:Dr|Mr|Mrs|Ms|Miss|Prof|Sr|Jr|Ing|Lic|Gen|Col|Maj|Capt|Sgt|Rev|Hon)\.?\s+",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
_LEGAL_SUFFIXES = re.compile(
|
||||
r"\b(?:Inc|LLC|Ltd|Corp|Co|S\.?A|GmbH|B\.?V|N\.?V|PLC|AG|SRL|S\.?L|Pty|"
|
||||
r"LP|LLP|LLLP|PC|PA|PLLC|Foundation|Group|Holdings|Enterprises?|"
|
||||
r"International|Industries|Services?|Solutions?|Systems?|Technologies?)\.?\s*$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
_MULTI_SPACE = re.compile(r"\s+")
|
||||
|
||||
|
||||
def normalize_entity_name(name: str, entity_type: str = "") -> str:
|
||||
"""Normaliza el nombre de una entidad para comparacion y deduplicacion.
|
||||
|
||||
Aplica reglas diferentes segun el tipo de entidad:
|
||||
- ip / email / domain / crypto_wallet / phone: normalizacion tecnica
|
||||
- person: normalizacion de nombre humano (titulos, formato apellido-nombre)
|
||||
- organization: normalizacion corporativa (sufijos legales)
|
||||
- default: lower + strip + colapsar espacios
|
||||
|
||||
Args:
|
||||
name: nombre de la entidad a normalizar.
|
||||
entity_type: tipo de entidad (ip, email, domain, crypto_wallet, phone,
|
||||
person, organization). Vacio = default.
|
||||
|
||||
Returns:
|
||||
nombre normalizado como string.
|
||||
"""
|
||||
name = name.strip()
|
||||
et = entity_type.lower().strip()
|
||||
|
||||
if et == "ip":
|
||||
return name.lower()
|
||||
|
||||
if et == "email":
|
||||
return name.lower()
|
||||
|
||||
if et == "domain":
|
||||
result = name.lower().rstrip(".")
|
||||
if result.startswith("www."):
|
||||
result = result[4:]
|
||||
return result
|
||||
|
||||
if et == "crypto_wallet":
|
||||
# Bitcoin addresses son case-sensitive — solo strip
|
||||
return name
|
||||
|
||||
if et == "phone":
|
||||
# Mantener solo digitos y el signo +
|
||||
return re.sub(r"[^\d+]", "", name)
|
||||
|
||||
if et == "person":
|
||||
# Remover titulos al inicio
|
||||
result = _TITLES.sub("", name).strip()
|
||||
# Detectar formato "Apellido, Nombre"
|
||||
if "," in result:
|
||||
parts = result.split(",", 1)
|
||||
last = parts[0].strip()
|
||||
first = parts[1].strip()
|
||||
result = f"{first} {last}"
|
||||
# Colapsar espacios y title case
|
||||
result = _MULTI_SPACE.sub(" ", result).strip()
|
||||
return result.title()
|
||||
|
||||
if et == "organization":
|
||||
result = _LEGAL_SUFFIXES.sub("", name).strip()
|
||||
result = _MULTI_SPACE.sub(" ", result).strip()
|
||||
# Title case para consistencia
|
||||
return result.title()
|
||||
|
||||
# Default: lower, strip, colapsar espacios
|
||||
return _MULTI_SPACE.sub(" ", name.lower()).strip()
|
||||
Reference in New Issue
Block a user