Vai al contenuto

Dati dei backlink in JSON: $100 di credito gratuito, nessuna carta richiesta, accesso con Google.

SEOMasters.dev
SEOMasters.devRegistrati

DR in batch per una lista di clienti, come un lavoro Python di 40 righe

Hai un foglio di calcolo con i domini e una dashboard che richiede un numero per riga. Un controllo dei domini dei backlink per questo lavoro è principalmente un'infrastruttura, e questo script è proprio quell'infrastruttura.

Mani che ordinano blocchi di legno in pile su un banco da lavoro

Lo script

Legge domains.txt, invia 200 domini per richiesta, salva ogni risposta grezza in SQLite e stampa il costo della esecuzione. Salviamo l'intero payload perché i nomi dei campi sono meglio copiati da una risposta reale, non da un post sul blog.

python
import os, sqlite3, time, json, requests

BASE = "https://seomasters.dev/api.php"
KEY = os.environ["SEO_API_KEY"]
BATCH = 200

db = sqlite3.connect("dr.db")
db.execute("create table if not exists raw (ts int, batch text, body text)")

domains = [d.strip() for d in open("domains.txt") if d.strip()]
spent = 0
for i in range(0, len(domains), BATCH):
    chunk = domains[i:i + BATCH]
    for attempt in range(4):
        try:
            r = requests.get(BASE, timeout=30,
                params={"action": "bulk_dr", "domains": ",".join(chunk)},
                headers={"Authorization": "Bearer " + KEY})
            break
        except requests.RequestException:
            time.sleep(2 ** attempt)
    else:
        raise SystemExit(f"network gave up at batch {i}")
    if r.status_code in (401, 402):
        raise SystemExit(f"HTTP {r.status_code}: fix the key or top up, do not retry")
    body = r.json()
    if not body.get("ok"):
        raise SystemExit(f"ok=false at batch {i}: {json.dumps(body)[:300]}")
    db.execute("insert into raw values (?,?,?)", (int(time.time()), str(i), r.text))
    db.commit()
    print(body.get("_credits"))

Cosa fa ogni parte

action=bulk_dr

Un credito per chiamata. Il limite documentato è di 2.000 domini per chiamata.

domains=

Un parametro GET qui. L'endpoint accetta anche un corpo POST, che è la scelta migliore quando le liste diventano lunghe. Testa il separatore con due domini prima di un'esecuzione completa.

BATCH = 200

La nostra abitudine, non un limite: 200 domini brevi mantengono l'URL ben al di sotto dei limiti comuni dei proxy.

_credits

Presente nelle risposte autenticate: il costo della chiamata e quanto rimane. Stamparlo ogni batch è la traccia di audit più economica.

Colonna body grezza

Lo analizzi in seguito, una volta sola, contro un campione memorizzato. Una modifica allo schema da parte nostra ti costerà una query, non una riesecuzione.

Bilancia in ottone che bilancia pesi per mostrare un calcolo preciso

Un'esecuzione ipotetica, con i calcoli

Questo è un esempio, non una storia di un cliente. Immagina un'agenzia che monitora 1.800 domini di clienti e prospect in un Google Sheet e vuole aggiornare il DR ogni lunedì.

A 200 domini per batch sono 9 richieste. Nove richieste a 1 credito ciascuna sono 9 crediti, ovvero $0,0009 per esecuzione, e su 52 lunedì il totale è di 468 crediti, che arrotondati sono meno di cinque centesimi.

Il costo non è il vincolo. La freschezza sì. L'indice si ricostruisce circa mensilmente, quindi esecuzioni settimanali mostreranno gli stessi valori per tre settimane su quattro, e un'esecuzione mensile cattura lo stesso movimento per circa un quarto delle chiamate.

Quindi eseguilo mensilmente e mantieni il foglio settimanale per le modifiche umane. I dettagli sul motivo per cui il punteggio può rimanere fermo sono nel riferimento DR.

Cose che possono andare storte in questo script

