Test de Katana : `-jc` et `-headless` trouvent des points de terminaison différents, et aucune commande unique n’a permis de couvrir les deux

Dernière mise à jour le August 19, 2026
Test de Katana : `-jc` et `-headless` trouvent des points de terminaison différents, et aucune commande unique n’a permis de couvrir les deux
Résumé IA

Katana est le crawler de découverte de points de terminaison de ProjectDiscovery — un binaire Go sous licence MIT qui prend une cible en entrée et renvoie des URL et des endpoints pour l’outil suivant d’une chaîne. Il explore soit en mode HTTP sans navigateur, soit avec -headless, qui pilote Chromium. La documentation officielle présente le mode headless comme l’option offrant la meilleure couverture ; cet exemple montre pourquoi la nature des endpoints compte autant que leur quantité. J’ai monté un petit site comportant trois catégories d’endpoints volontairement différentes et j’ai mesuré, sur la version v1.6.1 avec -d 4, quels modes détectaient quoi.

Katana est le crawler de découverte d’endpoints de ProjectDiscovery : un binaire Go sous licence MIT qui prend une cible en entrée et renvoie des URL et des endpoints à transmettre à l’outil suivant dans une chaîne de traitement. Il peut explorer en mode HTTP sans navigateur ou avec -headless, qui s’appuie sur Chromium. La documentation officielle présente le mode headless comme l’option offrant la meilleure couverture ; ce test montre surtout que la nature de l’endpoint compte autant que le volume détecté.

J’ai monté un petit site comportant trois catégories d’endpoints volontairement distinctes et j’ai mesuré, sur la version v1.6.1 avec -d 4, quel mode détectait quoi. Le HTML classique a été retrouvé à 4/4 liens ainsi que dans la chaîne complète de trois sauts dans les quatre configurations. La différence est apparue sur les endpoints exposés via du code JavaScript versus les modifications du DOM au moment de l’exécution.

Dans ce test, le mode headless a trouvé la classe liée au DOM à l’exécution que les modes sans navigateur n’ont pas vue, tandis que le mode standard avec -jc a trouvé les littéraux présents dans les fichiers JavaScript, que les deux exécutions headless ont manqués. Aucune des quatre lignes du tableau de commandes ne couvrait les deux classes à la fois. Le périmètre, la reprise et le comportement des fichiers connus ont fourni les autres limites pratiques.

Ce qu’est réellement katana

Le crawler katana — projectdiscovery/katana sur GitHub — est écrit en Go et distribué sous licence MIT. J’ai testé la version v1.6.1 le 27 juillet 2026 ; cette version compte, car les résultats de couverture et de fichiers connus ci-dessous dépendent de la build.

Ici, l’étiquette de catégorie est plus importante que d’habitude. Un crawler de découverte d’endpoints n’est pas un extracteur de contenu. Si vous cherchez un crawler Go qui vous renvoie des noms de produits et des prix sous forme de JSON structuré, katana n’est clairement pas le bon outil — il vous dira volontiers que /products/1138 existe, mais ne vous dira rien sur le contenu de la page. C’est voulu, et le juger sur sa capacité d’extraction reviendrait à évaluer un détecteur de métaux sur sa faculté à estimer la valeur de bijoux.

Son terrain de jeu, ce sont la reconnaissance en sécurité offensive et les pipelines d’automatisation : entrée STDIN, sortie URL, puis enchaînement vers l’outil suivant. D’où l’avertissement évident : toutes les mesures ici ont été réalisées sur un environnement de test local sur 127.0.0.1, que j’ai écrit moi-même. N’utilisez katana que sur des hôtes que vous possédez ou pour lesquels vous avez une autorisation écrite, et rien d’autre. Il ne s’agit pas de contourner des défenses : il s’agit de mesurer quelle partie de l’espace d’endpoints d’un site est réellement énumérée par une commande donnée.

Les trois modes et ce que chacun voit

