Ir al contenido

Datos de backlinks en JSON: $100 de crédito gratuito, sin tarjeta, inicio de sesión con Google.

SEOMasters.dev
SEOMasters.devRegistrarse

Navega por un verificador de backlinks por URL sin huecos ni bucles infinitos

Filas por llamada, páginas por consulta y un límite estricto de 50.000. Aquí tienes un bucle que respeta las tres condiciones y te indica cuándo detenerse.

Arcos de puente de piedra interminables que cruzan un río brumoso sin huecos
Los tres números que debes recordar

Se devuelven hasta 1.000 filas por llamada. Cada llamada se factura una vez, independientemente del número de filas que contenga. La paginación profunda está limitada a 50.000 filas, lo que equivale a 50 llamadas de 1.000 filas cada una.

Por qué el ordenamiento precede a la paginación

Paginar sobre una lista sin ordenar es la causa de los duplicados. Envía siempre sort y order junto con page y per, para que la página 3 signifique lo mismo en cada solicitud del proceso.

Una consulta refdomains cuesta 2 créditos por llamada, por lo que 50 llamadas suman 100 créditos, o un céntimo. Incluso el peor caso es económico; el coste real es un bucle que no termina.

Elección de la columna de ordenación

La columna por la que ordenar depende de la pregunta. El orden descendente es la opción habitual para auditorías, porque el límite corta la cola larga en lugar de la parte que te interesa.

Ordena por un campo que no tenga relación con tu pregunta y el corte podría eliminar las filas que necesitabas. Extrae diez filas con cada ordenación candidata y observa qué fragmento sobrevive al límite.

Registra la elección en el informe, para que la siguiente persona sepa por qué el corte se situó donde lo hizo.

Registros que cambian durante una ejecución

Los datos no cambian durante una ejecución a menos que la reconstrucción mensual se ejecute a mitad del proceso. Es poco frecuente, pero real. Un trabajo nocturno que se solape con el primero del mes puede devolver una página del índice antiguo y la siguiente del nuevo, así que registra la hora de inicio en tu registro y compara.

Escribe la hora de inicio en la parte superior del registro y el número de página en cada línea. Así, una discrepancia en la salida indicará un problema de sincronización, no un error de análisis.

Si el trabajo está programado, evita una hora de inicio justo antes de una reconstrucción probable. Tus registros muestran una reconstrucción como un cambio en los totales entre dos ejecuciones que coinciden en lo demás, así que incluye los totales en cada línea del registro.

Una ejecución que abarca una reconstrucción no es errónea por defecto. Solo es inconsistente, así que marca esas ejecuciones en el registro y vuelve a ejecutar el fragmento afectado cuando sea relevante para un informe.

Un bucle de paginación que termina

TypeScript para un worker de Node 20. Se detiene en la primera página corta, en el límite o en cualquier ok que no sea verdadero.

ts
const BASE = "https://seomasters.dev/api.php";
const CAP = 50_000;
const PER = 1000;

export async function pullAll(domain: string, key: string) {
  const rows: unknown[] = [];
  for (let page = 1; rows.length < CAP; page++) {
    const u = new URL(BASE);
    u.search = new URLSearchParams({
      action: "refdomains", q: domain,
      page: String(page), per: String(PER),
      sort: "dr", order: "desc",
    }).toString();
    const res = await fetch(u, { headers: { Authorization: `Bearer ${key}` } });
    if (res.status === 401 || res.status === 402) throw new Error(`stop: HTTP ${res.status}`);
    const body = await res.json();
    if (!body.ok) throw new Error(JSON.stringify(body).slice(0, 300));
    const chunk = findRows(body);   // see note below
    rows.push(...chunk);
    if (chunk.length < PER) break;  // short page means we are done
  }
  return rows;
}

Solución de problemas en una ejecución de paginación

Lo que vesPosible causaQué hacer
La página 51 devuelve vacío o errorHas alcanzado el límite de 50.000Refina con otra acción o un sort diferente, luego fusiona por id
Mismo dominio en dos páginasConsulta sin ordenar o reconstrucción del índice a mitad de ejecuciónEnvía sort y order; elimina duplicados por la clave de dominio
Menos filas que el total del panelEl total es para todo el grafo, la extracción está limitadaMuestra "top 50.000" en la interfaz
Bucle infinitoLa condición solo verifica rows.lengthRompe en una página corta, como se indica arriba
Factura superior a la esperadaReintenta en cada respuesta distinta a 200Reintenta solo errores de red, ver errores
Jardinero inspeccionando plántulas únicas en un invernadero iluminado por el sol

Lectura de filas sin adivinar los nombres de los campos

La función auxiliar findRows anterior se deja intencionadamente abierta. Haz una llamada real, observa el JSON y escribe el accesor según lo que veas, no según lo que prometía un tutorial.

Para el primo más económico de este trabajo, evaluar muchos dominios a la vez sin paginación, lee el script DR masivo.

Congela una respuesta como fixture

Luego congélala con una prueba. Guarda una respuesta como archivo fixture y verifica el recuento de filas y las claves de la primera fila, para que un cambio futuro falle en CI y no en el gráfico de un cliente.

Mantén el fixture en control de versiones junto a la prueba, para que un revisor vea la estructura que espera el código sin tener que ejecutar nada.

Cuando la API añada un campo más tarde, la diferencia del fixture te dirá si tu accesor lo detectó o lo ignoró silenciosamente.

Nombra el fixture según la consulta de la que proviene, como la acción, el dominio y el orden. Un archivo llamado response1.json no le dice nada al siguiente lector sobre lo que demuestra.

Cuenta las filas que almacenaste

