El módulo html.entities de la biblioteca estándar de Python contiene tablas de referencia que relacionan nombres de entidades HTML, caracteres Unicode y puntos de código. Resulta útil cuando una aplicación necesita comprender referencias como &, ©, o ☃, generar documentación, verificar conversiones o construir herramientas de procesamiento de texto.
Este módulo no es un parser HTML completo y tampoco sanitiza contenido. Su función principal es ofrecer datos de referencia. Para procesar etiquetas, atributos, comentarios y texto, consulta la guía de html.parser en Python. Para convertir una cadena completa con referencias HTML, normalmente html.unescape() es la opción de alto nivel más sencilla.
Qué es una entidad HTML
Una entidad es una representación textual de un carácter. En HTML, un ampersand inicia una referencia. La forma nombrada usa un identificador, como < para el signo menor que. La forma numérica utiliza un punto de código Unicode decimal o hexadecimal, como < o <.
Estas referencias existen porque ciertos caracteres tienen significado especial dentro del marcado o pueden ser incómodos de escribir. Sin embargo, no todos los caracteres deben convertirse en entidades. HTML moderno y UTF-8 permiten representar directamente la mayoría de los símbolos. La decisión correcta depende del contexto de salida.
Los cuatro diccionarios del módulo
La documentación oficial describe cuatro estructuras principales:
html.entities.html5relaciona referencias nombradas de HTML5 con texto Unicode.html.entities.name2codepointrelaciona nombres HTML4 con puntos de código Unicode.html.entities.codepoint2namerealiza el camino inverso desde el punto de código a un nombre HTML4.html.entities.entitydefscontiene definiciones XHTML 1.0 y sus textos de reemplazo.
Estas tablas no son intercambiables. HTML5 incluye más nombres y algunas referencias producen más de un carácter Unicode. Elige la estructura según el estándar del documento y el objetivo de la aplicación.
Consultar entidades HTML5
from html.entities import html5
print(html5["copy;"])
print(html5["nbsp;"])
print(html5["NotEqualTilde;"])
Las claves de html5 suelen incluir el punto y coma final. Algunas referencias aceptadas por el estándar también aparecen sin él. No elimines automáticamente ese carácter antes de buscar, porque su ausencia puede cambiar la interpretación en determinados contextos.
El valor puede contener uno o varios caracteres. No supongas que len(valor) siempre es uno. Esta diferencia afecta cálculos de posiciones, límites, resaltado de texto e índices inversos.
Buscar entidades por nombre
from html.entities import html5
prefijo = "copy"
resultados = {
nombre: valor
for nombre, valor in html5.items()
if nombre.lower().startswith(prefijo)
}
for nombre, valor in resultados.items():
print(nombre, repr(valor))
Este patrón puede servir para documentación, autocompletado en editores o herramientas educativas. En una aplicación web, limita la cantidad de resultados y nunca conviertas nombres proporcionados por el usuario en HTML sin el escape contextual correcto.
Usar name2codepoint
from html.entities import name2codepoint
codigo = name2codepoint["euro"]
caracter = chr(codigo)
print(codigo)
print(caracter)
name2codepoint devuelve enteros. La función chr() convierte el punto de código en una cadena Unicode. El mapeo inverso está disponible mediante codepoint2name:
from html.entities import codepoint2name
nombre = codepoint2name.get(ord("©"))
print(nombre)
Usa get() cuando la ausencia de un nombre sea esperable. Muchos caracteres Unicode no tienen una entidad HTML4 nombrada. La aplicación puede conservar el carácter, producir una referencia numérica o aplicar una política explícita de fallback.
Crear referencias numéricas
def referencia_decimal(caracter: str) -> str:
if len(caracter) != 1:
raise ValueError("Indica exactamente un carácter")
return f"&#{ord(caracter)};"
print(referencia_decimal("☃"))
Para hexadecimal, utiliza f"&#x{ord(caracter):X};". Las referencias numéricas cubren más caracteres, pero deben generarse según el contexto. Convertir todo el texto en referencias aumenta el tamaño y dificulta la lectura sin mejorar automáticamente la seguridad.
Cuándo usar html.escape y html.unescape
El módulo superior html ofrece funciones de alto nivel. html.escape() protege caracteres especiales cuando se inserta texto plano en contenido HTML. html.unescape() interpreta referencias nombradas y numéricas siguiendo las reglas de HTML.
import html
texto = "Tom & Jerry <3 programación"
escapado = html.escape(texto)
restaurado = html.unescape(escapado)
print(escapado)
print(restaurado)
html.entities encaja mejor cuando necesitas consultar tablas, comprender un nombre concreto, crear índices o implementar una transformación controlada. Para codificar o decodificar cadenas completas, prefiere las funciones probadas de alto nivel.
Decodificar no significa sanitizar
Esta es la diferencia de seguridad más importante. html.unescape("<script>") produce una cadena que contiene una etiqueta script. La función solo convierte referencias; no decide si el resultado es seguro para renderizar.
Si contenido no confiable debe mostrarse como texto, escápalo al generar la salida. Si la aplicación permite un subconjunto de HTML, usa una biblioteca de sanitización mantenida con una allowlist de etiquetas y atributos. No intentes crear un sanitizador eliminando entidades, aplicando expresiones regulares o bloqueando unas pocas palabras.
Entidades dentro de atributos
Los atributos tienen reglas adicionales. Un valor insertado en href, src, style o un atributo de evento no queda protegido únicamente reemplazando signos angulares. Las URLs necesitan validación de esquema y origen, y los atributos peligrosos no deben aceptarse desde autores no confiables.
Para separar componentes de una URL, consulta urllib.parse en Python. Analizar una URL tampoco la convierte en confiable.
Punto y coma opcional
HTML5 acepta algunas referencias nombradas sin punto y coma bajo reglas históricas específicas. La tabla html5 puede contener ambas formas. Al generar HTML nuevo, usa el punto y coma: es más claro y evita ambigüedad con letras o números posteriores.
from html.entities import html5
print("amp;" in html5)
print("amp" in html5)
Al procesar documentos existentes, deja que un parser compatible con el estándar aplique las reglas. Una rutina que solo busque desde & hasta el siguiente ; fallará con marcado incompleto o ambiguo.
Valores con varios caracteres
Algunas entidades HTML5 representan secuencias Unicode. Un procesamiento que presupone una relación uno a uno puede cortar la salida o calcular índices incorrectos. Conserva la cadena completa e incluye entidades complejas en las pruebas.
from html.entities import html5
for nombre, valor in html5.items():
if len(valor) > 1:
print(nombre, [f"U+{ord(c):04X}" for c in valor])
break
Esto también se relaciona con la normalización Unicode. Dos textos visualmente iguales pueden usar secuencias diferentes. Para comparar o buscar contenido, considera unicodedata.normalize(), explicado en la guía de unicodedata en Python.
Construir un catálogo de entidades
from html.entities import html5
catalogo = []
for nombre, valor in sorted(html5.items()):
catalogo.append({
"nombre": nombre,
"texto": valor,
"codepoints": [f"U+{ord(c):04X}" for c in valor],
})
print(catalogo[:3])
Este catálogo puede exportarse a JSON, CSV o una página de documentación. Al generar HTML, escapa tanto etiquetas como valores mediante el sistema de plantillas. Incluso los datos confiables de la biblioteca estándar deben pasar por el mecanismo de salida correcto para evitar que cambios futuros introduzcan marcado crudo.
Tratar nombres desconocidos
from html.entities import html5
def resolver(nombre: str) -> str | None:
clave = nombre if nombre.endswith(";") else nombre + ";"
return html5.get(clave)
print(resolver("copy"))
print(resolver("entidad_inexistente"))
No reemplaces silenciosamente una entidad desconocida por una cadena vacía porque se pierde información. Conserva el origen, devuelve None, registra un aviso limitado o rechaza la entrada según el contrato de la aplicación.
Rendimiento y memoria
Las tablas ya son diccionarios y las búsquedas por clave son rápidas. La mayoría de las aplicaciones no necesita copiar todo el contenido repetidamente. Importa una vez, reutiliza las estructuras y crea índices adicionales solo cuando una carga medida lo justifique.
Para documentos grandes, evita una pasada de reemplazo por cada entidad. Usa html.unescape() o un parser incremental. La guía de html.parser muestra cómo alimentar datos por bloques.
Pruebas recomendadas
Incluye nombres comunes, referencias numéricas decimales y hexadecimales, punto y coma opcional, valores con varios caracteres, nombres desconocidos, texto ya escapado y entradas malformadas. Prueba también el contexto final: texto, atributo, JSON, logs o base de datos.
Una prueba debe verificar algo más que el carácter resultante. También debe comprobar la política de seguridad. Una cadena correctamente decodificada puede seguir siendo peligrosa para renderizar como HTML.
Errores comunes
Los errores frecuentes son usar el mapeo HTML4 para contenido HTML5, asumir que cada valor tiene un carácter, olvidar el punto y coma, descartar referencias desconocidas, tratar unescape() como sanitizador, escapar demasiado pronto y producir doble escape, o insertar valores decodificados en URLs y atributos sin validación contextual.
Conclusión
html.entities proporciona acceso directo a las relaciones entre nombres HTML y Unicode. Es útil para catálogos, herramientas de análisis, conversores especializados y validaciones. Para tareas comunes, combínalo con html.escape(), html.unescape() y un parser apropiado.
Consulta la documentación oficial de html.entities y la lista de referencias nombradas de HTML. Mantén separadas las operaciones de decodificación, parsing, validación, escape y sanitización.







