Clústeres automáticos de palabras clave SEO por intención de búsqueda con Python

  • HatumSEO
  • SEO
  • Clústeres automáticos de palabras clave SEO por intención de búsqueda con Python

El proceso de investigación de palabras clave de SEO se puede hacer más rápido, más preciso y más escalable con Python. Esto es lo que necesita saber.

Hay mucho que saber sobre la intención de búsqueda, desde el uso del deep learning para inferir la intención de búsqueda al clasificar el texto y desglosar los títulos SERP usando técnicas de procesamiento de lenguaje natural (NLP), hasta la agrupación basada en la relevancia semántica con los beneficios explicados.

No solo conocemos los beneficios de descifrar la intención de búsqueda, también tenemos una serie de técnicas a nuestra disposición para escalar y automatizar.

Pero a menudo, eso implica construir tu propia IA.. ¿Qué pasa si no tienes el tiempo ni el conocimiento para eso?

En esta columna, aprenderá un proceso paso a paso para automatizar la categorización de palabras clave por intención de búsqueda usando Python.

Los SERP contienen información para la intención de búsqueda

Algunos métodos requieren que obtenga toda la copia de los títulos del contenido posicionado para una palabra clave determinada, luego la introduzca en un modelo de red neuronal (que luego debe construir y probar), o tal vez esté usando NLP para agrupar palabras clave

Existe otro método que le permite utilizar la propia IA de Google para que haga el trabajo por usted, sin tener que scrapear todo el contenido de las SERP y crear un modelo de IA.

Supongamos que Google posiciona las URLs de los sitios según la probabilidad de que el contenido satisfaga la consulta del usuario en orden descendente.. De ello se deduce que si la intención de dos palabras clave es la misma, es probable que las SERP sean similares.

Durante años, muchos profesionales de SEO compararon los resultados SERP de las palabras clave para inferir la intención de búsqueda compartida (o compartida) para mantenerse al tanto de las core updates, por lo que esto no es nada nuevo.

El valor agregado aquí es la automatización y el escalado de esta comparación, que ofrece velocidad y mayor precisión.

Cómo agrupar miles de palabras clave por intención de búsqueda usando Python (con código)

Comience con los resultados de sus SERP en una descarga de CSV.

1. Importe la lista en su cuaderno de Python.

import pandas as pd
import numpy as np

serps_input = pd.read_csv('data/sej_serps_input.csv')
serps_input

A continuación se muestra el archivo SERP ahora importado en un marco de datos de Pandas.

2. Filtrar datos para la página 1

Queremos comparar los resultados de la página 1 de cada SERP entre palabras clave.

Dividiremos el marco de datos en mini marcos de datos de palabras clave para ejecutar la función de filtrado antes de volver a combinarlos en un solo marco de datos, porque queremos filtrar a nivel de palabra clave:

# Separar
serps_grpby_palabra clave = serps_input.groupby("palabra clave")
k_urls = 15

# Aplicar Combinar
def filter_k_urls(group_df):
    filtered_df = group_df.loc[group_df['url'].notnull()]
    filtered_df = filtered_df.loc[filtered_df['rango'] <= k_urls]
    devolver filtered_df
filtered_serps = serps_grpby_keyword.apply(filter_k_urls)

# Combinar
## Agregar prefijo a los nombres de las columnas
#normado = normado.add_prefix('normado_')

# Concatenar con el marco de datos inicial
filtered_serps_df = pd.concat([filtered_serps],axis=0)
del filtered_serps_df['palabra clave']
filtered_serps_df = filtered_serps_df.reset_index()
del filtered_serps_df['level_1']
filtrado_serps_df

3. Convertir las URLs posicionadas en un string

Debido a que hay más URLs de resultados que palabras clave, necesitamos comprimir esas URLs en una sola línea para representar el SERP de la palabra clave.

Así es cómo:

# convert results to strings using Split Apply Combine
filtserps_grpby_keyword = filtered_serps_df.groupby("keyword")
def string_serps(df):
    df['serp_string'] = ''.join(df['url'])
    return df    

# Combine
strung_serps = filtserps_grpby_keyword.apply(string_serps)