Compara las filas que guardaste con el total que reportó el bucle. Una diferencia significa que se perdió una página, y una repetición significa que una página se extrajo dos veces y se actualizó en una sola fila.

Ejecuta esa comprobación después de cada extracción de prueba, no solo después de la primera. Una desviación en el recuento suele ser el primer síntoma de un cambio en el orden o de una reconstrucción a mitad de ejecución.

Mantén el recuento en la misma línea de registro que el número de página, para que ambos puedan leerse de un vistazo.

División del trabajo por encima del límite

Algunas preguntas superan el límite. Para listas por encima del límite, divide el problema en lugar de paginar más intensamente. Extrae los top 50.000 con un orden, luego pregunta a otras acciones sobre los dominios más relevantes, ya que también cuestan 2 créditos y responden a preguntas diferentes. Paginar más intensamente nunca supera el corte.

Extrae los top 50.000 con un orden

Acepta el límite como un hecho de la API. Extrae los top 50.000 filas con un orden, guárdalas y etiqueta el resultado como el fragmento superior en cualquier informe.

Un panel que muestra un recuento limitado como si fuera el total completo engaña a las personas que lo leen. La etiqueta no tiene coste, y un informe de verificador de backlinks por URL se lee con mayor honestidad con ella.

Decide el tamaño del fragmento antes de la ejecución y escríbelo en la cabecera del informe, para que el número nunca parezca mayor de lo que es. Una línea de cabecera no tiene coste, y un lector que encuentre una fila faltante más tarde te lo agradecerá.

Haz una pregunta diferente a los dominios más relevantes

anchors y toppages responden a otras preguntas, como qué texto ancla domina o qué páginas atraen los enlaces. Para un dominio que supera el límite, esas respuestas pueden ser más importantes que la siguiente página de la misma lista.

Mantén sus resultados en sus propias tablas, indexadas por el dominio, para que una extracción posterior del mismo dominio pueda reemplazarlas sin tocar las filas del fragmento superior.

Cada acción extra cuesta sus propios créditos, así que calcúlalo antes de la ejecución, no después de que llegue la factura.

Una lista corta de los dominios más pesados, extraída una vez al mes, a menudo da un contexto más útil que una lista más larga extraída todas las noches.

Fusión por la clave de dominio

Cuando dos extracciones se solapan, fusionalas por la clave de dominio y conserva la marca de tiempo más reciente. La fusión entonces no depende de qué extracción terminó primero.

Registra qué extracción ganó cada fila. Si un número cambia entre dos informes, ese registro te dirá si cambió el índice o la fusión.

Mantén la fusión en una sola función con una prueba, ya que es el único lugar donde se encuentran dos extracciones.

Reanudación tras un fallo

Los fallos ocurren. Un despliegue reinicia el worker, un portátil entra en suspensión, una VPN se cae y el bucle muere en la página 31 de 50.

Guarda la página después de cada llamada

Persiste el último número de página completado después de cada llamada. Reinicia desde ese número más uno, no desde el principio, y pagarás 2 créditos por página en lugar de volver a comprar toda la extracción.

Guárdalo después de analizar la respuesta, no antes. Una página que no lograste leer debe extraerse de nuevo, y un número de página guardado debe significar siempre filas que ya tienes.

Un guardado que ocurre una vez por minuto en lugar de una vez por llamada deja una ventana donde un fallo puede repetir el gasto de créditos. Mantén la escritura pequeña, para que sea económica hacerla cada vez.

Registra también cuánto tarda cada guardado y cuánto tarda cada llamada. Un guardado que compite en tiempo con la llamada apunta a la capa de almacenamiento, y eso vale la pena corregirlo antes de que crezca el bucle.

Actualización insertada (Upsert) por la clave de dominio

Mantén una escritura idempotente. Actualiza inserta cada fila por su clave de dominio, para que una página extraída dos veces deje una fila, no dos.

Usa la misma clave en todas las vías de escritura, incluyendo el script de reparación manual. Dos vías de escritura con dos claves son la causa de que los duplicados sobrevivan a una reanudación.

Un script de reparación suele escribirse apresuradamente, tras una ejecución fallida. Es entonces cuando se introduce una segunda clave, así que revísalo con el mismo cuidado que el bucle principal.

Rechaza una reanudación si cambió el orden

Registra el orden y el sentido junto al número de página. Si alguien cambia sort entre un fallo y el reinicio, el número de página guardado ya no significa el mismo fragmento. Rechaza la reanudación y empieza de cero.

Almacena un pequeño registro de reanudación con el orden, el sentido, la página y la hora. El bucle lee ese registro primero y se niega a continuar si algún campo ya no coincide con la solicitud que está a punto de hacer.

Una reanudación rechazada no es un fallo. Es el bucle diciendo que la página guardada ya no significa las mismas filas, y empezar de cero es el error más barato.

Ejecución del bucle en producción

  1. 1

    Empieza con un dominio pequeño

    Ejecuta el bucle contra un dominio con unas pocas cientos de filas, para que se active la parada en página corta y puedas observar cómo funciona la ruta de salida.

  2. 2

    Verifica una página a ojo

    Abre una respuesta almacenada y confirma que el accesor sigue leyendo las filas. No confíes en un análisis que no hayas examinado.

  3. 3

    Mantén los límites en la configuración

    Pon el límite y el tamaño de página en un solo archivo de configuración, para que un cambio aparezca en la revisión y no se oculte dentro de una función.

  4. 4

    Registra la razón por la que terminó el bucle

    Registra si la ejecución terminó en una página corta, en el límite o por un error. Esas tres finalizaciones significan cosas diferentes para quien lea el registro.