Как автоматизировать кластеризацию ключевых слов SEO путем поиска с Python

Как автоматизировать кластеризацию ключевых слов SEO путем поиска с Python

< P > Это практическое руководство использует сравнения SERP и Python с ключевыми словами группы по намерениям, быстрее и более интуитивно.

< IMG Width = "1600" height = "840" src = "https://www.searchenginejournal.com/wp-content/uploads/2025/04/data-217.png" class = "Привязанность к размеру "FetchPriority =" high "decoding =" async "srcset =" https://www.searchenginejournal.com/wp-content/uploads/2025/04/data-217.png 1600W, https://www.searchenginejournal.com/wp-content/uploads/2025/04/data-217-480x252.png 480w, https://www.searchenginejournal.com/wp-content/uploads/2025/04/data-217.com 680W, https://www.searchenginejournal.com/wp-content/uploads/2025/04/data-217-384x202.png 384w, https://www.searchenginejournal.com/wp-content/uploads/2025/04/data-217-768x403.png 768w, https://www.searchenginejournal.com/wp-content/2025/04/data-217-1024388.g. = "(Максимальная ширина: 1600px) 100VW, 1600px"/> < p > там & S, чтобы узнать о поиске, от использования глубокого обучения до вывода поиска, вывода поиска путем классификации текста и разбивания типа SERP с использованием методов обработки естественного языка (NLP), до кластеризации на основе семантической значимости, с объясненными преимуществами.

< P > Мы не только знаем преимущества расшифровки намерения поиска, но поэтому у нас есть ряд методов в нашем распоряжении для масштаба и автоматизации.

< p >Итак, зачем нам нужна еще одна статья об автоматизации намерения поиска ?

< p > Поиск намерения теперь все более важны, когда поиск AI прибыл

< P > Хотя больше было общим в эпоху поиска 10 синих ссылок, обратное верно для технологии поиска искусственного интеллекта, поскольку генеральные тезисные платформы стремятся свести к минимуму вычислительные затраты (за провал), чтобы предоставить услугу.

< H2 > SERP по -прежнему содержат наилучшие идеи для поиска < P > Методы до сих пор включают в себя выполнение вашего собственного ИИ, то есть получение всей копии от типа контента ранжирования для данного ключевого слова, а затем подавать его в модель нейронной сети (которую вы должны затем создать и проверить).

~ iframe class = “sej-iframe-car-height” id = “In-content iframe” scrolling = “no” src = “https://www.searchenginejournal.com/wp-json/sscats/v2/tk/middle_post_text” < p >Что если вы не надеваете rsquo; У меня есть время или знания, чтобы построить свой собственный ИИ или вызвать открытый AI API ?~/p > < P > Хотя сходство косинуса рекламировалось, поскольку отвечающие специалисты SEO ориентируются на разработку тематических тем таксономию и структур сайта, я все еще утверждаю, что кластеризация поиска по результатам SERP является гораздо более высоким методом. ~/P > < p > that & rsquo; S, потому что ИИ очень заинтересован в том, чтобы заземлить свои результаты на SERP и по уважительной причине и Ampah; это & ​​amp; rsquo; S моделируется по поведению пользователей.

< p > Есть другой способ, который использует Google & rsquo; S очень собственный ИИ, чтобы выполнить работу за вас, без необходимости очищать все содержимое SERP и создавать модель ИИ.

< p >Пусть & rsquo; S предполагает, что Google оценивает URL -адреса сайта по вероятности того, что контент удовлетворяет пользовательскому запросу в порядке убывания. Отсюда следует, что если намерение для двух ключевых слов одинакова, то серпсы похожи на то, чтобы быть похожими.

< P > В течение многих лет многие специалисты SEO сравнивали результаты SERP для ключевых слов, чтобы сделать вывод общего (или общего) поиска в первую очередь основных обновлений, так что в этом нет ничего нового.

< p > Значение-это автоматизация и масштабирование этого сравнения, предлагая как скорость, так и большую точность.

< H2 > Как кластер ключевые слова с помощью поиска в масштабе в масштабе, используя Python (с кодом)

