Parcourez le vérificateur de backlinks URL sans trous ni boucles infinies
Lignes par appel, pages par requête et un plafond strict à 50 000. Voici une boucle qui respecte ces trois paramètres et vous indique quand s'arrêter.

Chaque appel renvoie jusqu'à 1 000 lignes. Chaque appel est facturé une seule fois, quel que soit le nombre de lignes retournées. La pagination profonde est limitée à 50 000 lignes, soit 50 appels de 1 000 lignes chacun.
Pourquoi le tri précède la pagination
Paginer sur une liste non triée est la cause des doublons. Envoyez toujours sort et order conjointement avec page et per, afin que la page 3 désigne le même jeu de résultats à chaque requête de la série.
Un appel refdomains coûte 2 crédits par appel, soit 50 appels pour 100 crédits, soit un centime. Même dans le pire des cas, le coût est faible ; le vrai risque est une boucle qui ne se termine jamais.
Choix de la colonne de tri
La colonne de tri dépend de la question posée. Le tri décroissant est le choix habituel pour les audits, car il permet de couper la longue traîne plutôt que la partie qui vous intéresse.
Trier par un champ sans lien avec votre question peut faire disparaître les lignes souhaitées. Extrayez d'abord dix lignes pour chaque critère de tri et observez quelles lignes subsistent après le filtrage.
Notez ce choix dans le rapport afin que la personne suivante comprenne pourquoi le seuil a été défini ainsi.
Enregistrements qui changent pendant l'exécution
Les données ne changent pas pendant une exécution, sauf si le rebuild mensuel intervient en cours de route. C'est rare, mais réel. Un job nocturne qui chevauche le premier du mois peut renvoyer une page depuis l'ancien index et la suivante depuis le nouveau ; notez l'heure de début dans vos logs et comparez.
Indiquez l'heure de début en haut du log et le numéro de page sur chaque ligne. Ainsi, une incohérence dans la sortie indique un problème de synchronisation et non un bug de parsing.
Si le job est planifié, évitez une heure de début juste avant un rebuild probable. Vos logs montrent un rebuild comme un changement dans les totaux entre deux exécutions par ailleurs identiques ; incluez donc les totaux dans chaque ligne de log.
Une exécution qui chevauche un rebuild n'est pas fausse par défaut. Elle est seulement incohérente ; marquez ces exécutions dans le log et relancez la tranche concernée lorsque cela est nécessaire pour un rapport.
Une boucle de pagination qui s'arrête
TypeScript pour un worker Node 20. Il s'arrête sur la première page courte, sur le seuil, ou sur tout ok qui n'est pas vrai.
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;
}Dépannage d'une exécution de pagination
| Ce que vous voyez | Raison probable | Que faire |
|---|---|---|
| La page 51 revient vide ou affiche une erreur | Vous avez atteint la limite de 50 000 | Affinez avec une autre action ou un sort différent, puis fusionnez par id |
| Même domaine sur deux pages | Requête non triée, ou l'index reconstruit en cours d'exécution | Envoyez sort et order ; dédupliquez sur la clé de domaine |
| Moins de lignes que le total affiché dans le tableau de bord | Le total concerne l'ensemble du graphe, le tirage est limité | Affichez "top 50 000" dans l'interface |
| La boucle ne se termine jamais | La condition vérifie uniquement rows.length | Interrompez sur une page courte, comme indiqué ci-dessus |
| Facturation plus élevée que prévu | Réessayez à chaque erreur non-200 | Réessayez uniquement les erreurs réseau, voir erreurs |

