Keywords clusteren met Python

Het doen van een zoekwoordenonderzoek is een taak waar wij SEO specialisten enorm veel tijd aan kwijt zijn. Het verzamelen van de zoekwoorden, het clusteren hiervan en vervolgens deze keywords omzetten naar een contentplan zodat we de content hebben waar onze doelgroep naar zoekt.

Vooral in het clusteren van keywords zit enorm veel werk. Daarnaast is dit een proces wat veel specialisten niet data gedreven wordt omdat dit tijd technisch bijna niet te doen is. Het scheelt eenmaal enorm veel tijd om met eigen kennis van de branche te bepalen of keywords wel of niet bij elkaar passen. Dit zette mij aan het denken, dit moet toch praktischer kunnen?

Daarom ben ik begonnen met het bouwen van een script dat op basis van de overeenkomst van de SERP resultaten bepaald of bepaalde keywords geclusterd zouden moeten worden en op dezelfde pagina gebruikt zouden moeten worden.

Waarom Python en geen LLM?

De logische vraag om te stellen is natuurlijk waarom de keuze is gevallen op een progameertaal als Python en niet een LLM als Chat GPT, Claude of Gemini. Het antwoord was voor mij eigenlijk vrij simpel. Het clusteren van keywords is in mijn ogen het meest accuraat wanneer je dit bepaald op basis van de zoekresultaten. Je kan dit via een LLM doen, maar dit is niet perse essentieel. Daarnaast komt het geregeld voor dat een LLM dingen verzint en niet altijd even zuiver omgaat met data.

Ook werk je met grote datasets waardoor je al snel naar een LLM als Claude moet gaan kijken die vervelend genoeg niet toegankelijk is vanuit Nederland. Toch denk ik dat een LLM hier gewoon simpelweg in dit proces niet de juiste toepassing is. Wat je uiteindelijk met de output gaat doen staat hier natuurlijk los van maar middels Python en de API van SerpAPI ervaar ik geen problemen en merk ik dat ik precies kan doen wat ik wil.

Wat je nodig hebt om het script te laten draaien

Het gebruikmaken van het script is eenvoudig. Mijn collega’s bij Maatwerk Online maken hier ook bij ieder zoekwoordonderzoek gebruik van en besparen zo enorm veel tijd. Wel zijn er een aantal dingen die je moet regelen. Zo moet je Python op je computer hebben staan of deze online draaien middels bijvoorbeeld Google Colab. Daarnaast scraped het script de zoekresultatenpagina, dit doet het middels de API van SerpAPI. Een betaalde tool (vanaf honderd SERP’s) waar je een abonnement op dient te hebben.

Uiteraard kun je de code aanpassen als je een voorkeur hebt voor een andere API of bijvoorbeeld de code op een andere manier in de cloud wilt laten draaien. Dat is zeker mogelijk, houdt er wel rekening mee dat je dan een basiskennis van Python dient te hebben om dit draaiende te krijgen. Als het eenmaal draait werkt het in ieder geval als een raket.

Imports en standaard waarden

We beginnen met het importeren van requests zodat we gebruik kunnen maken van de API van SerpAPI. Daarnaast kunnen we de keywords toevoegen en ook de API key vanuit SerpAPI alvast toevoegen.

import requests

KEYWORDS = Voeg hier je keywords toe als lijst API_KEY_SERPAPI = Voeg hier de API key van SerpAPI toe als string

Functie om de SERP te scrapen

Om te clusteren scrapen we eerst de data vanuit de SERP middels SerpAPI. De onderstaande code gaat de SERP af vanuit het Nederland in het Nederlands.

def scraping_google():
    serp_data = []
    for i in KEYWORDS:
        params = {
            "q": i,
            "google_domain": "google.nl",
            "hl": "nl",
            "gl": "nl",
            "api_key": API_KEY_SERPAPI,
        }
        response = requests.get(url="https://serpapi.com/search", params=params)
        data = response.json()
        serp_data.append(data)
    return serp_data

