Cómo extraer las entidades más repetidas de varias URLs con Python y TextRazor

17 min de lectura

Para extraer las entidades más repetidas de varias URLs con Python basta un script corto: descarga cada página con requests, limpia el HTML con BeautifulSoup, envía el texto a la API de TextRazor y cuenta qué entidades aparecen más veces. Aquí tienes el código completo, cómo ejecutarlo y qué hacer después con el resultado.

Sirve sobre todo para dos cosas: ver de qué hablan de verdad las páginas que posicionan para una búsqueda y comprobar si tu contenido cubre esos mismos conceptos. Se tarda menos en ejecutarlo que en leer cinco artículos de la competencia.

Qué es una entidad en SEO y por qué importa más que repetir palabras clave

Una entidad en SEO es una «cosa» con nombre propio que un buscador sabe identificar: una persona, una empresa, un lugar, un producto o un concepto. A diferencia de una palabra clave, la entidad es la misma aunque se escriba de formas distintas, y los buscadores la usan para entender de qué trata un texto.

La documentación de Google Cloud lo explica de forma parecida al describir su API: el análisis de entidades ofrece información sobre las «cosas» con nombre que aparecen en un texto, como personajes conocidos, lugares u objetos comunes.

¿Y esto qué tiene que ver con posicionar? Que un contenido completo sobre un tema menciona, de forma natural, las entidades que un experto esperaría encontrar. Repetir veinte veces la misma palabra clave no lo consigue. Google lo dice a su manera en la guía sobre crear contenido útil, fiable y dirigido a personas: sus sistemas premian el contenido hecho para ayudar al lector, no el pensado para manipular el ranking.

Con los buscadores con IA pasa lo mismo. Un modelo de lenguaje (ChatGPT, Gemini y compañía) trabaja con conceptos y relaciones entre ellos, así que un texto que nombra las entidades correctas y las explica bien es más fácil de entender y de citar. Es una parte de lo que trabajamos en el posicionamiento en LLM.

Qué hace el script de Python con TextRazor paso a paso

El script de Python recibe una lista de URLs, descarga el texto de cada una, se lo pasa a la API de TextRazor para que reconozca las entidades y devuelve las 40 más repetidas entre todas las páginas, separadas por comas y sin números ni ruido. No necesita base de datos ni interfaz: se ejecuta en la consola.

  1. Lee un listado de URLs pegadas en la consola, separadas por espacios o comas.
  2. Descarga el HTML de cada URL con requests.
  3. Limpia el HTML con BeautifulSoup, quitando <script>, <style>, <noscript> y <template>.
  4. Envía el texto a la API de TextRazor para extraer las entidades.
  5. Filtra números y se queda con las entidades que contienen letras.
  6. Cuenta las apariciones de cada entidad (sin distinguir mayúsculas de minúsculas) y devuelve las 40 más frecuentes.

Requisitos para ejecutar el script: Python, librerías y clave de TextRazor

Para ejecutar el script necesitas Python 3.9 o superior, tres librerías que se instalan con un solo comando (textrazor, requests y beautifulsoup4) y una clave de API de TextRazor, que se obtiene al registrarte. El plan gratuito de TextRazor es suficiente para análisis puntuales de unas pocas URLs.

  1. Instala Python 3.9 o superior.
  2. Instala las dependencias:
    pip install textrazor requests beautifulsoup4
  3. Regístrate en TextRazor y copia tu API Key. Va en la línea textrazor.api_key = "AQUI_TU_API_KEY".

Límites del plan gratuito de TextRazor

Según la página de planes de TextRazor, el plan gratuito incluye 500 peticiones al día y 2 peticiones simultáneas. Ojo con un detalle: una petición cubre hasta 10 KB de texto, y los documentos más largos cuentan como varias peticiones (una por cada 10 KB).

En la práctica, un artículo largo puede gastar varias peticiones él solo. Para analizar cinco o diez URLs vas sobrado; para cientos de páginas al día necesitarás un plan de pago o repartir el trabajo en varios días.