< P > Предполагая, что у вас есть SERPS, результаты в CSV Download, Let & rsquo; S Импортируйте его в ноутбук Python.

< h3 > 1. Импортировать список в свою записную книжку Python < P > Импорт панд в качестве PD Импортировать Numpy как NP Serps_input = pd.read_csv ('data/sej_serps_input.csv') del serps_input ['United: 0'] Serps_input < P > ниже – SERPS, теперь импортируемый в DataFrame Pandas.

< Img Decoding = "async" src = "https://www.searchenginejournal.com/wp-content/uploads/2025/04/image1-612.png" alt = "" width = "800" class = "size-full wp-image-545598" srcset = "size-full wp-image-545598" = "800" "https://www.searchenginejournal.com/wp-content/uploads/2025/04/image1-612.png 1330w, https://www.searchenginejournal.com/wp-content/uploads/2025/04/image1-612-480x289. https://www.searchenginejournal.com/wp-content/uploads/2025/04/image1-612-680x409.png 680w, https://www.searchenginejournal.com/wp-content/uploads/2025/04/image112388.com/wp-content/uploads/2025/04/image11238-n. 384W, https://www.searchenginejournal.com/wp-content/uploads/2025/04/image1-612-768x462.png 768w, https://www.searchenginejournal.com/wp-content/uploads/2025/04/image1-612-1024x616.png 1024W "Sits =" (MAX-Width: 1330px) 100VW, 1330px "Загрузка =" ~ " < H3 >2. Фильтруя данные для страницы 1

< P > Мы хотим сравнить результаты Page 1 каждого SERP между ключевыми словами.

< P > We & Ll Разделите DataFrame на Mini Keyword DataFrames для запуска функции фильтрации перед рекомбинацией в единый флажок данных, потому что мы хотим отфильтровать на уровне ключевых слов: ~/p > < p ># Расколоть Serps_grpby_keyword = serps_input.groupby (“Ключевое слово”) K_URLS = 15 # Применить комбинацию Def filter_k_urls (group_df): Filtered_df = Group_df.loc [group_df ['url']. Notnull ()] Filtered_df = filtreed_df.loc [filected_df ['rank'] & LT; = k_urls] возврат фильтрованного_дф Filtered_serps = serps_grpby_keyword.apply (filter_k_urls) # Комбинировать ## Добавить префикс к именам столбцов #Normed = normed.add_prefix ('normed_') # Согласен с начальным кадром данных Filtered_serps_df = pd.concat ([filetred_serps], axis = 0) del filtered_serps_df ['Keyword'] Filtreed_serps_df = filtreed_serps_df.reset_index () del filtered_serps_df ['level_1'] Filtered_serps_df < Decoding = "async" class = "wp-image- 413762 size-full" src = "https://www.searchenginejournal.com/wp-content/uploads/2021/1_serps_import-60f41925-sej.png" alt = "altemport file-aMemed filefraMed dataMed. Width = "1246" height = "784" srcset = "https://www.searchenginejournal.com/wp-content/uploads/2021/1_serps_import-60f4192d0f125-sej.png 1246w, https://www.searchenginejournal.com/wp-content/2021/1_serps_import-60f4192d0f125-sej-480x302.png 480w, https://www.searchenginejournal.com/wp-content/2021/1_serps_import-60f4192d0f125-sej-680x428.png 680w, https://www.searchenginejournal.com/wp-content/2021/07/1_serps_import-60f4192d0f125-sej-768x483.png 768w, https://www.searchenginejournal.com/wp-content/2021/1_serps_import-60f4192d0f125-sej-1024x644.png 1024w "Размеры =" (максимум: 1246px). < p > < H3 > 3. Преобразовать URL -адреса ранжирования в строку ~/h3 > < P > Поскольку TERE являются URL -адресами результатов SERP, чем ключевые слова, нам необходимо сжать эти URL -адреса в одну строку, чтобы представлять ключевое слово & S Serp.

< P > ЗДЕСЬ & rsquo; s Как:

< p ># Преобразовать результаты в строки с использованием разделения применить Combine filtserps_grpby_keyword = filtered_serps_df.groupby (“Ключевое слово”) Def string_serps (df): df ['serp_string'] = '' .join (df ['url']))) Вернуть df # combine strung_serps = filtserps_grpby_keyword.apply (string_serps) # Согласен с начальной кадрой данных и чистым Strung_serps = pd.concat ([strung_serps], axis = 0) Strung_serps = strung_serps [['Keyword', 'serp_string']]#. Голова (30) strung_serps = strung_serps.drop_duplicates () Strung_serps < p > ниже показано, что SERP сжала в одну строку для каждого ключевого слова.

< Decoding = "async" class = "wp-image- 413763 size-full" src = "https://www.searchenginejournal.com/wp-content/uploads/2021/2_serp_strung-60f41930648be-sejej.png" alt-ally-spocressed. "Width =" 1118 "height =" 942 "srcset =" https://www.searchenginejournal.com/wp-content/uploads/2021/2_serp_strung-60f41930648be-sej.png 1118W, https://www.searchenginejournal.com/wp-content/uploads/2021/2_serp_strung-60f41930648be-sej-sej-sej-sej-sej-sej-sej-sej-sej https://www.searchenginejournal.com/wp-content/2021/2_serp_strung-60f41930648be-sej-680x573.png 680w, https://www.searchenginejournal.com/wp-content/uploads/207/2_serp_strung-60f41930648be-sej-768x647.png 768w, https://www.searchenginejournal.com/wp-content/2021/2_serp_strung-60f41930648be-1024x863.png 1024w "Размеры =" (максимальная ширина) 100VW, 1118px "Загрузка =" Lazy "> изображение. < H3 > 4. Сравните расстояние SERP < p > Для выполнения сравнения, нам теперь нужна каждая комбинация ключевых слов, в сочетании с другими парами:

< p ># Выравнивать SERP 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'}) Вернуть prime_df Columns = ['Keyword', 'serp_string', 'Keyword_b', 'serp_string_b'] Matched_serps = pd.dataataframe (columns = columns) Matched_serps = matched_serps.fillna (0) Queries = strung_serps.keyword.to_list () Для Q в запросах: Temp_df = serps_align (q, strung_serps) Matched_serps = matched_serps.append (temp_df) Matched_serps < p > < p >< Decoding = "async" class = "Align Center wp-image- 413764 size-full" src = "https://www.searchenginejournal.com/wp-content/uploads/2021/3_serps_aligned-60f419348333be-sej.png". Width = "1940" height = "794" srcset = "https://www.searchenginejournal.com/wp-content/uploads/2021/3_serps_aligned-60f419348333be-sej.png 1940w, https://www.searchenginejournal.com/wp-content/uploads/2021/07/3_serps_aligned-60f419348333be-sej-480x196.png 480w, https://www.searchenginejournal.com/wp-content/2021/07/3_serps_aligned-60f419348333be-sej-680x278.png 680w, https://www.searchenginejournal.com/wp-content/2021/07/3_serps_aligned-60f419348333be-sej-768x314.png 768w, https://www.searchenginejournal.com/wp-content/2021/07/3_serps_aligned-60f419348333be-sej-102419.png 1024w, https://www.searchenginejournal.com/wp-content/2021/3_serps_aligned-60f41934833be-sej-sej-sej-sej-sej-ej-ej- 1600w "sies =" (max-width: 1940px) 100vw, 1940p "(Max-width: 1940px) 100vw, 1940p" hies = "(max-width: 1940px) 100vw, 1940px". ~/p > < P > Выше всего показывают все комбинации Serp Cueword Serp, что делает его готовым для сравнения строк SERP.

< P > Не существует библиотеки с открытым исходным кодом, которая сравнивает объекты списка по порядку, поэтому функция была записана для вас ниже.

< p > Функция & ldquo; Serp_compare & rdquo; Сравнивает перекрытие сайтов и порядок этих сайтов между SERP.