SintomoCausaSoluzione
SystemExit: HTTP 402Saldo zeroRicarica dalla pagina dell'account, riesegui; i batch completati sono già in SQLite
SystemExit: HTTP 401Variabile d'ambiente vuota o errore di battitura nella chiaveStampa len(KEY) e controlla il prefisso sk_
ok=false nel batch 3Valore errato nella lista, come un URL completoRimuovi schema e percorso prima di inviare, vedi la tabella degli errori
Stesso DR della settimana scorsaL'indice non si è ancora ricostruitoPrevisto; confronta mensilmente
URL lungo rifiutatoBatch troppo grande per GETRiduci BATCH o passa a un corpo POST

Dimensione del batch, GET e POST per liste lunghe

Il limite è di 2.000 domini per chiamata, e lo script invia un decimo di quello. Ogni chiamata costa lo stesso credito fisso, quindi la dimensione del batch è una questione di fallimento e payload, non di prezzo.

Perché 200 e non 2.000

Un batch più piccolo fallisce in modo economico. Se un'esecuzione si interrompe a metà, la coda lasciata da rifare è lunga un batch, non una lista intera.

Liste più brevi mantengono anche ogni corpo salvato abbastanza piccolo da essere scansionato a occhio quando un numero sembra errato, e questo conta più di alcune chiamate salvate.

Se in seguito aumenti la dimensione del batch, fallo una volta sola, in una costante, e riesegui il test con due domini. Un numero più grande non è un motivo per saltare il test.

Pianifica il batch in base alla durata dell'esecuzione che puoi tollerare, non al limite. Un lavoro notturno che deve terminare prima di un rapporto mattutino può permettersi batch più piccoli e più sicuri rispetto a un riempimento una tantum.

GET per liste brevi, POST per quelle lunghe

La forma GET inserisce ogni dominio nell'URL. Questo funziona finché un proxy o una riga di log non tronca la query, motivo per cui la tabella sopra dice di ridurre prima il batch. Una volta che le liste crescono, invia lo stesso valore domains in un corpo POST.

Testa il separatore e l'encoding con due domini prima di un'esecuzione completa. Una virgola stray appare nel primo batch, ed è più economico vederla lì.

Un corpo POST mantiene anche la lista fuori dai log di accesso che molti host tengono di default. Questo è un piccolo guadagno di privacy per le liste di clienti, e costa una riga di intestazione in più nello script.

Quando passi a POST, mantieni la versione GET dello script come fallback per le liste brevi. Due percorsi di codice sembrano pesanti, ma una singola piccola funzione che sceglie in base alla lunghezza è facile da leggere e da testare.

Pulisci e rimuovi i duplicati prima della prima richiesta

Rimuovi gli spazi bianchi, metti in minuscolo l'host e elimina i duplicati prima che qualsiasi cosa lasci la tua macchina. I duplicati occupano spazio sotto il limite di 2.000 domini, e fanno sì che il conteggio nel tuo foglio non corrisponda al conteggio nella risposta.

Scegli una regola per www. e applicala in una singola funzione, in modo che lo stesso sito non venga mai cercato con due grafie diverse. Qualsiasi controllo dei domini dei backlink che scala oltre poche centinaia di nomi ha bisogno di questa disciplina.

Cosa dovrebbe dire il log dell'esecuzione

Stampa il valore _credits dopo ogni batch, e scrivi il numero del batch, il conteggio dei domini e l'ora accanto. Questi tre numeri rispondono a quasi tutte le domande che un lettore finanziario farà su un'esecuzione.

Un'esecuzione che non stampa nulla fino alla fine non ti dà alcun indizio quando si blocca. Una riga per batch è economica, e trasforma un blocco silenzioso in un numero di batch che puoi nominare.

Mantieni il log nella stessa cartella del file SQLite, in modo che un backup copi entrambi. Un log che vive da qualche altra parte è quello che va perso durante un incidente.

Giunzione di legno finita in piedi separata dal legno grezzo

Tre estensioni che valgono il pomeriggio

Memorizza il numero del batch accanto al timestamp. È già nella tabella sopra, e ti permette di rieseguire solo il batch che è fallito dopo un 402 a metà esecuzione.

Scrivi una piccola vista sulla tabella grezza una volta che hai ispezionato una risposta reale: dominio, punteggio, data di recupero. Le dashboard leggono la vista, e la colonna grezza rimane come tua prova se un numero viene messo in discussione.