Functie om de organische top 10 te pakken

De data die we vanuit SerpAPI is een lijst waaruit we enkel de top 10 nodig hebben. Deze functie gaat deze data langs en haalt hier de organische top 10 uit indien deze aanwezig is. Het is niet altijd zo dat de API de top 10 pakt, in dat geval pakt die zoveel als mogeijk.

def get_organic_results(serp_data):
    full_serp = {}
    ammount = 0
    for i in serp_data:
        current_serp = serp_data[ammount]
         += 1
        keyword = current_serp["search_parameters"]["q"]
        rankings = []
        for position in range(0, 9):
            ammount  if position >= len(current_serp["organic_results"]):
                break
            rankings.append(current_serp["organic_results"][position]["link"])
        full_serp[keyword] = rankings
    return full_serp

Functie om keywords te clusteren

Nu we de organische top 10 hebben kunnen we aan de slag met het clusteren van de keywords. Door de lijst met keywords en de bijbehorende top tien langs te gaan zal wanneer er een aantal overeenkomsten zijn deze vervolgens samenworden gevoegd in een dictionary. De hoeveelheid van overeenkomst kan je zelf aanpassen. De sweet spot ligt in mijn ogen tussen de 3 a 4 overeenkomende URL’s.

def clustering_keywords(dict):
    clustered_keywords = {}
    keyword_searched = set()

    for current_keyword, current_url in dict.items():
        if current_keyword in keyword_searched:
            continue

        keyword_searched.add(current_keyword)
        clustered_keywords[current_keyword] = [current_keyword]

        for compared_keyword, compared_url in dict.items():
            if compared_keyword == current_keyword or compared_keyword in keyword_searched:
                continue

            agreements = len(set(current_url) & set(compared_url))

            if agreements >= Vul hier in hoeveel overeenkomende URL's er zijn als een integer:
                clustered_keywords[current_keyword].append(compared_keyword)
                keyword_searched.add(compared_keyword)

    return clustered_keywords

Koppel alles aan elkaar

Vervolgens kunnen we alles aan elkaar koppelen en zetten de lijst van keywords om naar een dictionary met de keywords geclusterd.

import requests

KEYWORDS = Voeg hier je keywords toe als lijst
API_KEY_SERPAPI = Voeg hier de API key van SerpAPI toe als string

def scraping_google():
    serp_data = []
    for i in KEYWORDS:
        params = {
            "q": i,
            "google_domain": "google.nl",
            "hl": "nl",
            "gl": "nl",
            "api_key": API_KEY_SERPAPI,
        }
        response = requests.get(url="https://serpapi.com/search", params=params)
        data = response.json()
        serp_data.append(data)
    return serp_data


def get_organic_results(serp_data):
    full_serp = {}
    ammount = 0
    for i in serp_data:
        current_serp = serp_data[ammount]
         += 1
        keyword = current_serp["search_parameters"]["q"]
        rankings = []
        for position in range(0, 9):
            ammount  if position >= len(current_serp["organic_results"]):
                break
            rankings.append(current_serp["organic_results"][position]["link"])
        full_serp[keyword] = rankings
    return full_serp


def clustering_keywords(dict):
    clustered_keywords = {}
    keyword_searched = set()

    for current_keyword, current_url in dict.items():
        if current_keyword in keyword_searched:
            continue

        keyword_searched.add(current_keyword)
        clustered_keywords[current_keyword] = [current_keyword]

        for compared_keyword, compared_url in dict.items():
            if compared_keyword == current_keyword or compared_keyword in keyword_searched:
                continue

            agreements = len(set(current_url) & set(compared_url))

            if agreements >= Vul hier in hoeveel overeenkomende URL's er zijn als een integer:
                clustered_keywords[current_keyword].append(compared_keyword)
                keyword_searched.add(compared_keyword)

    return clustered_keywords

serp_data = scraping_google()
organic_results = get_organic_results(serp_data)
clustered_keywords = clustering_keywords(organic_results)
print(clustered_keywords)