Buscador de backlinks en Python: una lista de prospectos en cuarenta líneas
Encuentra dominios que enlazan a tus rivales pero no a ti, puntúalos en una sola llamada y ordena el CSV. A continuación se muestra un ejemplo práctico con números hipotéticos.
Equipo editorial de Linkzoid ·
La lógica antes del código
Tres llamadas hacen el trabajo. intersect toma de dos a diez dominios y devuelve quiénes enlazan a varios de ellos. refdomains en tu propio sitio da el conjunto que hay que restar. bulk_dr luego puntúa lo que queda.
El coste por ejecución es mínimo y la aritmética merece la pena hacerla una vez. Dos créditos para la intersección, dos para tu propia lista, uno para puntuar hasta 2.000 dominios. Cinco créditos son $0.0005.
El orden importa. Resta antes de puntuar.
La gente suele puntuar todo primero y filtrar después. Eso es al revés. Puntuar cuesta poco, pero pierde mucho tiempo cuando el CSV tiene cincuenta mil filas. Reduce la lista por superposición primero, pide DR a los supervivientes y mantén todo en un diccionario simple para que una segunda ejecución pueda reutilizar el resultado de ayer.
prospects.py
Los dominios en RIVALS son marcadores de posición. Los nombres de campo se leen con .get, así que revisa una fila cruda de tu propia ejecución antes de confiar en una columna.
python
import csv, json, os, urllib.request as u, urllib.parse as p
KEY = os.environ['LZ_KEY']
ME = 'mysite.example'
RIVALS = ['rival-a.example', 'rival-b.example', 'rival-c.example']
def get(**kw):
q = p.urlencode(kw)
with u.urlopen(f'https://linkzoid.pro/api.php?{q}&key={KEY}', timeout=30) as r:
d = json.load(r)
if not d['ok']:
raise SystemExit(d)
return d
gap = get(action='intersect', q=','.join(RIVALS), per=1000)['rows']
mine = {r.get('domain') for r in get(action='refdomains', q=ME, per=1000)['rows']}
fresh = [r.get('domain') for r in gap if r.get('domain') not in mine]
scores = get(action='bulk_dr', domains=','.join(fresh[:2000]))['rows']
with open('prospects.csv', 'w', newline='') as f:
wr = csv.writer(f)
for row in scores:
wr.writerow([row.get('domain'), row.get('dr')])
print(len(fresh), 'candidates')
Ejemplo práctico, números hipotéticos
Ejecución inventada para un blog de nicho pequeño; la tuya será diferente
Paso
Filas resultantes
Créditos
Intersección de 3 rivales
640 dominios
2
Menos tus propios dominios de referencia
Quedan 410
2
bulk_dr sobre los 410
410 puntuados
1
Mantener DR 20 y superior
unos 120
0
Verificación manual de los 30 primeros
30 páginas abiertas
0
De CSV a outreach, sin spam
01
Ordenar por superposición
Los dominios que enlazan a dos o tres de tus rivales son los que tienen una razón temática para enlazarte a ti. Ponlos primero.
02
Abrir treinta manualmente
Mira la página que enlaza al rival. ¿Es una lista de recursos, una reseña, una noticia? Solo algunas de estas aceptan una nueva entrada.
03
Escribe una línea de razón
Di qué aporta tu página que la página del rival no tiene. Si no puedes decirlo en una frase, salta ese sitio.
04
Registra lo que enviaste
Añade columnas para fecha, contacto y resultado al mismo CSV y haz commit. El próximo trimestre te darás las gracias.
Errores y soluciones
Los scripts de prospección fallan en los mismos pocos lugares
Error
Por qué duele
Solución
Ordenar solo por DR
Los grandes directorios y scrapers flotan hacia arriba
Ordenar por cantidad de superposición primero, DR segundo
Enviar correo a todo lo que esté por encima de un umbral
Parece spam, cuesta buena voluntad
Abrir los 30 primeros manualmente
Codificación URL manual
Las comas y las barras rompen la consulta
Usar urllib.parse.urlencode
Enviar 3.000 dominios en una sola llamada
Por encima del límite de 2.000
Dividir la lista en fragmentos, un crédito por fragmento
Confiar en DR como calidad
Es un recuento a escala logarítmica de dominios de referencia
Trátalo como una clave de ordenación, no como un veredicto
Elegir rivales que compartan tu lector
Los rivales deciden qué devuelve la intersección. Un buscador de backlinks es tan bueno como la lista que le alimentas. Tres competidores directos para el mismo lector dan una superposición limpia, mientras que un editor enorme que posiciona para todo te da miles de enlaces que no dicen nada sobre tu página.
Digamos que tienes un blog pequeño sobre reparación de bicicletas. Tus rivales podrían ser dos blogs de reparación y una tienda con una sección de guías sólida. Ese es un buen conjunto. Añade un medio nacional y la lista se llena de páginas que nunca enlazarían a un blog de bicicletas.
De dos a diez dominios es la ventana que acepta el endpoint, así que elige el conjunto dentro de ese rango. Mantén la lista lo suficientemente corta como para poder nombrar a cada rival de memoria. Las listas cortas son más fáciles de defender.
Por qué los hubs gigantes contaminan el conjunto
Los directorios y agregadores enlazan a casi todo. Aparecen en cada intersección y entierran el puñado de dominios que enlazan por interés real. Lee la parte superior de la lista ordenada antes de confiar en ella.
Un archivo de exclusión simple soluciona la mayoría de esto. Mantén los dominios que nunca quieras en un archivo de texto, uno por línea. Carga esto en un conjunto y elimina las coincidencias antes de la llamada de puntuación, para que los créditos solo se gasten en candidatos que valga la pena leer.
Mantener rivales y tu propio sitio separados
Tu propio dominio nunca debería ser un rival. Parece obvio, pero una lista copiada de un proyecto antiguo a menudo la incluye, y luego la intersección informa tus propios enlaces hacia ti.
Pon los rivales en un diccionario de configuración en la parte superior del script, con un comentario sobre por qué está cada uno. El próximo mes recordarás la razón, y un extraño que lea el repositorio también.
Leer las filas crudas antes de filtrar
El código lee todos los campos con .get, lo que evita que una clave faltante detenga la ejecución. También oculta una clave incorrecta. Imprime una fila de la intersección antes de escribir cualquier filtro, y mira los nombres de campo y el tipo de cada valor.
Una puntuación que llega como texto se ordena como texto, por lo que el 9 queda después del 80. Conviértelo a número una vez, justo después de la llamada, y el resto del script puede mantenerse simple.
Normalizar dominios antes de comparar
El mismo sitio puede aparecer con un prefijo www. en una lista y sin él en otra. Pon todo en minúsculas y elimina el prefijo antes de comparar conjuntos. De lo contrario, tu propio sitio puede parecer un candidato nuevo.
Las barras finales y los espacios extraños de una lista pegada causan el mismo problema. Una función de limpieza de una línea cuesta menos que una llamada de puntuación desperdiciada.
Mantener una copia fechada de cada ejecución
Escribe cada ejecución en un archivo con fecha y mantén el anterior. Así puedes distinguir a los candidatos nuevos de los que ya viste, y ver cuándo un rival empezó a enlazar en otro lugar.
Los archivos con fecha también son la forma más fácil de depurar un resultado extraño. Abre los dos archivos lado a lado y el cambio suele ser obvio.
Puntuar solo lo que sobrevive
La llamada masiva acepta hasta 2.000 dominios por un crédito. Pásale los supervivientes de la resta, nunca la intersección completa. En la ejecución inventada anterior, 640 filas y 410 filas cuestan lo mismo puntuar en una llamada, pero la lista más pequeña es mucho más fácil de leer.
Preguntas antes de ejecutar el buscador
La mayoría de las preguntas que la gente trae a esta parte del trabajo se reducen al coste, la ordenación y qué sucede cuando falla una llamada.
¿Cuesta mucho construir una lista de prospectos?
No mucho. La receta usa intersect, refdomains y bulk_dr, por lo que cinco créditos por ejecución del tamaño mostrado, que son $0.0005. Una reejecución el próximo mes cuesta lo mismo. Tu propio tiempo, dedicado a leer páginas, es el coste real.
¿Por qué no ordenar la intersección por DR y detenerse ahí?
DR cuenta dominios de referencia en una escala logarítmica. Los grandes directorios suben a la cima sin importar su relevancia, así que ordena por superposición primero y usa DR como desempate, no como clave principal.
¿Puedo enviar outreach a todo lo que hay en el CSV?
Puedes, pero es un mal uso de la lista. Abre la página que enlaza al rival, decide si una nueva entrada encaja, y solo entonces escribe. El CSV es una lista corta, no una lista de correo.
¿Cuántos rivales debería empezar con?
Tres es un buen comienzo, dentro del rango de dos a diez que acepta la intersección. Añade más solo cuando la primera ejecución devuelva demasiadas pocas filas para clasificar.
¿Qué pasa si mi propio dominio aún no tiene dominios de referencia?
Entonces la resta no elimina nada, y cada fila de la intersección se convierte en un candidato. Eso es correcto, pero la lista será larga. Redúcela por superposición y lee los treinta primeros manualmente.
¿Necesita el script una clave de pago?
Sí. Las llamadas intersect, refdomains y bulk_dr se facturan por crédito. La acción de resumen gratuita no necesita clave, y el crédito de registro de $100 cubre muchas ejecuciones de este tamaño.
Antes de que salga un solo mensaje
Abre la página candidata y confirma que enlaza al rival, no solo a una lista de enlaces.
Comprueba que la página se adapta a tu lector, no solo a tu palabra clave.
Elimina cualquier dominio al que ya hayas contactado y registra la fecha junto a él.
Escribe una frase sobre lo que aporta tu página, o desecha al candidato.
Envía en pequeños lotes, para que las respuestas puedan ser leídas realmente.
Ejecutar el buscador en un horario
Las listas de prospectos se vuelven obsoletas más lentamente de lo que la mayoría de la gente espera. Mensual es suficiente. Los nuevos enlaces de un rival aparecen con la actualización mensual, por lo que una ejecución cada pocas semanas atrapa la mayoría de ellos. Las ejecuciones semanales principalmente reproducen el archivo de la semana pasada, por eso el mismo buscador de backlinks puede ejecutarse sin supervisión sin mucho ruido.
El ritmo sensato es mensual para la puntuación y una rápida revisión de las filas superiores después de cada ejecución. Mantén el paso de resta dentro del mismo trabajo, para que la lista nunca incluya lo que ya tienes.
Mantener la clave fuera del archivo
El script lee la clave del entorno, por lo que nunca se queda en el repositorio. Establece LZ_KEY como un secreto en tu programador, o expórtalo desde un archivo que se mantenga fuera de git.
Una línea de crontab puede llamar al mismo script con la variable establecida delante. Comprueba que el archivo que contiene la clave tenga permisos estrictos en el servidor.
Fallo antes de escribir el CSV
Un 401 o un 402 deberían detener la ejecución, y también una bandera ok que sea falsa. El código genera una excepción antes de abrir el archivo, por lo que una ejecución fallida nunca sobrescribe el CSV de ayer con uno parcial.
Registrar el gasto con cada ejecución
Cada respuesta lleva _credits, así que imprime el saldo al final del trabajo. En unos pocos meses, esa línea te dirá si un horario cuesta lo que planeaste, y si un bucle ha empezado a volver a obtener páginas.
Páralo con la diferencia de SQLite si quieres el historial en una base de datos en lugar de una carpeta de archivos.
Una palabra sobre lo que DR puede y no puede decir
DR aquí es round(100 veces log(ref_domains + 1) sobre log(20,000,000)). Sube con los dominios de referencia y nada más. Tenlo en cuenta. Un sitio puede estar en 55 y seguir siendo inútil para ti.
Úsalo para clasificar, luego lee. Mira qué publica el sitio, si enlaza a cien tiendas no relacionadas, y si algo en él cambió recientemente. Esas comprobaciones toman un minuto por sitio, y ningún script las reemplaza.
Una vez que la lista esté limpia, guárdala como un archivo con fecha y vuelve a ejecutar en un mes. El manual de ejecución de Actions muestra cómo programarlo, y la comparación con n8n cubre la ruta sin código si tu persona de outreach lo prefiere.
Notas sobre velocidad y tamaño
Cada llamada devuelve hasta 1.000 filas y se factura una vez, por lo que paginar a través de 5.000 filas de intersección cuesta 10 créditos, o $0.001. La paginación profunda se detiene en 50.000 filas. Usa sort y order=desc en el servidor en lugar de ordenar una lista enorme en Python después.