El código completo del script para extraer entidades de varias URLs

Este es el código completo del script para extraer entidades de varias URLs. Cópialo en un archivo, por ejemplo entidades.py, cambia AQUI_TU_API_KEY por tu clave de TextRazor y ejecútalo con python entidades.py. Respeta la sangría (los espacios al inicio de cada línea): en Python forma parte del código.

# pip install textrazor requests beautifulsoup4

import re
import sys
from collections import Counter

import requests
from bs4 import BeautifulSoup
import textrazor

# Clave API de TextRazor
textrazor.api_key = "AQUI_TU_API_KEY"

# Expresión regular para filtrar entidades con letras (evitar números)
ALPHA_RE = re.compile(r"[A-Za-zÁÉÍÓÚÜÑáéíóúüñ]")


def fetch_text(url, timeout=20):
    """Descarga y limpia el texto de una URL."""
    headers = {"User-Agent": "Mozilla/5.0 (compatible; EntityCollector/1.0)"}
    r = requests.get(url, headers=headers, timeout=timeout)
    r.raise_for_status()
    soup = BeautifulSoup(r.text, "html.parser")
    for tag in soup(["script", "style", "noscript", "template"]):
        tag.decompose()
    return soup.get_text(" ", strip=True)[:100_000]  # límite para API


def extract_entities_from_text(text, language="spa"):
    """Extrae entidades de un texto usando TextRazor."""
    client = textrazor.TextRazor(extractors=["entities"])
    client.set_language_override(language)
    resp = client.analyze(text)
    names = []
    for ent in resp.entities() or []:
        name = (ent.matched_text or "").strip()
        if not name or not ALPHA_RE.search(name):
            continue
        # TextRazor devuelve un objeto por cada mención de la entidad
        names.append(name)
    return names


def main():
    raw = input("Pega las URLs separadas por comas o espacios: ").strip()
    parts = re.split(r"[,\s]+", raw)
    urls = [u if "://" in u else "https://" + u for u in parts if u]

    counts = Counter()
    first_seen_case = {}

    for url in urls:
        try:
            text = fetch_text(url)
            for e in extract_entities_from_text(text):
                k = e.lower()
                if k not in first_seen_case:
                    first_seen_case[k] = e
                counts[k] += 1
        except Exception as e:
            print(f"[AVISO] {url}: {e}", file=sys.stderr)

    top = [first_seen_case[k] for k, _ in counts.most_common(40)]
    print(", ".join(top))


if __name__ == "__main__":
    main()

Qué hace cada parte del código

  • fetch_text descarga la página, elimina las etiquetas que no son contenido y devuelve el texto plano, recortado a 100.000 caracteres. La documentación de TextRazor para Python indica que cada petición admite hasta 200 KB de texto, así que el recorte deja margen de sobra y evita gastar cuota en páginas enormes.
  • extract_entities_from_text crea el cliente pidiendo solo el extractor entities y fuerza el idioma con set_language_override("spa"). Ese método espera un código ISO 639-2 (tres letras): spa es español y eng, inglés. Si quitas esa línea, TextRazor detecta el idioma solo.
  • matched_text es el texto tal como aparece en la página. TextRazor devuelve un objeto por cada mención, así que contar los objetos equivale a contar las veces que se nombra cada entidad.
  • main junta los recuentos de todas las URLs, ignora mayúsculas y minúsculas al sumar y muestra cada entidad con la grafía de la primera vez que apareció. Si una URL falla, avisa y sigue con las demás.

Cómo ejecutar el script y qué resultado devuelve

El script se ejecuta desde la consola con python entidades.py, pide que pegues las URLs separadas por comas o espacios y, tras unos segundos por página, imprime una sola línea con las 40 entidades más repetidas en el conjunto, ordenadas de más a menos frecuente y separadas por comas.

Imagina que analizas cinco artículos de un competidor sobre IA y marketing. La salida tendría este aspecto:

Inteligencia artificial, Google, SEO, aprendizaje automático, búsqueda, ChatGPT, algoritmos, datos, contenido...

Con esa lista ves de un vistazo qué conceptos dominan en su contenido y puedes compararlos con el tuyo. Puedes pegar las URLs con o sin https://: si falta, el script lo añade.

Cómo leer el resultado y qué hacer con las entidades

La lista de entidades sirve para comparar: ejecuta el script con las URLs que posicionan para tu búsqueda, vuelve a ejecutarlo con tu página y mira qué entidades tienen ellas y tú no. Esas ausencias son subtemas que probablemente falten en tu contenido. El resto es ruido que hay que descartar con criterio.

Separa las entidades útiles del ruido

No todo lo que sale en la lista merece atención. Antes de sacar conclusiones, quita:

  • Nombres de marca de cada competidor y de sus autores.
  • Elementos de menú, pie de página y avisos de cookies («Política de privacidad», «Contacto», redes sociales).
  • Entidades demasiado genéricas que aparecerían en cualquier texto («España», «Internet»).

Lo que queda suele ser lo interesante: conceptos, productos, normativas, herramientas o lugares que varios competidores mencionan y que definen el tema.

Pásalo a un briefing de redacción

Una entidad que falta no se arregla metiendo la palabra en una frase. Se arregla respondiendo a lo que el lector querría saber sobre ella. En un briefing se traduce en algo así:

  1. Entidades que aparecen en la mayoría de competidores y no en nuestra página: candidatas a un apartado propio (H2 o H3).
  2. Entidades que solo trabaja un competidor: revisar si aportan algo o son una rareza suya.
  3. Entidades que tenemos nosotros y nadie más: puede ser nuestro punto diferencial, o una señal de que nos hemos ido del tema.

Esto encaja bien después de un keyword research paso a paso: las palabras clave te dicen qué busca la gente y las entidades, qué tiene que contar la página para responder bien.

¿Quieres contenidos que cubran lo que de verdad trata tu competencia? Preparamos contigo los briefings y la redacción a partir de datos como estos, pensados para tu sector y tu cliente.

Ver el servicio de redacción SEO

Usos del análisis de entidades en una auditoría o estrategia SEO

El análisis de entidades tiene seis usos claros en SEO: analizar a la competencia, optimizar la semántica de tus contenidos, detectar brechas de contenido, planificar clústeres temáticos, ordenar el enlazado interno y vigilar cambios en la estrategia de un competidor. Todos parten de la misma lista, comparada entre distintas páginas o fechas.

  1. Análisis de la competencia. Pega varias URLs de competidores y obtén las entidades que más repiten. Te muestra de qué hablan realmente, más allá de las palabras clave exactas, y con qué temas podría estar asociándolos Google.
  2. Optimización semántica de contenidos. Introduce tus propias URLs y comprueba si aparecen las entidades relevantes de tu sector. Si faltan, intégralas de forma natural para reforzar la temática.
  3. Detección de brechas de contenido (content gap). Compara las entidades de los competidores con las tuyas. Las que ellos trabajan y tú no son oportunidades para artículos nuevos o actualizaciones.
  4. Planificación de clústeres temáticos. A partir de las entidades comunes en un grupo de artículos puedes definir subtemas y crear un clúster de contenidos enlazados entre sí, lo que mejora la cobertura del tema.
  5. Optimización del enlazado interno. Usa las entidades más recurrentes como nodos principales (hubs) de tu arquitectura. Por ejemplo, si «inteligencia artificial» es frecuente, crea o refuerza una página pilar y enlázala desde todos los artículos que la mencionan.
  6. Seguimiento de la estrategia de un competidor. Ejecuta el script cada cierto tiempo sobre las mismas URLs o categorías. Si empiezan a aparecer entidades nuevas, puede ser señal de un cambio de enfoque.