Eseguilo da GitHub Actions o da un semplice cron su un piccolo VPS. Entrambi vanno bene. Ciò che conta è che il lavoro esiti con codice diverso da zero in caso di errore, perché un errore silenzioso sembra un grafico obsoleto tre settimane dopo.

L'ordinamento dell'output è una questione di front-end. Ordina il portafoglio per punteggio, raggruppalo o confrontalo con dr_distribution (1 credito) per vedere dove si trova ogni cliente tra tutti i 181.132.097 domini.

Deriva dei campi e la tabella grezza

Un lavoro a lungo termine fallisce silenziosamente quando un campo cambia forma. La colonna grezza c'è affinché il fallimento rimanga rumoroso e facile da risolvere.

Memorizza prima il corpo grezzo

La colonna grezza è la rete di sicurezza. Se un campo viene rinominato o ne appare uno nuovo, riesegui una query sulle risposte memorizzate invece di pagare per l'intera lista di nuovo. Analizzare in seguito è economico, mentre riacquistare no.

Tieni anche un campione salvato per settimana in un file a parte. Quando un'analisi si interrompe, confronta il campione di questa settimana con l'ultimo che ha funzionato.

Scrivi il corpo esattamente come ricevuto, senza formattazione e senza trimming. Qualsiasi modifica apportata al testo prima di salvarlo è una modifica che non potrai annullare in seguito.

Come appare la deriva nella pratica

Supponiamo che una dashboard mostri improvvisamente punteggi vuoti per un batch. La riga grezza è ancora lì. La apri, confronti le sue chiavi con il campione della settimana scorsa e trovi la differenza in pochi minuti.

La correzione è poi una singola riga nella vista, non una riesecuzione dell'intera lista. Questo è il punto principale dello storage del corpo.

Tieni una breve nota accanto alla vista che dice quale campo legge e quando l'hai controllata l'ultima volta contro una risposta reale. La nota richiede un minuto per essere scritta e risparmia una lunga ricerca in seguito.

Ordina le migrazioni con i dati

Crea la tabella grezza prima della vista, e la vista prima di qualsiasi query della dashboard. Tieni le istruzioni di creazione in un file, eseguile in ordine e registra il numero del batch con ogni riga.

Database separati per cliente derivano allo stesso modo di un database condiviso. La regola rimane la stessa: un corpo memorizzato per chiamata, e un unico punto dove analizzarlo.

Tieni il parser accanto ai test

Metti la funzione di parsing nello stesso repository di un test che legge un corpo memorizzato. Il test è il punto in cui un campo derivato appare per la prima volta, molto prima che lo faccia un grafico.

Nomina i campi che il parser si aspetta in una costante vicino all'inizio del file. Un revisore può così vedere tutte le dipendenze dalla forma della risposta in un'unica schermata.

Prima esecuzione, in ordine

  1. 1

    Testa un dominio

    Chiama bulk_dr con un singolo dominio che conosci, e leggi l'intera risposta. Annota le chiavi prima di scrivere qualsiasi codice di parsing.

  2. 2

    Esegui due batch

    Fornisci allo script una lista di 400 domini, in modo che vengano eseguiti esattamente due batch. Controlla che la diminuzione di _credits corrisponda a due chiamate a un credito ciascuna.

  3. 3

    Conta le righe memorizzate

    Apri il file SQLite e confronta il conteggio delle righe con il conteggio dei batch. Una discrepanza significa che un batch è stato saltato o memorizzato due volte, e lo scopri prima che lo faccia la dashboard.

  4. 4

    Pianifica la lista completa

    Solo dopo che i test sono puliti, aggiungi la lista completa e il scheduler. Mantieni l'uscita non zero, in modo che un errore sia rumoroso dalla prima notte.

Prima di pianificarlo

  • Rimuovi i duplicati e metti in minuscolo la lista prima
  • Decidi una volta, in una funzione, se www. rimane o va via
  • Tieni la chiave in un archivio segreto, non nel crontab
  • Allerta su un codice di uscita diverso da zero
  • Esegui i numeri del budget di crediti per il tuo volume