# Concatenate with initial data frame and clean
strung_serps = pd.concat([strung_serps],axis=0)
strung_serps = strung_serps[['keyword', 'serp_string']]#.head(30)
strung_serps = strung_serps.drop_duplicates()
strung_serps

A continuación se muestra el SERP comprimido en una sola línea para cada palabra clave.

4. Comparar la similitud de las SERP

Para realizar la comparación, ahora necesitamos cada combinación de palabra clave SERP emparejada con otros pares:

# align serps
def serps_align(k, df):
    prime_df = df.loc[df.keyword == k]
    prime_df = prime_df.rename(columns = {"serp_string" : "serp_string_a", 'keyword': 'keyword_a'})
    comp_df = df.loc[df.keyword != k].reset_index(drop=True)
    prime_df = prime_df.loc[prime_df.index.repeat(len(comp_df.index))].reset_index(drop=True)
    prime_df = pd.concat([prime_df, comp_df], axis=1)
    prime_df = prime_df.rename(columns = {"serp_string" : "serp_string_b", 'keyword': 'keyword_b', "serp_string_a" : "serp_string", 'keyword_a': 'keyword'})
    return prime_df

columns = ['keyword', 'serp_string', 'keyword_b', 'serp_string_b']
matched_serps = pd.DataFrame(columns=columns)
matched_serps = matched_serps.fillna(0)
queries = strung_serps.keyword.to_list()

for q in queries:
    temp_df = serps_align(q, strung_serps)
    matched_serps = matched_serps.append(temp_df)

matched_serps

Lo anterior muestra todas las combinaciones de pares SERP de palabras clave, lo que lo prepara para la comparación de strings de las SERP.

No existe una biblioteca de código abierto que compare los objetos de la lista por orden, por lo que la función se ha escrito a continuación.

La función ‘serp_compare’ compara la superposición de sitios y el orden de esos sitios entre SERP.

import py_stringmatching as sm
ws_tok = sm.WhitespaceTokenizer()

# Only compare the top k_urls results 
def serps_similarity(serps_str1, serps_str2, k=15):
    denom = k+1
    norm = sum([2*(1/i - 1.0/(denom)) for i in range(1, denom)])

    ws_tok = sm.WhitespaceTokenizer()

    serps_1 = ws_tok.tokenize(serps_str1)[:k]
    serps_2 = ws_tok.tokenize(serps_str2)[:k]

    match = lambda a, b: [b.index(x)+1 if x in b else None for x in a]

    pos_intersections = [(i+1,j) for i,j in enumerate(match(serps_1, serps_2)) if j is not None] 
    pos_in1_not_in2 = [i+1 for i,j in enumerate(match(serps_1, serps_2)) if j is None]
    pos_in2_not_in1 = [i+1 for i,j in enumerate(match(serps_2, serps_1)) if j is None]
    a_sum = sum([abs(1/i -1/j) for i,j in pos_intersections])
    b_sum = sum([abs(1/i -1/denom) for i in pos_in1_not_in2])
    c_sum = sum([abs(1/i -1/denom) for i in pos_in2_not_in1])

    intent_prime = a_sum + b_sum + c_sum
    intent_dist = 1 - (intent_prime/norm)
    return intent_dist
# Apply the function
matched_serps['si_simi'] = matched_serps.apply(lambda x: serps_similarity(x.serp_string, x.serp_string_b), axis=1)
serps_compared = matched_serps[['keyword', 'keyword_b', 'si_simi']]
serps_compared

Ahora que se han ejecutado las comparaciones, podemos comenzar a agrupar palabras clave.

Trataremos cualquier palabra clave que tenga una similitud ponderada del 40 % o más.

# group keywords by search intent
simi_lim = 0.4

# join search volume
keysv_df = serps_input[['keyword', 'search_volume']].drop_duplicates()
keysv_df.head()

# append topic vols
keywords_crossed_vols = serps_compared.merge(keysv_df, on = 'keyword', how = 'left')
keywords_crossed_vols = keywords_crossed_vols.rename(columns = {'keyword': 'topic', 'keyword_b': 'keyword',
                                                                'search_volume': 'topic_volume'})

# sim si_simi
keywords_crossed_vols.sort_values('topic_volume', ascending = False)