La misma idea se aplica fuera de tu web: al valorar un enlace, las entidades de la página que te enlaza indican si habla de tu tema o no. Lo explico en el post sobre la afinidad semántica de los backlinks.

Limitaciones del script y cómo mejorarlo

El script tiene tres limitaciones: no ejecuta JavaScript, incluye en el recuento el texto de menús y pies de página, y cuenta el texto literal en lugar del identificador de la entidad, de modo que «Google» y «Google LLC» suman por separado. Las tres tienen arreglo sencillo.

No ejecuta JavaScript

requests descarga el HTML tal como lo sirve el servidor. Si la página pinta su contenido con JavaScript, el script verá poco o nada. En esos casos necesitas un navegador que renderice la página o un rastreador que lo haga, como contamos en el tutorial para auditar con Screaming Frog y Claude.

Cuenta también menús, pie y avisos de cookies

get_text() extrae todo el texto visible de la página, no solo el artículo. Tienes dos salidas: eliminar también nav, header, footer y aside en la lista de etiquetas que se descartan, o dejar que TextRazor haga la limpieza. Su cliente tiene el método analyze_url, que descarga la página él mismo, y el modo de limpieza cleanHTML, que según su documentación quita el contenido repetitivo (menús incluidos) y deja el cuerpo del artículo.

Agrupa por identificador de entidad en lugar de por texto

Cada entidad que devuelve TextRazor trae, además de matched_text, un campo id con su nombre canónico (el de Wikipedia en el idioma del documento) y dos puntuaciones, relevance_score y confidence_score. Si cuentas por id, las variantes de un mismo concepto se suman juntas. Basta con sustituir la función por esta variante:

def extract_entities_from_text(text, language="spa"):
    """Variante: agrupa por el identificador de la entidad."""
    client = textrazor.TextRazor(extractors=["entities"])
    client.set_language_override(language)
    resp = client.analyze(text)
    names = []
    for ent in resp.entities() or []:
        # ent.id es el nombre canónico (el de Wikipedia en el idioma del texto)
        name = (ent.id or ent.matched_text or "").strip()
        if not name or not ALPHA_RE.search(name):
            continue
        names.append(name)
    return names

Si además quieres quedarte solo con las entidades de las que TextRazor está más seguro, añade una condición sobre ent.confidence_score. Prueba el umbral con tus propias páginas, porque depende del tipo de texto.

Buenas prácticas al descargar webs ajenas

Estás pidiendo páginas a servidores que no son tuyos. Hazlo con cabeza: pocas URLs por ejecución, sin lanzarlas en paralelo contra el mismo dominio, y respetando lo que indique su archivo robots.txt (si no lo tienes fresco, aquí explicamos qué es el robots.txt y cómo se interpreta).

Errores frecuentes al ejecutar el script y cómo resolverlos

Los errores más habituales al ejecutar el script son cuatro: clave de API no válida o cuota agotada, páginas que bloquean la descarga, texto demasiado grande e idioma mal indicado. El script no se detiene cuando falla una URL: muestra una línea que empieza por [AVISO] con el motivo y continúa con la siguiente.

SíntomaCausa probableQué hacer
Error 401 de TextRazorClave mal copiada o cuota diaria agotadaRevisa la clave en tu cuenta y el consumo del día
Error 403 o 429 al descargar la URLLa web bloquea peticiones automáticasNo insistas; copia el texto a mano o usa analyze_url
Error 413 de TextRazorTexto por encima de 200 KBReduce el recorte de 100.000 caracteres
Entidades raras o en otro idiomaLa página no está en españolCambia "spa" por el código del idioma o quita la línea
Salida vacíaContenido cargado con JavaScriptUsa una herramienta que renderice la página

TextRazor, Google Cloud Natural Language, spaCy o un modelo de IA: cuál usar

TextRazor es la opción más rápida para empezar a extraer entidades con Python porque tiene plan gratuito y un cliente oficial muy simple. La API Natural Language de Google Cloud es la alternativa de Google, spaCy funciona en tu propio ordenador sin enviar datos fuera y un modelo de IA generativa es el más flexible, pero el menos repetible.