Le mode standard est un client HTTP Go. Il récupère la page, analyse le HTML, suit les href et ne lance jamais de navigateur. Rapide, peu coûteux, mais aveugle à tout ce qui n’existe qu’après exécution du JavaScript.

-jc (-js-crawl) ajoute un parseur JavaScript à cette voie sans navigateur. Il télécharge les fichiers .js liés et extrait du code source les chaînes qui ressemblent à des URL. Aucune exécution, juste de la lecture. Il existe aussi -jsl (jsluice), décrit dans le README comme un parseur plus lourd et plus gourmand en mémoire — je ne l’ai pas testé, donc je ne peux rien dire sur son impact sur la couverture.

System diagram: Scope Is Applied in Layers

-headless lance Chromium et exécute les scripts de la page. Dans ce test, c’était le seul mode Katana qui a récupéré le chemin assemblé à partir de fragments puis injecté dans le DOM à l’exécution. Ce résultat ne prouve pas ce que tous les parseurs, ni les futures variantes de Katana, pourraient récupérer.

Il y a ensuite le modèle de scope, et c’est la première chose que je retiendrais avant de taper quoi que ce soit en production.

FlagCe qu’il contrôleValeurs / défaut
-fs (field scope)quels hôtes sont pris en comptedn, rdn, fqdn, ou une regex personnalisée — défaut : rdn
-cs et -cosregex d’URL qui filtrent à l’intérieur de ce scope
-kffichiers connus : robots.txt et sitemap.xmlle README indique qu’une profondeur minimale de 3 est nécessaire
-dprofondeurdéfaut 3
-resumereprend un crawl interrompu

L’ordre n’est pas décoratif : il décide si une regex d’hôte élargit un crawl ou le vide silencieusement.

Mise en place : un binaire, un astérisque

Trois façons d’installer, et une seule demande une chaîne d’outils :

Mode d’installationPrérequis
Depuis les sources : go install github.com/projectdiscovery/katana/cmd/katana@latestGo 1.25 ou plus récent est requis
Binaires précompilés sur la page des releasesaucune chaîne d’outils
Image Dockeraucune chaîne d’outils

Le mien s’est installé dans ~/go/bin/katana et a affiché Current version: v1.6.1 à chaque exécution. Jusqu’ici, la classique bonne histoire du monde Go : un seul fichier, pas d’exécution au runtime.

L’astérisque concerne le mode headless, où le navigateur devient une dépendance distincte du binaire :

Où s’exécute -headlessCe qu’il faut
Ma machinekatana a détecté automatiquement un Chromium déjà installé ; je n’ai ni noté la version du navigateur ni fourni de chemin vers celui-ci
Un serveur nu, selon les instructions Ubuntu du projetapt install google-chrome-stable avant que le mode headless ne fonctionne
Le parcours Dockerle mode headless fonctionne avec -system-chrome

Sur un serveur nu, cette simplicité disparaît. Prévoyez un navigateur, pas seulement un binaire, dès que -headless entre dans votre commande.

Un point plus discret, mais utile si vous exécutez cela en CI : katana fait un appel de vérification de version vers GitHub au démarrage. -duc le désactive. Sur un portable, c’est anodin ; sur un runner isolé du réseau ou soumis à des limites de débit, c’est un aller-retour réseau à chaque exécution que vous n’avez pas demandé. Mes mesures de temps passent -duc afin que les chiffres reflètent le crawl, pas un appel maison.

Comment j’ai testé

