Python per la SEO Semantica: Estrarre Entità e Generare JSON-LD Automaticamente

Cerca:

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Script Python che trasforma un articolo in codice JSON-LD per la SEO semantica

L’Automazione Semantica: Trasformare Articoli in Dati Strutturati con Python

Scrivere un buon articolo oggi è solo metà della fatica.

Puoi aver speso ore a curare ogni singola parola, ma se i motori di ricerca non riescono a “digerire” il tuo testo, hai lavorato per nulla.

Spesso ci affidiamo al caso, lasciando che i bot di Google leggano il contenuto sperando che capiscano il contesto.

Il risultato?

Ottimi articoli che spariscono nei meandri della SERP.

La soluzione non è riempire la pagina di parole chiave sperando di ingannare l’algoritmo, ma iniziare a parlare la lingua madre delle macchine:

i dati strutturati.

Invece di compilare manualmente noiosi form su WordPress o affidarci a plugin che rallentano il sito,  vedremo come automatizzare l’intero processo  con un po’ di Python.

Costruiremo un sistema capace di leggere un testo, capirne le entità principali e tradurlo in un formato che i moderni motori di ricerca adorano.

In questo articolo didattico, costruiremo un generatore semantico scritto in Python.

Non si tratta di un semplice script di scraping, ma di un sistema capace di:

  • Analizzare un URL ed estrarre chirurgicamente le informazioni chiave (Headline, Autore, Date).

  • Identificare entità e FAQ latenti all’interno del testo attraverso regole euristiche e mapping semantico.

  • Costruire un Knowledge Graph in formato JSON-LD, pronto per essere iniettato nel codice HTML per potenziare la SEO tecnica.

Passeremo al setaccio le classi WebAnalyzer e SchemaKnowledgeGraph, vedendo come librerie standard come BeautifulSoup e Requests possano diventare strumenti potenti per il Semantic Web. Che tu sia un analista di dati o un esperto SEO alla ricerca di efficienza, questo viaggio nel codice ti mostrerà come “spiegare” i tuoi contenuti alle macchine, un tag alla volta.

👉 SEO Semantica e IA: Guida Completa all’Evoluzione del Linguaggio nel Digital Marketing


Punti chiave che andremo ad analizzare:

  1. L’estrazione parametrica: Come isolare il contenuto reale dal “rumore” di fondo di una pagina web.

  2. Linking e Identità: L’importanza degli @id e dei riferimenti a Wikipedia per creare autorità semantica.

  3. Logica Booleana e Pattern Matching: La sfida di intercettare domande e risposte (FAQ) all’interno di un discorso fluido.

Dai Testi ai Significati: Il Potere delle Entità (Strings vs. Things)

Nel passato della SEO, i motori di ricerca ragionavano per keyword: se scrivevi “Apple”, il computer cercava quella specifica sequenza di lettere. Ma per un algoritmo moderno, “Apple” è un’entità ambigua: è un frutto o l’azienda di Cupertino?

È qui che entra in gioco il concetto di Entity-Based SEO, un pilastro fondamentale del Web Semantico. Le entità sono i “nodi” di un enorme grafo della conoscenza (Knowledge Graph) che permette alle macchine di comprendere le relazioni tra concetti.

Perché integrare le Entità nel tuo JSON-LD?

Il codice che analizzeremo non si limita a citare dei termini, ma utilizza la proprietà mentions e l’attributo sameAs per dichiarare esplicitamente l’identità di un concetto. Ecco perché questo passaggio è cruciale per la Scienza dei Dati applicata al web:

  • Disambiguazione Totale: Collegando la parola “AI” all’URL di Wikipedia corrispondente, stiamo dicendo a Google: “Non sto solo scrivendo queste due lettere, mi riferisco esattamente a questo concetto enciclopedico”.

  • Costruzione di Autorità (E-E-A-T): Quando il tuo codice mette in relazione il tuo contenuto con entità autorevoli (come Google, Python o PyTorch), stai inserendo il tuo articolo in un “vicinato semantico” di valore, aumentando la fiducia che il motore di ricerca ripone nelle tue informazioni.

  • Preparazione per la SGE (Search Generative Experience): Le nuove intelligenze artificiali di ricerca non cercano più pagine, ma risposte basate su relazioni tra entità. Fornire dati strutturati puliti significa parlare la lingua nativa dei nuovi LLM.