OpciónVentajasInconvenientes
TextRazorPlan gratuito, pocas líneas de código, enlaza cada entidad con WikipediaCuota diaria limitada; el texto sale de tu equipo
API Natural Language de Google CloudTecnología de Google, bien documentadaRequiere proyecto en Google Cloud y facturación configurada
spaCy (en local)Sin cuotas ni coste por uso, los datos no salen de tu ordenadorHay que instalar un modelo de idioma; reconoce tipos de entidad, pero no las vincula a Wikipedia por defecto
Modelo de IA generativaPuedes pedirle que agrupe, explique y prioriceEl resultado varía entre ejecuciones y hay que revisarlo

Mi criterio: para un análisis puntual, TextRazor y este script. Si vas a montarlo como proceso fijo sobre muchas URLs, compensa valorar spaCy o un plan de pago.

Preguntas frecuentes

¿No está tu pregunta? Escríbeme a alberto@ingenieroseo.com y te contesto en menos de 24 horas.

¿Qué es la extracción de entidades?

La extracción de entidades es una técnica de procesamiento del lenguaje natural que detecta en un texto las personas, empresas, lugares, productos y conceptos que se mencionan, y los identifica como elementos únicos aunque estén escritos de formas distintas. En SEO se usa para saber de qué trata realmente una página y compararla con otras.

¿TextRazor es gratis?

TextRazor tiene un plan gratuito que permite 500 peticiones al día con 2 simultáneas, según su página de planes. Cada 10 KB de texto cuenta como una petición, así que una página larga consume varias. Para volúmenes mayores hay planes de pago.

¿Funciona el script con páginas en inglés u otros idiomas?

Sí. El script fuerza el español con el código spa; para inglés hay que cambiarlo por eng, siempre en formato ISO 639-2 de tres letras. Si eliminas la línea set_language_override, TextRazor detecta el idioma de cada texto automáticamente.

¿Cuántas URLs conviene analizar a la vez?

Para comparar contenidos, entre cinco y diez URLs que posicionen para la misma búsqueda suelen dar una lista representativa. Con más páginas el recuento se llena de entidades genéricas y de marca, y además gastas antes la cuota diaria del plan gratuito de TextRazor.

¿Meter más entidades en un texto mejora el posicionamiento?

No por sí solo. Añadir nombres sin explicarlos es otra forma de relleno. Lo que ayuda es que el contenido responda bien a lo que el lector espera sobre el tema, y las entidades que usan las páginas mejor posicionadas son una pista de qué subtemas faltan en el tuyo.

Qué hacer a continuación

Elige una búsqueda que te importe, pasa por el script las cinco primeras URLs que posicionan y después tu propia página. Con las dos listas delante, apunta tres entidades que te falten y decide si merecen un apartado. Es un ejercicio de media hora que suele dejar trabajo claro para el redactor.

¿Te interesa aparecer también en las respuestas de ChatGPT, Gemini o Google? Revisamos contigo cómo entienden tu marca los buscadores con IA y qué contenidos hay que reforzar, paso a paso.

Ver el servicio de SEO para IA

Si adaptas el script o te da algún error que no aparece en la tabla, cuéntamelo en los comentarios y lo vemos.

Compartir

Consultor SEO senior y perito SEO judicial. Trabaja en posicionamiento web desde 2008 y ayuda a empresas a conseguir clientes desde Google y desde las inteligencias artificiales. También elabora informes periciales de SEO para procedimientos judiciales.

Recibe los próximos artículos en tu correo

Te avisamos cuando publiquemos algo nuevo sobre SEO e inteligencia artificial. Puedes darte de baja cuando quieras.

¿Quieres aplicar esto en tu web?

Cuéntanos tu caso y te decimos con claridad qué haríamos primero y si podemos ayudarte.

HablemosWhatsApp