Trois classes d’endpoints, choisies précisément parce qu’elles séparent les modes. Tout se trouve dans un serveur local de test, et la vérité terrain a été écrite avant tout crawl, afin de mesurer le rappel par rapport à un ensemble fixe et non à ce que katana affichait au hasard.

  • Classe A — HTML simple. /page/a, /page/b, /page/c, plus une chaîne de trois sauts /depth/1 → /depth/2 → /depth/3. N’importe quel crawler devrait les trouver.
  • Classe B — littéraux dans un fichier JavaScript. /api/js-endpoint-7 et /api/js-endpoint-8 n’existent que comme littéraux de chaîne dans un fichier lié /static/app.js. Lisibles sans navigateur, à condition qu’un outil prenne la peine de lire le JS.
  • Classe C — uniquement dans le DOM à l’exécution. Un chemin assemblé à l’exécution à partir de fragments ('endpoint' + (6 * 7)) puis injecté dans le DOM par script. La chaîne /runtime-only/endpoint42 n’apparaît jamais de manière contiguë dans un seul octet envoyé par le serveur — ni dans le HTML, ni dans le code source JS. Seule l’exécution permet de la voir.

À cela s’ajoutent un robots.txt, un sitemap.xml contenant deux endpoints <loc> qui n’apparaissent nulle part ailleurs, une route qui renvoie 500, un lien mort et un lien hors scope pointant vers un second serveur sur un autre nom d’hôte.

L’instrument compte autant que le fixture : le serveur mesure ce qui a réellement été récupéré, de sorte que les affirmations sur le scope et la reprise reposent sur des hits vérifiables et non sur la simple sortie standard de katana. Les exécutions brutes sont archivées dans le dépôt de benchmark si vous voulez vérifier mes calculs.

La séparation de couverture que personne ne quantifie

Measured results chart: Endpoint coverage by Katana mode

La matrice, par mode et par classe d’endpoint, avec -d 4 :

ModeLiens HTML (A)Chaîne de profondeur (A)Littéraux JS (B)DOM à l’exécution (C)
standard4/43/30/2non trouvé
standard -jc4/43/32/2non trouvé
-headless4/43/30/2trouvé
-headless -jc4/43/30/2trouvé

Lisez les deux dernières colonnes ensemble, et le problème saute aux yeux. La classe B n’a été trouvée que par une seule configuration : le mode standard avec -jc. La classe C n’a été trouvée que par deux : les deux exécutions headless. Aucune ligne n’affiche un résultat positif dans les deux colonnes. Le tableau complet se trouve dans discovery-summary.json, où le champ calculé headless_jc_covers_both vaut false.

La conséquence pratique est que “utilisez simplement headless pour une meilleure couverture” était une conclusion incomplète pour ce test. Le mode headless n’a pas ajouté la classe B au résultat standard ; il a récupéré la classe C tout en manquant la classe B. Pour couvrir toutes les classes injectées dans ce fixture, il a fallu deux crawls puis une fusion :

katana -u https://target.example -jc -d 4 -silent -o pass-jc.txt
katana -u https://target.example -headless -d 4 -silent -o pass-headless.txt
sort -u pass-jc.txt pass-headless.txt > endpoints.txt

La ligne -headless -jc est celle sur laquelle j’aimerais le plus une réponse de l’amont. Ajouter le parseur JavaScript à l’exécution headless n’a rien changé — toujours 0/2 sur la classe B, à chaque test, y compris lors d’une reproduction fraîche. Je décris le comportement, je ne prétends pas en avoir trouvé la cause ; je n’ai pas instrumenté les entrailles de katana pour comprendre pourquoi le chemin navigateur cesse de contribuer aux littéraux de fichiers JS. Traitez cela comme une observation reproductible et un bon sujet de ticket GitHub, pas comme un diagnostic. (À noter aussi : la combinaison -hl -jc s’est exécutée correctement avec un code de retour 0 sur v1.6.1 sous macOS ARM, ce qui n’a pas toujours été le cas historiquement.)

La documentation officielle décrit le mode headless comme offrant une meilleure couverture, et c’était bien le cas ici pour la classe rendue à l’exécution. En revanche, la documentation vérifiée ne détaillait pas cette séparation entre littéraux de source et DOM dynamique ; considérez donc cette matrice comme une raison de tester les deux voies sur vos propres classes d’endpoints, pas comme une taxonomie universelle.

Ce que coûte le headless en temps réel