Nota tecnica: Nel nostro script, la classe WebAnalyzer funge da “ponte” tra il testo non strutturato e il database delle entità, trasformando una lettura passiva in un collegamento attivo verso la conoscenza globale.

💡 Curiosità: Il Big Bang delle Entità

Molti pensano che la rivoluzione semantica sia recente, ma la sua pietra miliare risale al 2010. In quell’anno, Google acquisì Metaweb, una piccola azienda che aveva creato Freebase, un database collaborativo di entità (simile a Wikipedia, ma strutturato per le macchine).

L’obiettivo di Google era chiaro: smettere di essere un semplice indice di pagine e diventare un motore di risposte. Proprio dai dati di Freebase è nato quello che oggi conosciamo come Knowledge Graph (il box informativo che appare a destra nelle ricerche). Acquisendo Metaweb, Google ha ufficialmente sancito il passaggio dall’era delle “Keywords” (parole chiave isolate) all’era delle “Entities” (concetti connessi), trasformando per sempre il modo in cui i dati vengono estratti e interpretati.

Forse potrebbe interessarti anche:  Distribuzione Gamma in Python: MLE, Bayes e mixture con 3 esercizi svolti

Passiamo al codice: L’architettura del Generatore

Per trasformare un articolo in un nodo del Web Semantico, abbiamo bisogno di una struttura che sia al tempo stesso un chirurgo (per estrarre i dati) e un architetto (per ricostruirli). Lo script si divide in due classi principali: WebAnalyzer, che si occupa del Natural Language Processing rudimentale e dello scraping, e SchemaKnowledgeGraph, che modella l’output secondo gli standard internazionali.

Ecco il listato completo commentato:

1. Importazioni e Setup Iniziale

Questa sezione contiene le librerie necessarie.

Nota l’uso di BeautifulSoup per il parsing e re per la manipolazione del testo.

import json
import requests
import re
from datetime import datetime
from urllib.parse import urlparse
from bs4 import BeautifulSoup
from typing import List, Dict

# Configurazione iniziale: utile per definire i tipi di dati attesi

2. La Classe SchemaKnowledgeGraph (L’Architetto)

Questa classe si occupa esclusivamente di trasformare i dati grezzi in oggetti conformi agli standard di Schema.org.

È qui che avviene la magia del “Linking” tramite gli @id.

class SchemaKnowledgeGraph:
    """Gestisce la creazione del grafo e il linking semantico."""
    
    def __init__(self, base_url: str, organization_name: str):
        self.base_url = base_url.rstrip('/')
        self.organization_name = organization_name
        self.org_id = f"{self.base_url}/#organization"

    def _add_context(self, data: Dict) -> Dict:
        """Aggiunge il contesto obbligatorio JSON-LD."""
        return {"@context": "https://schema.org", **data}

    def create_faq_node(self, faqs: List[Dict]) -> Dict:
        """Costruisce il nodo FAQPage per i Rich Results di Google."""
        if not faqs: return {}
        return self._add_context({
            "@type": "FAQPage",
            "mainEntity": [
                {
                    "@type": "Question",
                    "name": f["q"],
                    "acceptedAnswer": {"@type": "Answer", "text": f["a"]}
                } for f in faqs
            ]
        })

    def create_article(self, data: dict, entities: List[Dict]) -> Dict:
        """Crea l'oggetto Article con ID univoci per autore e publisher."""
        slug = re.sub(r'\W+', '-', data.get('author_name', 'staff').lower()).strip('-')
        person_id = f"{self.base_url}/profile/{slug}/#person"
        
        return self._add_context({
            "@type": "Article",
            "@id": f"{data['url']}#article",
            "headline": data.get('headline'),
            "description": data.get('description'),
            "datePublished": data.get('date_published'),
            "author": {"@id": person_id},
            "publisher": {"@id": self.org_id},
            "mentions": entities 
        })

    def to_json_ld(self, schema_object: dict) -> str:
        return json.dumps(schema_object, indent=2, ensure_ascii=False)