< p >Импорт py_stringmatching как sm ws_tok = sm.whitespacetokenizer () # Сравните только лучшие результаты K_URLS Def serps_similality (serps_str1, serps_str2, k = 15): Деном = k+1 Norm = sum ([2*(1/i – 1,0/(деном)) для i в диапазоне (1, деном)]) #Используйте токенизировать URL -адреса ws_tok = sm.whitespacetokenizer () #Hept только k urls Serps_1 = ws_tok.tekenize (serps_str1) [: k] Serps_2 = ws_tok.tekenize (serps_str2) [: k] #Значить позиции матчей Матч = ЛАБДА А, Б: [Б. Индекс (x) +1, если x в b else none для x в] #positions пересечения формы [(pos_1, pos_2), …] Pos_intersections = [(i+1, j) для i, j in enumerate (match (serps_1, serps_2)), если j не является нет] pos_in1_not_in2 = [i+1 для i, j in enumerate (match (serps_1, serps_2), если j не является]. pos_in2_not_in1 = [i+1 для i, j in enumerate (match (serps_2, serps_1)), если j не является]. a_sum = sum ([abs (1/i -1/j) для i, j in pos_intersections]) b_sum = sum ([abs (1/i -1/denom) для i в pos_in1_not_in2]) c_sum = sum ([abs (1/i -1/denom) для i в pos_in2_not_in1]) intent_prime = a_sum + b_sum + c_sum intent_dist = 1 – (intent_prime/norm) вернуть intent_dist # Применить функцию Matched_serps ['si_simi'] = matched_serps.apply (lambda x: serps_similality (x.serp_string, x.serp_string_b), axis = 1) # Это то, что вы получаете Matched_serps [['Keyword', 'Keyword_b', 'si_simi']]]] < p > < P > 60 ~ Decoding = “async” class = “Align Center wp-image-413766 size-full” src = “https://www.searchenginejournal.com/wp-content/2021/5_serps_map-60f4193cd19d4-se.s.serps_map-60f4193cd19d4-sej.s.s.serps_map-60f4193cd19d4-sej.s.serps_map-60f4193cd19d4-sej.se.s. Порядок этих сайтов SERP. ” Width = “782” height = “800” srcset = “https://www.searchenginejournal.com/wp-content/uploads/2021/5_serps_map-60f4193cd4-sej.png 782W, https://www.searchenginejournal.com/wp-content/2021/07/5_serps_map-60f4193cd19d4-sej-480×491.png 480w, https://www.searchenginejournal.com/wp-content/2021/07/5_serps_map-60f4193cd19d4-sej-680×696.png 680w, https://www.searchenginejournal.com/wp-content/2021/5_serps_map-60f4193cd19d4-sej-78×786.png 768w “Размеры =” (макс. < p >Теперь, когда сравнения были проведены, мы можем начать кластеризировать ключевые слова.

< P > Мы будем лечить любые ключевые слова, которые имеют взвешенное сходство 40% или более.

< p ># Групповые ключевые слова по поиску SIMI_LIM = 0,4 # Присоединяйтесь к тому поиска keysv_df = serps_input [['Keyword', 'search_volume']. keysv_df.head () # Добавление темы Vols Keywords_crossed_vols = serps_compared.merge (keysv_df, on = 'Keyword', как = 'Left') Keywords_crossed_vols = Keywords_crossed_vols.rename (Columns = {'Keyword': 'The Topic', 'Keyword_b': 'Keyword', 'Search_volume': 'topic_volume'}) # Sim si_simi Keywords_crossed_vols.sort_values ​​('topen_volume', ascending = false) # Стричь Нэн Keywords_filtered_nonnan = Keywords_crossed_vols.dropna () Keywords_filtered_nonnan < p > Теперь у нас есть потенциальное имя темы, сходство серп -слова и объемы поиска каждого. < br >< Decoding = "async" class = "Align Center WP-Image-413767 Size-full" src = "https://www.searchenginejournal.com/wp-content/uploads/2021/6_topic_kords-60f4193f69848-se." plustering alstering alstering alstering Ключевые слова. " Width = "982" height = "704" srcset = "https://www.searchenginejournal.com/wp-content/uploads/2021/6_topic_kords-60f419848-sej.png 982w, https://www.searchenginejournal.com/wp-content/2021/6_topic_kords-60f4193f69848-sej-480x344.png 480w, https://www.searchenginejournal.com/wp-content/2021/6_topic_kords-60f4193f69848-sej-680x487.png 680w, https://www.searchenginejournal.com/wp-content/2021/6_topic_kords-60f4193f69848-sej-768x551.png 768w "Размеры =" (максимум) 100VW, 982px "loading =" lazize > 62 > 62 > 62 > 62 > 62 > 62 > 62 ~ 62. ~ 60 > Вы & rsquo; LL отметите, что ключевое слово и ключевое слово_B были переименованы в тему и ключевое слово соответственно.