Trois exécutions consécutives par mode, sur une machine par ailleurs inactive :

Modep50min–maxmoyenne
standard13.08s13.07–13.17s13.11s
-headless66.82s66.78–67.68s67.09s

Le rapport est de 5,1x, avec des plages qui ne se chevauchent même pas de près — ma lenteur standard la plus élevée (13,17s) reste plus de 53 secondes plus rapide que mon exécution headless la plus rapide (66,78s) (cost-summary.json). Ce n’est pas du bruit de mesure.

Une nuance sur ces 13 secondes : mon fixture inclut volontairement une route 500 et un lien mort, et le mode standard attend la queue de retentative du -timeout 10 par défaut dans les deux cas. Je n’ai pas ajusté le timeout pour rendre le mode rapide artificiellement plus flatteur, ce qui veut dire qu’un standard mieux réglé élargirait probablement encore l’écart au lieu de le réduire.

Ce ratio est un signal local de capacité, pas une prévision de production. Les cibles réelles varient en latence, en échecs, en exécution de scripts et en ordonnancement, tandis que ce fixture inclut la queue d’un timeout par défaut. Utilisez l’écart mesuré de 5,1x pour décider si headless mérite son propre budget et son propre sous-ensemble de cibles, puis validez ce plan sur des hôtes représentatifs et autorisés.

Le scope a tenu, mais un flag n’a discrètement rien fait

Le test de scope utilisait deux serveurs : le principal sur 127.0.0.1, et un second accessible en tant que localhost sur un autre port, qui servait un chemin existant uniquement là-bas. Ainsi, un hit sur ce chemin prouve que l’hôte hors scope a réellement été récupéré, et pas simplement affiché.

ConfigurationHôte hors scope récupéré ?Hits sur le second serveur
défaut (-fs rdn)non0
-fs fqdnnon0
-cs localhostnon0
`-fs '(127.0.0.1localhost)'`oui

La discipline du scope est une bonne nouvelle : par défaut, katana est resté sagement à la maison, et il a fallu un acte explicite pour élargir. C’est le bon défaut pour un outil qu’on pointe vers l’infrastructure d’autrui.

La ligne intéressante est -cs localhost. Elle n’a pas élargi le crawl au second hôte — et elle n’a aussi produit aucune URL du tout. Comme -cs filtre à l’intérieur du field scope, et que celui-ci pointait encore vers l’hôte principal, la regex n’a rien fait correspondre et le crawl a renvoyé un ensemble vide au lieu d’une erreur. Si vous avez déjà écrit une regex de scope en nommant l’hôte que vous vouliez inclure et regardé un fichier de sortie vide, voilà le mécanisme (scope-summary.json). Pour ajouter un hôte, utilisez -fs. Pour restreindre à l’intérieur d’un ensemble d’hôtes déjà inclus, utilisez -cs/-cos.

La reprise est plus grossière que le flag ne le laisse entendre

Le README décrit le flag comme -resume string resume scan using resume.cfg, ce qui donne l’impression d’un fichier déposé dans le répertoire de travail. Ce n’est pas le cas. Sur ma machine, le point de reprise a été écrit dans ~/.config/katana/resume-<xid>.cfg — mesuré, pas déduit d’une page de documentation, car les docs ne précisent pas de chemin.

Le vrai surprise, c’est le contenu. Le fichier contenait une map InFlightUrls avec exactement une seule chose : l’URL de départ. Ni l’ensemble des pages visitées, ni la frontière. Voici donc ce qui s’est passé quand j’ai interrompu un crawl avec SIGINT après trois secondes puis repris :

ExécutionChemins distincts
Crawl de base complet11
Récupérés avant l’interruption10
Re-récupérés par la repriseles 11, y compris les 10 déjà terminés