3. WebAnalyzer: Estrazione di FAQ ed Entità

In questa parte del codice, implementiamo l’euristica per “capire” il testo.

Cerchiamo pattern interrogativi e mappiamo le entità verso Wikipedia.

class WebAnalyzer:
    """Motore di analisi testuale e scraping."""

    @staticmethod
    def extract_faqs(soup: BeautifulSoup) -> List[Dict]:
        """Estrae domande dai titoli H2/H3 seguiti da paragrafi."""
        faqs = []
        headers = soup.find_all(['h2', 'h3'])
        for h in headers:
            text = h.get_text(strip=True)
            if "?" in text or any(word in text.lower() for word in ["come", "perché", "cosa"]):
                next_p = h.find_next_sibling('p')
                if next_p and len(next_p.get_text()) > 50:
                    faqs.append({"q": text, "a": next_p.get_text(strip=True)})
        return faqs[:5]

    @staticmethod
    def extract_mentions(full_text: str) -> list:
        """Collega il testo a entità esterne (Wikipedia)."""
        # Dizionario allineato al tema dell'articolo (Cloud, DevOps, Terraform)
        ENTITY_MAP = {
            "Terraform": "https://en.wikipedia.org/wiki/Terraform_(software)",
            "DevOps": "https://it.wikipedia.org/wiki/DevOps",
            "Cloud": "https://it.wikipedia.org/wiki/Cloud_computing",
            "Intelligenza Artificiale": "https://it.wikipedia.org/wiki/Intelligenza_artificiale"
        }
        mentions = []
        for name, url in ENTITY_MAP.items():
            if re.search(rf'\b{re.escape(name)}\b', full_text, re.IGNORECASE):
                mentions.append({"@type": "Thing", "name": name, "sameAs": url})
        return mentions

4. WebAnalyzer: Fetching e Pulizia HTML

Qui gestiamo la connessione HTTP e la pulizia del DOM.

Eliminare il “rumore” (footer, script) è fondamentale per non sporcare il dataset.

@staticmethod
    def fetch_and_extract(url: str) -> dict:
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
        try:
            res = requests.get(url, headers=headers, timeout=15)
            res.raise_for_status()
            soup = BeautifulSoup(res.text, 'html.parser')

            # Decomposizione dei tag inutili
            for tag in soup(["script", "style", "nav", "footer", "aside"]):
                tag.decompose()

            # Recupero metadati base
            site_name = (soup.find('meta', attrs={'property': 'og:site_name'}) or urlparse(url).netloc)
            headline = soup.find('h1').get_text(strip=True) if soup.find('h1') else soup.title.string
            
            return {
                'url': url,
                'site_name': site_name,
                'author_name': "Staff", # Fallback semplice
                'headline': headline,
                'full_text': soup.get_text(),
                'faqs': WebAnalyzer.extract_faqs(soup),
                'description': (soup.find('meta', attrs={'name': 'description'}) or {}).get('content', ''),
                'date_published': datetime.now().date().isoformat()
            }
        except Exception as e:
            print(f"Errore: {e}")
            return None

5. Il Main Loop (Esecuzione)

L’ultima parte che mette insieme i pezzi: riceve l’input dall’utente e stampa i blocchi JSON-LD pronti per l’uso.