< p > Теперь мы & Переход к переходу через столбцы в DataFrame с использованием методики Lambda.

< p > Техника лямбда является эффективным способом итерации над строками в пандас -фрейму, поскольку он преобразует строки в список, а не функцию .iterrows ().

< p > Здесь идет:

< p >Queries_in_df = list (matched_serps ['Keyword']. To_list ())))) TOMA_GROUPS = {} def dict_key (dicto, keyo): Вернуть Keoo в Dicto Def dict_values ​​(dicto, vala): Вернуть любой (vala in val для val в dicto.values ​​()) Def What_key (dicto, vala): для k, v in dicto.items (): Если Вала в V: возврат k Def find_topics (si, keyw, topc): if (si & gt; = simi_lim): if (не dict_key (sim_topic_groups, keyw)) и (не dict_key (sim_topic_groups, topc)): if (не dict_values ​​(sim_topic_groups, keyw)) и (не dict_values ​​(sim_topic_groups, topc)): Sim_topic_groups [keyw] = [keyw] sim_topic_groups [keyw] = [topc] Если dict_key (non_sim_topic_groups, keyw): non_sim_topic_groups.pop (keyw) Если dict_key (non_sim_topic_groups, topc): non_sim_topic_groups.pop (topc) if (dict_values ​​(sim_topic_groups, keyw)) и (не dict_values ​​(sim_topic_groups, topc)): d_key = whet_key (sim_topic_groups, keyw) sim_topic_groups [d_key]. Если dict_key (non_sim_topic_groups, keyw): non_sim_topic_groups.pop (keyw) Если dict_key (non_sim_topic_groups, topc): non_sim_topic_groups.pop (topc) if (не dict_values ​​(sim_topic_groups, keyw)) и (dict_values ​​(sim_topic_groups, topc)): d_key = whet_key (sim_topic_groups, topc) sim_topic_groups [d_key]. Если dict_key (non_sim_topic_groups, keyw): non_sim_topic_groups.pop (keyw) Если dict_key (non_sim_topic_groups, topc): non_sim_topic_groups.pop (topc) Elif (keyw в sim_topic_groups) и (не Topc в sim_topic_groups): Sim_topic_groups [keyw]. sim_topic_groups [keyw]. Если keyw в non_sim_topic_groups: non_sim_topic_groups.pop (keyw) Если Topc в non_sim_topic_groups: non_sim_topic_groups.pop (topc) Elif (не Keyw в sim_topic_groups) и (topc в sim_topic_groups): Sim_topic_groups [topc]. Sim_topic_groups [topc]. Если keyw в non_sim_topic_groups: non_sim_topic_groups.pop (keyw) Если Topc в non_sim_topic_groups: non_sim_topic_groups.pop (topc) Elif (keyw в sim_topic_groups) и (topc в sim_topic_groups): Если len (sim_topic_groups [keyw]) & GT; len (sim_topic_groups [topc]): Sim_topic_groups [keyw]. [sim_topic_groups [keyw]. sim_topic_groups.pop (topc) Elif len (sim_topic_groups [keyw]) & LT; len (sim_topic_groups [topc]): Sim_topic_groups [topc]. [sim_topic_groups [topc]. sim_topic_groups.pop (keyw) Elif len (sim_topic_groups [keyw]) == len (sim_topic_groups [topc]): Если sim_topic_groups [keyw] == topc и sim_topic_groups [topc] == keyw: sim_topic_groups.pop (keyw) Elif si & LT; SIMI_LIM: if (не dict_key (non_sim_topic_groups, keyw)) и (не dict_key (sim_topic_groups, keyw)) и (не dict_values ​​(sim_topic_groups, keyw)): non_sim_topic_groups [keyw] = [keyw] if (не dict_key (non_sim_topic_groups, topc)) и (не dict_key (sim_topic_groups, topc)) и (не dict_values ​​(sim_topic_groups, topc)): не DICT_Values ​​(sim_topic_groups, topc)): non_sim_topic_groups [topc] = [topc] < p > ниже показывает словарь, содержащий все ключевые слова, сгруппированные по намерению поиска в пронумерованные группы:

< p >{1: ['Фиксированная скорость ISA', 'ISA ставки', «ИСА процентные ставки», «Лучшие тарифы ISA», «Наличные иса», 'Наличные ставки ISA'], 2: ['' Saving Scount ’, 'Kids Saving Scount'], 3: ['Сберегательный счет', «Сберегательная счетная процентная ставка», «Сберегательные ставки», «Сэкономить с фиксированной скоростью», «Легкая экономия доступа», «облигации с фиксированной ставкой», 'онлайн -сберегательный аккаунт', 'Easy Access Saving Scount', 'Сберегательные счета Великобритания'], 4: ['isa account', 'isa', 'isa savings']} < P > Let & rsquo; S вставьте это в вентилятор данных:

< p >TOMA_GROUPS_LST = [] для k, l в Tape_groups_numbered.items (): Для V в L: TOMA_GROUPS_LST.Append ([K, V]) TOMA_GROUPS_DICTDF = PD.DATATAFAFRAME (TOMA_GROUPS_LST, COLMANS = ['TOMA_GROUP_NO', 'Ключевое слово']) TOMA_GROUPS_DICTDF < IMG Decoding = "async" class = "wp-image- 413768 size-full" src = "https://www.searchenginejournal.com/wp-content/uploads/2021/7_kords_clustered-60f41c9baaaa-sejej.png" alt-frymar Width = "672" height = "1234" srcset = "https://www.searchenginejournal.com/wp-content/uploads/2021/7_kords_clustered-60f41941c9baa-sej.png 672w, https://www.searchenginejournal.com/wp-content/2021/7_keywords_clusered-60f41c9baa-sj-480x881.png 480w "siets =" (max-width) 100VW, 672px "Загрузка =" Lazys ~ 62 < P > Группы по итоге поиска выше показывают хорошее приближение ключевых слов внутри них, чего достиг бы эксперта SEO.

< p > Хотя мы использовали только небольшой набор ключевых слов, метод, очевидно, может быть масштабирован до тысяч (если не больше).

< H2 > Активация выходов, чтобы сделать ваш поиск лучше

< p > Конечно, вышеупомянутое можно принять дальнейшее использование нейронных сетей, обрабатывая контент ранжирования для более точного кластера и кластерной группы < p > На данный момент, с этим выходом, вы можете:

< ul > < li > Включите это в свои собственные системы мониторинга SEO, чтобы сделать ваши тенденции, а SEO сообщали более значимыми.

< li > Постройте лучшие платные поисковые кампании, структурируя свои аккаунты Google Ads с помощью поиска намерения для высокого качества.

< li > УРПЛОВКИ СЕРЕВАННЫХ АСПЕТИ ЭКОМЕМЕРСА.

< li > Структура сайта покупки & S таксономия в соответствии с поиском вместо типичного каталога продуктов.

< p > i & Я уверен, что есть больше приложений, которые я приводит в Haul & rsquo; t упомянуто & ndash; Не стесняйтесь комментировать любые важные, которые я & rsquo; еще не упоминается.

< P > В любом случае, ваше исследование ключевых слов SEO только что получило немного более масштабируемое, точное и быстрее!

< P > Загрузите полный код здесь для вашего собственного использования.

Back To Top