La reprise a bien abouti au même ensemble final d’endpoints, donc rien n’est cassé. Mais la granularité du point de reprise est par seed d’entrée, pas par URL — le filtre de déduplication en mémoire n’est jamais persisté, donc reprendre un crawl à seed unique recommence ce seed depuis zéro (resume-summary.json). Si vous donnez à katana une liste de 500 hôtes, la reprise devrait vous faire gagner les hôtes déjà terminés ; ce comportement multi-seed découle de la manière dont l’état est stocké, mais je n’ai mesuré que le cas à seed unique. Si vous êtes très loin dans un site unique très volumineux, la reprise vous apporte la correction, pas le temps gagné.

Fichiers connus : demandés, puis abandonnés

System diagram: Known files: requested, then dropped

-kf all -d 3 a bien demandé les deux fichiers — robots.txt et sitemap.xml apparaissent dans le journal de hits du serveur — puis a récupéré 0 sur 2 des endpoints listés dans les éléments <loc> du sitemap. Rappel à 0,0.

Avant d’appeler cela une limite, j’ai essayé de voir si c’était de ma faute. Chaque variante renvoyait la même chose :

Variante testéeEndpoints du sitemap <loc> récupérés
-kf all0/2, rappel 0,0
-kf sitemapxml0/2, rappel 0,0
-kf robotstxt0/2, rappel 0,0
profondeur 30/2, rappel 0,0
profondeur 40/2, rappel 0,0
profondeur 50/2, rappel 0,0
avec ajout de -jc0/2, rappel 0,0
en partant directement de /sitemap.xml0/2, rappel 0,0

L’exigence documentée — utiliser -kf et aller au moins à profondeur 3 — était respectée à chaque fois. Ce n’est donc pas une histoire d’option manquante.

La décision utile vient d’abord : sur ce fixture à base d’IP littérale, ne partez pas du principe que demander les fichiers connus signifie que leurs URL <loc> ont rejoint le crawl. Vérifiez le rappel, ou extrayez ces URL vous-même pour les donner en seed.

Le chemin du code v1.6.1 est cohérent avec cette observation, mais je ne l’ai pas instrumenté pendant l’exécution. Dans sitemapxml.go à v1.6.1, NewNavigationRequestURLFromResponse construit les requêtes de navigation <loc> à partir d’une réponse sans RootHostname renseigné. La requête passe ensuite par ValidateScope; dans scope.go à v1.6.1, la branche pour les IP littérales compare l’hôte de l’URL à cette racine vide et peut rejeter l’URL. La commande personnalisée -fs '(127.0.0.1|localhost)' a pris une autre branche de scope dans un test distinct ; c’est donc un sauvetage prédit par le code source, pas un contournement mesuré de -kf. Une tentative de confirmation a été bloquée par des échecs de connexion intermittents dans le client des fichiers connus sur cet hôte ; le résultat rapporté reste donc 0/2.

Ce que je ferais réellement en production, tant que personne ne confirme le flag : récupérer le sitemap moi-même, extraire les URL <loc> et les passer à katana comme liste de seeds. Deux lignes de shell, sans validation de scope.

Une chose a fonctionné exactement comme annoncé et mérite une phrase : la route 500 et le lien mort ont été récupérés, consignés et dépassés. Toutes les exécutions sans navigateur se sont terminées avec un code de retour 0. Un crawler qui s’arrête au premier mauvais retour est inutilisable en mode non surveillé, et katana ne fait pas ça.

Un contrôle de couverture spécifique à la cible avant déploiement

La matrice du fixture est surtout utile comme modèle pour tester vos propres cibles autorisées. Définissez les classes d’endpoints avant d’exécuter Katana : liens simples, littéraux dans des scripts liés, routes créées uniquement après exécution, et entrées de fichiers connus sont quatre catégories de départ raisonnables. Gardez pour chacune un petit échantillon de vérité terrain. Sans cette liste préalable, une sortie standard plus longue peut donner l’impression d’une meilleure couverture alors qu’une classe a disparu.