def main():
    print("🚀 GENERATORE SEMANTICO IN CORSO...")
    target_url = input("🔗 Inserisci l'URL dell'articolo: ").strip()
    
    data = WebAnalyzer.fetch_and_extract(target_url)
    
    if data:
        domain = f"{urlparse(target_url).scheme}://{urlparse(target_url).netloc}"
        kg = SchemaKnowledgeGraph(domain, data['site_name'])
        
        # Generazione Articolo ed Entità
        mentions = WebAnalyzer.extract_mentions(data['full_text'])
        article_json = kg.create_article(data, mentions)
        
        # Output formattato per WordPress
        print("\n--- COPIA IL CODICE SOTTO ---")
        print(f'')
        
        faq_json = kg.create_faq_node(data['faqs'])
        if faq_json:
            print(f'\n')

if __name__ == '__main__':
    main()

L’output Finale

--- GENERATORE DI DATI STRUTTURATI SEMANTICI ---
Inserisci l'URL dell'articolo: https://frontiereevolutive.altervista.org/terraform-cose-come-funziona-e-perche-e-indispensabile-per-devops-e-cloud-engineer/

==============================
CODICE JSON-LD PRONTO PER IL TUO SITO
==============================

<!-- Schema Article -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "@id": "https://frontiereevolutive.altervista.org/terraform-cose-come-funziona-e-perche-e-indispensabile-per-devops-e-cloud-engineer/#article",
  "headline": "Terraform: Cos’è, Come Funziona e Perché È Indispensabile per DevOps e Cloud Engineer",
  "description": "Terraform è il linguaggio universale del cloud: dichiarativo, sicuro, scalabile. Scopri come funziona, perché i recruiter lo vogliono e come prepararti al colloquio.",
  "datePublished": "2026-05-01",
  "author": {
    "@type": "Person",
    "@id": "https://frontiereevolutive.altervista.org/profile/frontiere-evolutive/#person",
    "name": "Frontiere Evolutive"
  },
  "publisher": {
    "@type": "Organization",
    "@id": "https://frontiereevolutive.altervista.org/#organization",
    "name": null
  },
  "mentions": [
    {
      "@type": "Thing",
      "name": "Terraform",
      "sameAs": "https://en.wikipedia.org/wiki/Terraform_(software)"
    },
    {
      "@type": "Thing",
      "name": "DevOps",
      "sameAs": "https://it.wikipedia.org/wiki/DevOps"
    },
    {
      "@type": "Thing",
      "name": "Cloud",
      "sameAs": "https://it.wikipedia.org/wiki/Cloud_computing"
    },
    {
      "@type": "Thing",
      "name": "Intelligenza Artificiale",
      "sameAs": "https://it.wikipedia.org/wiki/Intelligenza_artificiale"
    },
    {
      "@type": "Thing",
      "name": "Google",
      "sameAs": "https://it.wikipedia.org/wiki/Google"
    }
  ]
}
</script>

<!-- Schema FAQPage -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Perché i recruiter lo pretendono?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Se Terraform appare in ogni job description, è perché risolve il problema più costoso di ogni azienda tech:l’incoerenza."
      }
    },
    {
      "@type": "Question",
      "name": "L’era dell’AI: Terraform è ancora utile?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Potresti pensare che l’intelligenza artificiale possa rendere obsoleti questi strumenti. In realtà, sta accadendo l’esatto contrario. Gli agenti AI sono bravissimi a generare codice Terraform, ma hanno bisogno di un framework rigido e sicuro per eseguirlo."
      }
    },
    {
      "@type": "Question",
      "name": "Vale la pena impararlo?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Sì. Non è solo uno strumento in più nella cassetta degli attrezzi; è un cambio di paradigma. Imparare Terraform oggi significa imparare a gestire la complessità del cloud moderno senza impazzire. Se punti a ruoli come Cloud Engineer, DevOps o SRE, non è un’opzione: è il biglietto d’ingresso."
      }
    },
    {
      "@type": "Question",
      "name": "1. Cosa devi sapere “prima” di iniziare",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Terraform non vive nel vuoto. Prima di installarlo, assicurati di avere una vaga idea di:"
      }
    },
    {
      "@type": "Question",
      "name": "2. Il “Modello Mentale” (Come ragiona Terraform)",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Prima di scrivere codice, devi capire come pensa lo strumento. Immagina che Terraform sia unmaggiordomo molto pignolo:"
      }
    }
  ]
}
</script>