# strip NANs
keywords_filtered_nonnan = keywords_crossed_vols.dropna()
keywords_filtered_nonnan

Ahora tenemos el nombre del tema potencial, la similitud SERP de las palabras clave y los volúmenes de búsqueda de cada uno.

Notará que palabra clave y palabra clave_b se han renombrado como tema y palabra clave, respectivamente.

Ahora vamos a iterar sobre las columnas en el marco de datos usando la técnica lamdas.

La técnica lamdas es una forma eficiente de iterar sobre las filas en un marco de datos de Pandas porque convierte las filas en una lista en lugar de la función .iterrows().

Aquí va:

queries_in_df = list(set(keywords_filtered_nonnan.topic.to_list()))
topic_groups_numbered = {}
topics_added = []

def find_topics(si, keyw, topc):
    i = 0
    if (si >= simi_lim) and (not keyw in topics_added) and (not topc in topics_added): 
        i += 1     
        topics_added.append(keyw)
        topics_added.append(topc)
        topic_groups_numbered[i] = [keyw, topc]          
    elif si >= simi_lim and (keyw in topics_added) and (not topc in topics_added):  
        j = [key for key, value in topic_groups_numbered.items() if keyw in value]
        topics_added.append(topc)
        topic_groups_numbered[j[0]].append(topc)

    elif si >= simi_lim and (not keyw in topics_added) and (topc in topics_added):
        j = [key for key, value in topic_groups_numbered.items() if topc in value]        
        topics_added.append(keyw)
        topic_groups_numbered[j[0]].append(keyw) 

def apply_impl_ft(df):
  return df.apply(
      lambda row:
        find_topics(row.si_simi, row.keyword, row.topic), axis=1)

apply_impl_ft(keywords_filtered_nonnan)

topic_groups_numbered = {k:list(set(v)) for k, v in topic_groups_numbered.items()}

topic_groups_numbered

A continuación se muestra un diccionario que contiene todas las palabras clave agrupadas por intención de búsqueda en grupos numerados:

{1: ['fixed rate isa',
  'isa rates',
  'isa interest rates',
  'best isa rates',
  'cash isa',
  'cash isa rates'],
 2: ['child savings account', 'kids savings account'],
 3: ['savings account',
  'savings account interest rate',
  'savings rates',
  'fixed rate savings',
  'easy access savings',
  'fixed rate bonds',
  'online savings account',
  'easy access savings account',
  'savings accounts uk'],
 4: ['isa account', 'isa', 'isa savings']}

Peguemos eso en un marco de datos:

topic_groups_lst = []

for k, l in topic_groups_numbered.items():
    for v in l:
        topic_groups_lst.append([k, v])

topic_groups_dictdf = pd.DataFrame(topic_groups_lst, columns=['topic_group_no', 'keyword'])
                                
topic_groups_dictdf

Los grupos de intención de búsqueda anteriores muestran una buena aproximación de las palabras clave dentro de ellos, algo que un experto en SEO probablemente lograría.

Aunque solo usamos un pequeño conjunto de palabras clave, el método obviamente se puede escalar a miles (si no más).

Activación de las salidas para mejorar su búsqueda

Por supuesto, lo anterior podría llevarse más allá utilizando redes neuronales que procesan el contenido de la clasificación para obtener clústeres y nombres de grupos de clústeres más precisos, como ya lo hacen algunos de los productos comerciales que existen.

Por ahora, con esta salida puedes:

  • Combinar direcciones URL de búsqueda de comercio electrónico de facetas redundantes.
  • Estructure la taxonomía de un sitio de compras de acuerdo con la intención de búsqueda en lugar de un catálogo de productos típico.

Estoy seguro de que hay más aplicaciones que no he mencionado; siéntase libre de comentar sobre las importantes que aún no he mencionado.

En cualquier caso, su investigación de palabras clave de SEO acaba de volverse un poco más escalable, precisa y rápida.

Imagen destacada: Astibuag/Shutterstock.com

Leer el articulo original en Search Engine Journal.

¡Danos un Voto!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¿Tienes una pregunta?

Luis Narciso
Sobre SEO
(Posicionamiento Web)

Frank Fajardo
Sobre Diseño Web, Anuncios, Diseño y Redes Sociales