Exécutez d’abord les chemins sans navigateur et avec navigateur comme deux mesures séparées. Conservez les commandes exactes, la version de Katana, la build du navigateur, les codes de retour et les sorties. Normalisez puis comparez les ensembles d’endpoints au lieu de comparer des nombres de lignes. Si -jc en mode standard n’apporte rien d’unique sur votre échantillon, une politique headless only peut suffire ; si les ensembles divergent comme ici, gardez les deux passes distinctes et fusionnez après collecte. Ajouter les deux flags dans une seule commande ne doit pas être supposé équivalent à l’union, tant que le diff spécifique à la cible ne l’a pas prouvé.

Validez le scope avec des preuves extérieures à la sortie de Katana. Placez une URL canari sur un hôte qui doit rester exclu et inspectez le journal de requêtes de ce serveur. Testez aussi un second hôte voulu si le crawl est censé s’élargir. L’exécution -cs localhost ici a produit une sortie vide parce que le filtrage de content scope n’a pas élargi le field scope ; la commande personnalisée -fs '(127.0.0.1|localhost)' a bien contacté le second serveur. Enregistrer l’expression régulière exacte est important, car un changement d’un seul caractère peut transformer la regex elle-même, pas seulement sa présentation.

Testez l’interruption et les fichiers connus séparément du rappel de découverte. Pour la reprise, interrompez un seed représentatif après plusieurs pages, sauvegardez le chemin du checkpoint généré et comptez combien d’URL déjà terminées sont récupérées à nouveau. Pour -kf, vérifiez à la fois que robots/sitemap ont bien été demandés et que les URL <loc> injectées ont réellement été planifiées. Ce sont deux affirmations différentes. Dans ce fixture, les fichiers ont bien été récupérés alors que les deux endpoints du sitemap étaient absents ; il fallait donc à la fois les logs de requêtes et la sortie d’endpoints pour voir la frontière.

Enfin, établissez une base de coût locale avec des exécutions séquentielles sur une machine au repos, puis recommencez sur des hôtes représentatifs. Conservez le minimum, le maximum et la médiane, pas seulement un multiplicateur. Le 5,1x mesuré ici inclut le comportement de timeout et d’échec de ce fixture ; cela vous dit que headless mérite son propre budget, pas combien de temps prendra un inventaire de production.

Avantages et inconvénients

Avantages :

  • Rappel parfait sur le HTML classique dans tous les modes — 4/4 liens et la chaîne complète 3/3, sans configuration supplémentaire.
  • -jc fonctionne réellement sans navigateur : 2/2 endpoints récupérés à partir de littéraux de chaîne dans un fichier JS lié, sans coût navigateur.
  • -headless est la seule chose qui a trouvé un endpoint assemblé à l’exécution — une classe invisible par construction à l’analyse de source.
  • Les valeurs de scope par défaut sont prudentes. L’hôte hors scope n’a jamais été récupéré avec les réglages par défaut, -fs fqdn ou -cs.
  • Un seul binaire Go, licence MIT, builds précompilés et image Docker, I/O pensée pour les pipelines.
  • Robuste en cas d’échec : les réponses 500 et les liens morts ne stoppent pas le crawl.

Inconvénients :

  • Aucune exécution unique n’a couvert à la fois les endpoints issus d’un fichier JS et ceux du DOM à l’exécution. Une couverture complète demande deux passes et une fusion.
  • -jc n’a rien apporté sous -headless — 0/2 sur la classe B à chaque exécution headless.
  • Le mode headless coûte 5,1x en temps réel (66,82s contre 13,08s en p50, avec des plages non chevauchantes).
  • -resume recrawle les pages déjà terminées à l’intérieur d’un seed. Il restaure l’ensemble des endpoints, pas le temps déjà passé.
  • Les fichiers connus ont bien demandé robots.txt et sitemap.xml mais n’ont récupéré aucun des 2 endpoints <loc> du sitemap sur une cible IP.
  • Le mode headless nécessite discrètement Chromium sur la machine ; l’histoire du “seul binaire” s’arrête au navigateur.
  • Découverte uniquement. Pas d’extraction structurée, pas de conversion de contenu, pas de schéma de champs.