Spiegazione

La Potenza delle “Mentions” (Entity-Based SEO)

La sezione mentions è la vera marcia in più. Invece di limitarsi a dichiarare l’argomento principale, lo script ha identificato entità specifiche come Terraform, DevOps e Cloud computing.

  • Perché è fondamentale: L’uso della proprietà sameAs con link a Wikipedia dice a Google: “Quando parlo di Terraform, intendo esattamente l’entità software definita qui”. Questo elimina ogni ambiguità (disambiguazione) e posiziona l’articolo all’interno di un cluster di argomenti autorevoli.

Forse potrebbe interessarti anche:  Analisi della Sopravvivenza e LTV: Dalla Curva di Kaplan-Meier al Modello di Cox

Il passaggio dai testi ai significati.

Per capire perché le mentions e le entità siano così rivoluzionarie, dobbiamo immaginare come ragiona un motore di ricerca oggi rispetto a dieci anni fa.

Ecco un approfondimento dettagliato sull’obiettivo di questa strategia.

 Il Problema della Polisemìa (L’Ambiguità)

Le parole, da sole, sono spesso ambigue.

Se in un articolo scrivo la parola “Terraform”, per un algoritmo potrebbe essere:

  1. Un software di Infrastructure as Code (HashiCorp).

  2. Un processo fantascientifico per rendere abitabile un pianeta (Terraforming).

  3. Il nome di un album musicale o di un videogioco.

Senza dati strutturati, Google deve “indovinare” il contesto analizzando le altre parole. Se però usiamo la proprietà sameAs puntando alla pagina Wikipedia del software, stiamo fornendo un ID univoco globale. È come dare a Google il codice fiscale del concetto di cui stiamo parlando: l’ambiguità scende a zero.

L’Obiettivo: Entrare nel “Knowledge Graph”

Google non è più un semplice elenco di siti, ma un enorme Grafo della Conoscenza. Questo grafo è una ragnatela di relazioni tra concetti: “Terraform” è collegato a “DevOps”, che è collegato a “Software Engineering”, che è collegato a “Cloud Computing”.

Quando inserisci le mentions nel tuo JSON-LD, stai dicendo a Google: “Il mio articolo è un nuovo nodo che si aggancia esattamente a questi punti del tuo grafo”.

  • Risultato: Google non ti indicizza solo per la parola chiave “Terraform”, ma ti riconosce come una risorsa autorevole all’interno dell’intero ecosistema Cloud/DevOps.

 “Strings vs. Things” (Stringhe contro Cose)

Questo è il mantra di Google dal 2012.

  • Stringhe: Sequenze di lettere (es. “T-e-r-r-a-f-o-r-m”). Vecchia SEO.

  • Cose (Entities): Concetti reali con attributi e relazioni. Nuova SEO.

L’obiettivo delle mentions è trasformare il tuo testo da una “stringa” a una “cosa”. Se l’algoritmo capisce che il tuo articolo parla di entità specifiche, può mostrarti non solo a chi cerca “Cos’è Terraform”, ma anche a chi sta facendo ricerche correlate nel settore DevOps, perché ha capito che il tuo contenuto è semanticamente vicino a quei temi.

Forse potrebbe interessarti anche:  Il Teorema di Čebyšëv: Fondamenti e Applicazioni nella Scienza dei Dati

L’impatto sulla SGE e l’IA Generativa

Le nuove interfacce di ricerca basate su AI (come Google Search Generative Experience o Perplexity) non si limitano a linkare siti, ma sintetizzano risposte. Queste IA estraggono informazioni dai siti che offrono i dati più “puliti” e strutturati. Dichiarare esplicitamente le entità tramite le mentions rende il tuo articolo una fonte privilegiata per l’IA, perché le risparmi la fatica di dover interpretare il testo: glielo stai già servendo in un formato che i suoi modelli linguistici (LLM) comprendono nativamente.