Lecture des lignes sans deviner les noms de champs
L'helper findRows ci-dessus est volontairement laissé ouvert. Effectuez un seul appel réel, examinez le JSON, et écrivez l'accesseur en fonction de ce que vous voyez plutôt que de ce qu'un tutoriel a promis.
Pour la version moins chère de ce travail, qui consiste à évaluer de nombreux domaines simultanément sans pagination du tout, lisez le script DR en masse.
Gélez une réponse en tant que fixture
Ensuite, figez-la avec un test. Sauvegardez une réponse en tant que fichier fixture et vérifiez le nombre de lignes et les clés de la première ligne, afin qu'une modification future échoue dans CI et non dans le graphique d'un client.
Conservez la fixture dans le contrôle de version à côté du test, afin qu'un réviseur voie la structure attendue par le code sans rien exécuter.
Lorsque l'API ajoute un champ plus tard, la différence du fixture vous indique si votre accesseur l'a détecté ou l'a ignoré silencieusement.
Nommez le fixture en fonction de la requête dont il provient, comme l'action, le domaine et le tri. Un fichier nommé response1.json n'indique rien au lecteur suivant sur ce qu'il prouve.
Comptez les lignes que vous avez stockées
Comparez les lignes que vous avez enregistrées avec le total indiqué par la boucle. Un écart signifie qu'une page a été perdue, et une répétition signifie qu'une page a été récupérée deux fois et insérée ou mise à jour dans une seule ligne.
Exécutez cette vérification après chaque extraction de test, pas seulement après la première. Une dérive dans le compte est généralement le premier symptôme d'un tri modifié ou d'une reconstruction en cours d'exécution.
Conservez le compte dans la même ligne de journal que le numéro de page, afin que les deux puissent être lus d'un coup d'œil.
Partage de la charge au-dessus du plafond
Certaines questions dépassent le plafond. Pour les listes au-dessus du plafond, divisez le problème plutôt que de paginer plus intensément. Récupérez les 50 000 premiers éléments par un tri, puis interrogez d'autres actions sur les éléments les plus lourds, car ceux-ci coûtent également 2 crédits et répondent à des questions différentes. Paginer plus intensément ne permet jamais de dépasser la limite.
Récupérez les 50 000 premiers éléments par un tri
Considérez le plafond comme un fait de l'API. Récupérez les 50 000 premières lignes par un tri, stockez-les et étiquetez le résultat comme la tranche supérieure dans tout rapport.
Un tableau de bord qui affiche un compte plafonné comme s'il s'agissait du total complet induit en erreur les personnes qui le lisent. L'étiquette ne coûte rien, et un rapport de vérification de backlinks URL est plus honnête avec elle.
Définissez la taille de la tranche avant l'exécution et inscrivez-la dans l'en-tête du rapport, afin que le nombre ne semble jamais plus élevé qu'il ne l'est. Une ligne d'en-tête ne coûte rien, et un lecteur qui trouve une ligne manquante plus tard vous en sera reconnaissant.
Posez une question différente aux éléments les plus lourds
anchors et toppages répondent à d'autres questions, telles que quel texte d'ancre domine ou quelles pages attirent les liens. Pour un domaine ayant dépassé le plafond, ces réponses peuvent être plus importantes que la page suivante de la même liste.
Conservez leurs résultats dans leurs propres tables, indexées par le domaine, afin qu'une extraction ultérieure du même domaine puisse les remplacer sans toucher aux lignes de la tranche supérieure.
Chaque action supplémentaire coûte ses propres crédits, donc évaluez le coût avant l'exécution, pas après la réception de la facture.
Une courte liste des domaines les plus lourds, extraite une fois par mois, donne souvent un contexte plus utile qu'une liste plus longue extraite chaque nuit.
Fusionner sur la clé de domaine
Lorsque deux extractions se chevauchent, fusionnez-les sur la clé de domaine et conservez l'horodatage le plus récent. La fusion ne dépend alors jamais de laquelle des deux extractions s'est terminée en premier.
Journalisez quelle extraction a gagné chaque ligne. Si un nombre change entre deux rapports, ce journal vous indique si l'index ou la fusion a changé.
Conservez la fusion dans une seule fonction avec un test, car c'est le seul endroit où deux extractions se rencontrent.
Reprise après un crash
Les crashes se produisent. Un déploiement redémarre le worker, un ordinateur portable se met en veille, un VPN tombe en panne et la boucle meurt à la page 31 sur 50.
Enregistrez la page après chaque appel
Persistez le dernier numéro de page terminé après chaque appel. Redémarrez à partir de ce numéro plus un, pas depuis le début, et vous payez 2 crédits par page au lieu de racheter toute l'extraction.
Enregistrez-le après l'analyse de la réponse, pas avant. Une page que vous n'avez pas pu lire doit être récupérée à nouveau, et un numéro de page enregistré doit toujours signifier des lignes que vous possédez.
Une sauvegarde qui se produit une fois par minute au lieu d'une fois par appel laisse une fenêtre où un crash peut répéter la dépense de crédits. Gardez l'écriture petite, afin qu'elle soit peu coûteuse à effectuer chaque fois.
Journalisez également la durée de chaque sauvegarde ainsi que la durée de chaque appel. Une sauvegarde qui rivalise avec l'appel lui-même pointe vers la couche de stockage, et cela vaut la peine d'être corrigé avant que la boucle ne grandisse.
Upsert sur la clé de domaine
Conservez une écriture idempotente. Upsert chaque ligne sur sa clé de domaine, afin qu'une page récupérée deux fois laisse une seule ligne, pas deux.
Utilisez la même clé sur chaque chemin d'écriture, y compris le script de réparation manuel. Deux chemins d'écriture avec deux clés sont la raison pour laquelle les doublons survivent à une reprise.
Un script de réparation est souvent écrit précipitamment, après un échec d'exécution. C'est alors qu'une deuxième clé se glisse, alors examinez-la aussi soigneusement que la boucle principale.
Rejeter une reprise lorsque le tri a changé
Journalisez le tri et l'ordre à côté du numéro de page. Si quelqu'un modifie sort entre un crash et le redémarrage, le numéro de page enregistré ne signifie plus la même tranche. Rejetez la reprise et commencez proprement.
Stockez un petit enregistrement de reprise avec le tri, l'ordre, la page et l'heure. La boucle lit d'abord cet enregistrement, et elle refuse de continuer si l'un des champs ne correspond plus à la requête qu'elle sur le point d'effectuer.
Une reprise rejetée n'est pas un échec. C'est la boucle disant que la page enregistrée ne signifie plus les mêmes lignes, et commencer proprement est l'erreur la moins coûteuse.
Exécution de la boucle en production
- 1
Commencez avec un petit domaine
Exécutez la boucle contre un domaine avec quelques centaines de lignes, afin que l'arrêt de page courte se déclenche et que vous puissiez voir le chemin de sortie fonctionner.
- 2
Vérifiez une page à l'œil nu
Ouvrez une réponse stockée et confirmez que l'accesseur lit toujours les lignes. Ne faites pas confiance à une analyse que vous n'avez pas examinée.
- 3
Conservez les limites dans la configuration
Mettez le plafond et la taille de page dans un seul fichier de configuration, afin qu'un changement apparaisse dans la revue et ne se cache pas à l'intérieur d'une fonction.
- 4
Journalisez la raison pour laquelle la boucle s'est terminée
Enregistrez si l'exécution s'est terminée sur une page courte, sur le plafond ou sur une erreur. Ces trois fins signifient des choses différentes pour celui qui lit le journal.