Non testés, et donc hors du périmètre de ces chiffres : -jsluice, un test de seuil de profondeur dédié à -d 1/-d 2, la reprise multi-seed, le remplissage automatique de formulaires, et tout site de production réel lourd en JavaScript ou protégé. Tous les chiffres proviennent d’une seule machine (macOS arm64) contre un fixture local.

À qui cela s’adresse, et qui devrait passer son tour

Si votre travail consiste à produire un inventaire d’endpoints pour une infrastructure que vous êtes autorisé à toucher, katana a la bonne forme de pipeline : entrée/sortie STDIN/STDOUT, binaire distribuable, et modes sans navigateur ou avec navigateur. La fusion en deux passes était nécessaire pour les classes injectées dans ce fixture ; pour vos cibles, il faudra déterminer si deux passes sont nécessaires à partir de pages représentatives.

Passez votre chemin si vous voulez des données plutôt que des adresses. Katana ne vous renverra jamais un tableau de produits ; il vous donnera les URL où les produits pourraient se trouver, et un autre outil fera l’extraction. Passez aussi votre chemin si vous avez besoin qu’une seule commande soit suffisante — la fusion en deux passes est très bien dans un pipeline et pénible au prompt. Et si votre énumération repose sur des endpoints <loc> de sitemap alors que vous ciblez des IP, vérifiez ce que vous obtenez réellement avant de faire confiance à la sortie, car dans mon fixture, ce chemin ne renvoyait rien.

Alternatives, et la frontière avec l’extraction

Katana est gratuit, sous licence MIT, et auto-hébergé. Il laisse la découverte, le choix du mode, le déploiement du navigateur et la fusion des résultats de votre côté de la frontière.

Dans l’open source, les comparaisons utiles se font par tâche plutôt que par langage. Colly est l’autre option Go, mais c’est une bibliothèque que vous compilez avec vos propres callbacks, et elle ne rend pas JavaScript du tout. Crawl4AI exécute un vrai navigateur et produit du Markdown pour des pipelines LLM, ce qui donne un résultat totalement différent. Si vous hésitez entre plusieurs outils de ce type, notre tour d’horizon des scrapers open source met les catégories côte à côte.

Divulgation : Thunderbit est le produit de l’éditeur et n’a pas été testé dans ce fixture Katana. Il se situe en aval, dans la catégorie de l’extraction gérée, en transformant des pages en texte ou en enregistrements structurés plutôt qu’en énumérant la surface d’endpoints d’une cible autorisée. Un workflow peut utiliser les deux catégories, mais ce test ne fournit des preuves que du comportement de découverte de Katana.

Essayez Thunderbit pour l’extraction de données web

Verdict

Utilisez katana lorsque le livrable est une liste d’endpoints pour des cibles que vous êtes autorisé à explorer et que vous pouvez valider la couverture des modes sur ces cibles. Dans ce fixture, -jc en mode standard a retrouvé les littéraux JavaScript injectés, tandis que le mode headless a retrouvé l’endpoint inséré dans le DOM à l’exécution ; les modes sans navigateur testés de Katana n’ont pas retrouvé ce chemin à l’exécution. Le scope par défaut a également laissé le second hôte intact, et les exécutions sans navigateur ont continué après la réponse 500 et le lien mort.

Les réserves sont opérationnelles : une fusion en deux passes peut être nécessaire pour des classes d’endpoints mixtes, headless a pris environ cinq fois plus de temps local, la reprise sur un seul seed a refait passer des chemins déjà terminés, et le rappel des fichiers connus était de 0/2 face à la cible IP. Ce sont des résultats de fixture v1.6.1, pas des garanties universelles. Ils suffisent néanmoins à définir les vérifications qu’une évaluation de production devrait répéter.

Essayez Thunderbit pour l’extraction de données web Get Started Free