In sintesi, l’obiettivo è:

Passare dalla speranza che Google capisca di cosa parli, alla certezza matematica di avergli comunicato l’identità precisa dei concetti trattati, legandoli a fonti di autorità universale (come Wikipedia o DBpedia).

Questo processo trasforma un semplice post sul blog in un pezzo di documentazione ufficiale agli occhi della macchina.

 Architettura degli ID (@id)

L’output utilizza correttamente gli identificatori univoci:

  • #article: Definisce il nodo principale dell’articolo.

  • #person e /#organization: Creano relazioni gerarchiche chiare. Questo permette ai motori di ricerca di capire che l’autore non è solo una stringa di testo, ma un’entità “Persona” collegata a un’entità “Organizzazione” (il sito web), rafforzando i segnali di E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness).

Trasformazione delle FAQ in Rich Results

Il blocco FAQPage è formattato per attivare i cosiddetti Rich Snippets (i menu a tendina che appaiono direttamente nei risultati di ricerca).

  • Analisi dell’estrazione: L’euristica ha funzionato bene, isolando domande cruciali come “L’era dell’AI: Terraform è ancora utile?”.

  • Nota di miglioramento: Nell’ultima FAQ, il testo estratto è “Immagina che Terraform sia unmaggiordomo…”. C’è un piccolo refuso (manca lo spazio tra ‘un’ e ‘maggiordomo’), ereditato probabilmente dal testo originale. Questo dimostra quanto l’automazione sia precisa nel riflettere la qualità della fonte.

Coerenza del Context e Vocabolario

L’uso di @context: [https://schema.org](https://schema.org) garantisce che il codice sia interpretato correttamente non solo da Google, ma anche da Bing, Yahoo e dai futuri sistemi di AI Overviews (SGE). Questi ultimi, in particolare, leggono i dati strutturati per sintetizzare le risposte che gli utenti vedono in cima ai risultati di ricerca.

Perché questo script è interessante dal punto di vista applicativo?

L’eleganza di questo script risiede nell’uso delle euristiche basate sul DOM al posto di pesanti modelli di Machine Learning.

  • Il pattern matching delle FAQ (La logica Booleana): Estrarre le FAQ da un testo libero è notoriamente complesso. Questo script utilizza un approccio pragmatico: invece di usare l’Intelligenza Artificiale per “capire” se una frase è una domanda, sfrutta la struttura semantica dell’HTML. Cerca i tag <h2> o <h3>, controlla se contengono un punto interrogativo o pronomi interrogativi (chi, come, cosa) e, se è così, assume che il paragrafo <p> immediatamente successivo sia la risposta. È una soluzione a basso costo computazionale ma ad altissima resa per siti strutturati bene.

  • Entità hardcoded vs dinamiche: La funzione extract_mentions utilizza un dizionario statico (ENTITY_MAP). A fini didattici è perfetto perché mostra esattamente cosa succede dietro le quinte (il mapping tra una stringa nel testo e l’URI di Wikipedia). In un’applicazione aziendale reale, questa funzione verrebbe sostituita da una chiamata alle API di Google NLP o implementata tramite librerie come spaCy, che riconoscono automaticamente le entità (Named Entity Recognition – NER) dinamicamente.

  • Generazione dell’ID tramite Slug: La creazione di @id univoci (es. /#person o /#article) è il cuore del Linked Data. Lo script automatizza la “slugificazione” del nome dell’autore con le RegEx (re.sub(r'\W+', '-', ...)) per garantire che gli URL generati per il Knowledge Graph siano sempre validi e senza spazi, rispettando gli standard del W3C.


L’esercizio dimostra come la Data Science possa essere applicata al Marketing Digitale. Non si scrive più solo per gli umani, ma si prepara il contenuto per essere “interrogabile” dalle macchine come se fosse un database.

Pubblicità