FAQ

Où Katana enregistre-t-il son fichier de reprise, et reprendre saute-t-il les pages déjà explorées ? Le checkpoint a été placé dans ~/.config/katana/resume-<xid>.cfg, et non dans un resume.cfg du répertoire de travail comme le laisse entendre l’aide du flag. Et non, il ne saute pas les pages terminées : le fichier ne stocke que les URL seeds en cours, donc une reprise sur un seed unique a refait passer les 11 chemins de base, y compris les 10 déjà terminés. On obtient le même ensemble final d’endpoints, mais pas le temps économisé.

Pourquoi -kf all a-t-il demandé mon sitemap.xml sans crawler les URL qu’il contenait ? Sur une cible IP, le résultat correspond davantage à une limite de validation du scope qu’à une erreur de flag. Dans le code v1.6.1, le parseur de sitemap de Katana construit chaque requête <loc> sans propager le nom d’hôte racine, et le contrôle de scope DNS pour les hôtes IP littéraux peut alors rejeter cette URL ; je n’ai pas instrumenté l’exécution pour confirmer ce mécanisme. Le rappel est resté à 0 sur toutes les variantes de flag, de profondeur et de seed que j’ai essayées. Une regex d’hôte personnalisée via -fs prend une autre branche de validation et c’est la solution que le code suggère — mais je n’ai pas pu la confirmer avec -kf sur ma machine, donc considérez-la comme non testée. Extraire vous-même les URL <loc> et les fournir à katana comme seeds est l’approche que je retiendrais aujourd’hui.

Que dois-je conserver lorsque je rends compte d’un test de couverture Katana ? Notez la version exacte de Katana et la commande, y compris l’expression -fs au caractère près ; définissez les classes d’endpoints avant l’exécution ; conservez les journaux de hits côté serveur en plus de la sortie standard ; et distinguez clairement ce qui a été mesuré de ce qui relève d’une hypothèse tirée du code source. Pour les exécutions headless, enregistrez aussi la build du navigateur — ce test ne l’a pas fait, ce qui limite la reproductibilité.

Dois-je utiliser -jc, -headless, ou les deux ? Choisissez en fonction des classes d’endpoints dont vous avez besoin. Dans ce fixture, -jc en mode standard a trouvé les littéraux stockés dans un fichier JavaScript, tandis que headless a trouvé l’endpoint injecté dans le DOM à l’exécution. Aucun mode n’a couvert les deux classes à lui seul, donc une exécution en deux passes suivie d’une déduplication était le choix défendable pour des cibles mixtes.

Une URL en échec arrêtera-t-elle le crawl ? Pas dans cet essai contrôlé. Katana a continué après une réponse 500 et un lien mort, tout en renvoyant les autres chemins accessibles. Cela ne remplace pas une comptabilité d’erreurs en production : conservez les journaux des requêtes en échec et définissez un taux d’échec acceptable afin qu’un crawl partiellement réussi ne soit pas confondu avec une couverture complète.

Ke
Ke
CTO chez Thunderbit | Data Scientist senior et expert en ML Forte d’une expérience de près de dix ans en machine learning et en data science, Ke Shen est diplômé de Columbia University et ancien Data Scientist senior chez Walmart Labs. Grâce à une expertise approfondie, reconnue par ses pairs, en Python, R, Java et statistiques, il partage des analyses éprouvées sur le passage d’algorithmes d’IA complexes de la théorie à une architecture prête pour la production.
Topics
Outils d’extraction WebExtracteur Web IA
Table des matières
Thunderbit · Agent IA de données web

Extrayez des données de n'importe quelle page en 1 clic

Approuvé par plus de 250 000 utilisateurs
formule gratuite disponible
De la page web au tableur
Décrivez ce dont vous avez besoin — l'agent IA de Thunderbit l'extrait et l'exporte vers Excel, Google Sheets, Airtable ou Notion. Gratuit pour commencer.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week