Katana-Test: `-jc` und `-headless` finden unterschiedliche Endpunkte, und kein einzelner Befehl deckte beide ab

Zuletzt aktualisiert am August 17, 2026
Katana-Test: `-jc` und `-headless` finden unterschiedliche Endpunkte, und kein einzelner Befehl deckte beide ab
KI-Zusammenfassung
Katana ist ProjectDiscoverys Crawler zur Endpunkt-Erkennung — ein Go-Binary unter MIT-Lizenz, das ein Ziel aufnimmt und URLs sowie Endpunkte für das nächste Tool in einer Pipeline ausgibt. Es crawlt entweder ohne Browser im HTTP-Modus oder mit -headless, wobei Chromium gesteuert wird. Die offizielle Empfehlung stellt den Headless-Modus als Option mit größerer Abdeckung dar; dieses Fixture zeigt, warum die Art des Endpunkts genauso wichtig ist wie die Anzahl. Ich habe eine kleine Website mit drei absichtlich unterschiedlichen Endpunkt-Klassen gebaut und gemessen, welche Modus-Variante auf v1.6.1 bei -d 4 welche davon findet.

Katana ist ProjectDiscoverys Crawler zur Endpunkt-Erkennung — ein Go-Binary unter MIT-Lizenz, das ein Ziel aufnimmt und URLs sowie Endpunkte für das nächste Tool in einer Pipeline ausgibt. Er crawlt entweder ohne Browser im HTTP-Modus oder mit -headless, wobei Chromium gesteuert wird. Die offizielle Empfehlung stellt den Headless-Modus als Option mit größerer Abdeckung dar; dieser Test zeigt, warum die Art des Endpunkts genauso wichtig ist wie die Anzahl.

Ich habe eine kleine Website mit drei absichtlich unterschiedlichen Endpunkt-Klassen gebaut und gemessen, welche Modus-Variante auf v1.6.1 bei -d 4 welche davon findet. Gewöhnliches HTML wurde in allen vier Konfigurationen vollständig erfasst: 4/4 Links und die komplette Kette über drei Ebenen. Der Unterschied zeigte sich bei Endpunkten, die entweder aus JavaScript-Quellen oder aus Laufzeit-Änderungen im DOM entstehen.

In diesem Test fand Headless die Laufzeit-DOM-Klasse, die die getesteten browserlosen Modi übersehen haben, während der Standardmodus mit -jc JavaScript-Dateiliterale fand, die beide Headless-Läufe verfehlten. Keine der vier Befehlsvarianten deckte beide Klassen ab. Scope, Resume und das Verhalten bei bekannten Dateien setzten die übrigen praktischen Grenzen.

Was Katana eigentlich ist

Der Katana-Crawler — auf GitHub unter projectdiscovery/katana — ist in Go geschrieben und MIT-lizenziert. Ich habe am 27. Juli 2026 v1.6.1 getestet; die Version ist wichtig, weil die hier beschriebenen Ergebnisse zu Abdeckung und bekannten Dateien buildspezifische Beobachtungen sind.

Die Kategorie ist hier besonders wichtig. Ein Crawler zur Endpunkt-Erkennung ist kein Extraktor für Inhalte. Wenn Sie einen Go-Webcrawler suchen, der Ihnen Produktnamen und Preise als strukturiertes JSON ausgibt, ist Katana die völlig falsche Schublade — er sagt Ihnen gern, dass /products/1138 existiert, aber nichts darüber, was auf dieser Seite steht. Genau so ist es gedacht; ihn nach seiner Extraktionsleistung zu beurteilen, wäre, als würde man einen Metalldetektor danach bewerten, wie gut er Schmuck einschätzt.

Sein Einsatzgebiet ist Reconnaissance und Automatisierung im Offensive-Security-Umfeld: STDIN rein, URLs raus, und dann an das nächste Tool weiterreichen. Damit ist der offensichtliche Vorbehalt gesetzt — alle Messungen hier liefen gegen ein von mir selbst geschriebenes Fixture auf 127.0.0.1. Verwenden Sie Katana nur auf Hosts, die Ihnen gehören oder für die Sie eine schriftliche Freigabe zum Testen haben. Hier geht es nicht darum, Schutzmechanismen zu umgehen, sondern darum, wie viel von einer Endpunktfläche ein bestimmter Befehl tatsächlich auflistet.

Die drei Modi und was jeder sehen kann

Der Standardmodus ist ein Go-HTTP-Client. Er ruft Seiten ab, parst HTML, folgt hrefs und startet nie einen Browser. Schnell, günstig, aber blind für alles, was erst nach Ausführung von JavaScript entsteht.

-jc (-js-crawl) setzt einen JavaScript-Parser auf diesen browserlosen Pfad. Dabei werden verlinkte .js-Dateien geladen und URL-ähnliche String-Literale aus dem Quelltext extrahiert. Keine Ausführung, nur Lesen. Es gibt außerdem -jsl (jsluice), das in der README als schwererer, speicherintensiver Parser beschrieben wird — ich habe ihn nicht getestet und kann daher nichts dazu sagen, ob er die Abdeckung verändert.

Systemdiagramm: Scope wird in Schichten angewendet

-headless steuert Chromium und führt Seitenskripte aus. In diesem Fixture war es der einzige getestete Katana-Modus, der den aus Fragmenten zusammengesetzten und in das Laufzeit-DOM eingefügten Pfad wiederherstellte. Das beweist nicht, was jeder Parser oder ein künftiger Katana-Modus erfassen könnte.

Dann gibt es noch das Scope-Modell — und das ist der Teil, den ich mir vor einem Einsatz in Produktion besonders genau merken würde.

FlagWas es steuertWerte / Standard
-fs (field scope)welche Hosts berücksichtigt werdendn, rdn, fqdn oder ein eigener Regex — Standard ist rdn
-cs und -cosURL-RegExe, die innerhalb dieses Field Scope filtern
-kfbekannte Dateien: robots.txt und sitemap.xmllaut README ist mindestens Tiefe 3 nötig
-dTiefeStandard 3
-resumesetzt einen unterbrochenen Crawl fort

Die Reihenfolge ist nicht nur Kosmetik: Sie entscheidet darüber, ob ein Host-Regex einen Crawl erweitert oder ihn stillschweigend auf null reduziert.

Setup: ein Binary, ein Sternchen

Drei Wege zur Installation, und nur einer davon braucht ein Toolchain:

InstallationswegVoraussetzung
Aus dem Quellcode: go install github.com/projectdiscovery/katana/cmd/katana@latestAls Voraussetzung wird Go 1.25 oder neuer genannt
Vorkompilierte Binaries auf der Release-Seitekein Toolchain nötig
Docker-Imagekein Toolchain nötig

Bei mir landete das Binary in ~/go/bin/katana und meldete bei jedem Lauf Current version: v1.6.1. Bis hierhin die übliche angenehme Go-Geschichte: eine Datei, keine Laufzeitabhängigkeit.

Das Sternchen ist der Headless-Betrieb, bei dem der Browser eine separate Voraussetzung ist und nicht Teil des Binaries:

Wo -headless läuftWas dafür nötig ist
Auf meinem RechnerKatana erkannte automatisch ein bereits installiertes Chromium; die Browser-Build-Version habe ich nicht dokumentiert und keinen Browser-Pfad angegeben
Auf einem nackten Server, laut den Ubuntu-Anweisungen des Projektsvor Headless erst apt install google-chrome-stable
Der Docker-WegHeadless läuft mit -system-chrome

Auf einem nackten Server verschwindet dieser Komfort. Planen Sie einen Browser ein, nicht nur ein Binary, sobald -headless in Ihrer Befehlszeile auftaucht.

Ein kleiner Punkt, der in CI wichtig ist: Katana ruft beim Start eine Versionsprüfung bei GitHub ab. -duc deaktiviert das. Auf einem Laptop ist das kaum der Rede wert; auf einem luftabgeschotteten oder rate-limitierten Runner ist es pro Lauf ein unnötiger Netzwerkrundlauf. Meine Zeitmessungen liefen mit -duc, damit die Zahlen das Crawling und nicht das Heimtelefonieren messen.

Wie ich getestet habe

Drei Arten von Endpunkten, bewusst so gewählt, dass sie die Modi voneinander trennen. Alles liegt auf einem lokalen Fixture-Server, und die Ground Truth wurde vor jedem Crawl festgelegt. So wird Recall gegen eine feste Menge gemessen und nicht gegen das, was Katana zufällig ausgibt.

  • Klasse A — normales HTML. /page/a, /page/b, /page/c sowie eine Kette über drei Ebenen /depth/1 → /depth/2 → /depth/3. Jeder Crawler sollte das finden.
  • Klasse B — Literale in JavaScript-Dateien. /api/js-endpoint-7 und /api/js-endpoint-8 existieren nur als String-Literale in einer verlinkten /static/app.js. Ohne Browser lesbar, sofern etwas die JS-Datei überhaupt liest.
  • Klasse C — nur im Laufzeit-DOM. Ein Pfad, der zur Laufzeit aus Fragmenten zusammengesetzt wird ('endpoint' + (6 * 7)) und per Skript ins DOM eingefügt wird. Die Zeichenfolge /runtime-only/endpoint42 erscheint in keinem Byte, das der Server sendet, zusammenhängend — weder im HTML noch im JS-Quelltext. Nur Ausführung macht sie sichtbar.

Dazu kommen eine robots.txt, eine sitemap.xml mit zwei <loc>-Endpunkten, die sonst nirgendwo auftauchen, eine Route mit 500-Fehler, ein toter Link und ein Link außerhalb des Scopes, der auf einen zweiten Server unter einem anderen Hostnamen zeigt.

Das Messinstrument ist fast so wichtig wie das Fixture: Der Server zählt was tatsächlich abgefragt wurde, sodass Scope- und Resume-Aussagen auf echten Treffern beruhen und nicht auf Katana-Stdout. Die Rohdurchläufe sind im Benchmark-Repo eingecheckt, falls Sie meine Rechnung überprüfen möchten.

Die Abdeckungslücke, die niemand quantifiziert

Gemessene Ergebnisse: Endpunktabdeckung nach Katana-Modus

Die Matrix nach Modus und Endpunktklasse bei -d 4:

ModusHTML-Links (A)Tiefen-Kette (A)JS-Datei-Literale (B)Laufzeit-DOM (C)
standard4/43/30/2nicht gefunden
standard -jc4/43/32/2nicht gefunden
-headless4/43/30/2gefunden
-headless -jc4/43/30/2gefunden

Wenn man die letzten beiden Spalten zusammen liest, wird das Problem sofort klar. Klasse B wurde nur von genau einer Konfiguration gefunden: dem Standardmodus mit -jc. Klasse C wurde nur von genau zwei gefunden: beiden Headless-Läufen. Es gibt keine Zeile, die in beiden Spalten Treffer zeigt. Die vollständige Matrix steht in discovery-summary.json, wo das berechnete Feld headless_jc_covers_both den Wert false trägt.

Die praktische Folge: „einfach Headless für bessere Abdeckung verwenden“ war für diesen Test nur die halbe Wahrheit. Headless ergänzte Klasse B nicht zum Standardergebnis, sondern stellte Klasse C wieder her, während Klasse B fehlte. Um in diesem Fixture alle absichtlich platzierten Klassen abzudecken, brauchte es zwei Crawls und ein Zusammenführen:

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

Die Zeile -headless -jc ist die, zu der ich mir am ehesten eine Antwort von upstream wünschen würde. Das Hinzufügen des JavaScript-Parsers zum Headless-Lauf brachte nichts Neues — weiterhin 0/2 bei Klasse B, in jedem Lauf, auch bei einer frischen Reproduktion. Ich berichte das Verhalten; ich behaupte nicht, den Mechanismus aufgeklärt zu haben. Ich habe Katana intern nicht instrumentiert, um herauszufinden, warum der Browserpfad keine JS-Dateiliterale mehr beiträgt. Behandeln Sie das als reproduzierbare Beobachtung und als guten GitHub-Issue, nicht als Diagnose. (Bemerkenswert am Rande: die Kombination -hl -jc lief auf v1.6.1 unter macOS ARM sauber mit Rückgabecode 0 durch; historisch war das nicht immer so.)

Die offizielle Doku beschreibt Headless als Variante mit besserer Abdeckung, und genau das war hier für die zur Laufzeit gerenderte Klasse auch der Fall. Die geprüfte Anleitung erklärte diesen Split zwischen Quelltext-Literalen und Laufzeit-DOM jedoch nicht. Verstehen Sie die Matrix daher als Anlass, beide Pfade gegen Ihre eigenen Endpunktklassen zu testen — nicht als universelle Taxonomie.

Was Headless an Zeit kostet

Drei aufeinanderfolgende Läufe pro Modus auf einem sonst untätigen Rechner:

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

Das ist ein Verhältnis von 5,1x, und die Bereiche überlappen sich nicht einmal ansatzweise — mein langsamster Standardlauf (13.17s) war immer noch mehr als 53 Sekunden schneller als mein schnellster Headless-Lauf (66.78s) (cost-summary.json). Das ist kein Messrauschen.

Eine Einschränkung zu diesen 13 Sekunden: Mein Fixture enthält absichtlich eine 500-Route und einen toten Link, und der Standardmodus wartet auf beiden den Default--timeout 10-Retry-Schwanz ab. Ich habe den Timeout nicht so getunt, dass der schnelle Modus besser aussieht. Ein optimierter Standardlauf würde die Lücke also wahrscheinlich vergrößern und nicht verkleinern.

Das Verhältnis ist ein lokales Kapazitätssignal, keine Prognose für Produktion. Echte Ziele unterscheiden sich in Latenz, Fehlerraten, Skriptlast und Scheduling, während dieses Fixture den üblichen Timeout-Schwanz mitbringt. Nutzen Sie den gemessenen 5,1x-Unterschied, um zu entscheiden, ob Headless ein eigenes Budget und eine eigene Zielmenge verdient, und testen Sie diesen Plan anschließend auf repräsentativen, autorisierten Hosts.

Scope blieb erhalten, aber ein Flag tat stillschweigend nichts

Der Scope-Test verwendete zwei Server: den primären auf 127.0.0.1 und einen zweiten, erreichbar als localhost auf einem anderen Port, der einen Pfad bediente, der nur dort existiert. Ein Treffer auf diesem Pfad ist also der Beweis, dass der Host außerhalb des Scopes tatsächlich abgefragt wurde und nicht nur ausgegeben.

KonfigurationHost außerhalb des Scopes abgefragt?Treffer auf dem zweiten Server
Standard (-fs rdn)nein0
-fs fqdnnein0
-cs localhostnein0
`-fs '(127.0.0.1localhost)'`ja

Die strenge Scope-Disziplin ist gute Nachricht: Standardmäßig blieb Katana bei sich, und eine explizite Erweiterung war nötig. Das ist genau der richtige Standard für ein Tool, das gegen fremde Infrastruktur eingesetzt wird.

Die interessante Zeile ist -cs localhost. Das erweiterte den Crawl nicht auf den zweiten Host — und es gab dabei auch überhaupt keine URLs. Da -cs innerhalb des Field Scope filtert und der Field Scope weiterhin nur den primären Host umfasste, passte der Regex auf nichts und der Crawl lieferte statt eines Fehlers eine leere Menge zurück. Wenn Sie schon einmal einen Crawl-Scope-Regex geschrieben haben, der einen Host nennen sollte, und dann auf eine leere Ausgabedatei gestarrt haben, dann ist das genau der Mechanismus (scope-summary.json). Um einen Host hinzuzufügen, setzen Sie -fs. Um innerhalb bereits eingeschlossener Hosts einzuschränken, nutzen Sie -cs/-cos.

Resume ist grober, als das Flag vermuten lässt

Die README beschreibt das Flag als -resume string resume scan using resume.cfg, was so klingt, als würde die Datei im Arbeitsverzeichnis landen. Tut sie nicht. Auf meinem Rechner wurde der Checkpoint nach ~/.config/katana/resume-<xid>.cfg geschrieben — gemessen, nicht aus einer Doku abgelesen, weil die Doku keinen Pfad nennt.

Der wichtigere Überraschungseffekt steckt im Inhalt. Die Datei enthielt eine InFlightUrls-Map mit genau einem Eintrag: der Seed-URL. Nicht die besuchten URLs, nicht die Frontier. Das passierte also, als ich einen Crawl nach drei Sekunden mit SIGINT unterbrach und anschließend fortsetzte:

LaufUnterschiedliche Pfade
Vollständiger Baseline-Crawl11
Vor dem Interrupt abgerufen10
Vom Resume-Lauf erneut abgerufenalle 11, einschließlich aller 10, die bereits abgeschlossen waren

Resume erreichte denselben finalen Endpunkt-Satz, also ist nichts kaputt. Aber die Granularität des Checkpoints ist pro Input-Seed, nicht pro URL — der In-Memory-Dedupe-Filter wird nie persistiert, daher crawlt ein fortgesetzter Single-Seed-Lauf diesen Seed von vorn erneut (resume-summary.json). Wenn Sie Katana eine Liste von 500 Hosts geben, sollte Resume Ihnen die Hosts sparen, die vollständig fertig wurden; dieses Multi-Seed-Verhalten ergibt sich aus der Art der Speicherung, aber ich habe nur den Single-Seed-Fall gemessen. Wenn Sie tief in einer sehr großen Site stecken, bringt Resume Ihnen Korrektheit, nicht Zeit.

Known Files: angefordert und dann fallen gelassen

Systemdiagramm: Known files: angefordert und dann fallen gelassen

-kf all -d 3 hat beide Dateien tatsächlich angefordert — robots.txt und sitemap.xml tauchten im Hit-Log des Servers auf — und dann 0 von 2 der Endpunkte aus den <loc>-Einträgen dieser Sitemap wiedergefunden. Recall 0.0.

Bevor ich das als Limit bezeichne, wollte ich sicher sein, dass nicht ich der Fehler bin. Jede Variante lieferte dasselbe Ergebnis:

Ausprobierte VarianteWiederhergestellte Sitemap-<loc>-Endpunkte
-kf all0/2, Recall 0.0
-kf sitemapxml0/2, Recall 0.0
-kf robotstxt0/2, Recall 0.0
Tiefe 30/2, Recall 0.0
Tiefe 40/2, Recall 0.0
Tiefe 50/2, Recall 0.0
mit zusätzlich -jc0/2, Recall 0.0
direkt bei /sitemap.xml gestartet0/2, Recall 0.0

Die dokumentierte Voraussetzung — -kf verwenden, mindestens drei Ebenen tief crawlen — war jedes Mal erfüllt. Das ist also keine Geschichte über ein fehlendes Flag.

Die nützliche Entscheidung kommt zuerst: In diesem IP-literal-Fixture sollten Sie nicht annehmen, dass das Anfordern bekannter Dateien bedeutet, dass deren <loc>-URLs in den Crawl aufgenommen wurden. Prüfen Sie den Recall oder extrahieren und seeden Sie diese URLs selbst.

Der Codepfad in v1.6.1 passt zur Beobachtung, auch wenn ich ihn während des Laufs nicht instrumentiert habe. In sitemapxml.go in v1.6.1 baut NewNavigationRequestURLFromResponse <loc>-Navigation-Requests aus einer Response, ohne RootHostname zu setzen. Der Request gelangt dann zu ValidateScope; in scope.go in v1.6.1 vergleicht der IP-literal-Zweig den Host der URL mit diesem leeren Root und kann sie ablehnen. Der benutzerdefinierte Befehl -fs '(127.0.0.1|localhost)' nahm in einem separaten Scope-Test einen anderen Branch, also ist das eine aus dem Quelltext abgeleitete Rettung, kein gemessener -kf-Workaround. Ein Bestätigungsversuch wurde durch intermittierende Verbindungsprobleme im Known-Files-Client auf diesem Host blockiert; das berichtete Ergebnis bleibt daher 0/2.

Was ich in Produktion bis zur Bestätigung des Flags tatsächlich tun würde: die Sitemap selbst abrufen, die <loc>-URLs extrahieren und Katana als Seed-Liste übergeben. Zwei Shell-Zeilen, keine Scope-Validierung dazwischen.

Ein Punkt verhielt sich exakt wie angekündigt und verdient einen Satz: Die 500-Route und der tote Link wurden abgerufen, protokolliert und übersprungen. Jeder browserlose Lauf endete mit Rückgabecode 0. Ein Crawler, der beim ersten schlechten Response stirbt, ist unbeaufsichtigt nutzlos — Katana tut das nicht.

Ein target-spezifischer Coverage-Check vor dem Rollout

Die Fixture-Matrix ist am nützlichsten als Vorlage, um Ihre eigenen autorisierten Ziele zu testen. Definieren Sie die Endpunktklassen vor dem Einsatz von Katana: normale Links, Literale in verlinkten Skripten, erst nach Ausführung erzeugte Routen und Einträge aus bekannten Dateien sind vier sinnvolle Ausgangsgruppen. Halten Sie für jede Klasse eine kleine Ground-Truth-Stichprobe vor. Ohne diese Vorab-Liste kann eine größere Stdout-Ausgabe wie bessere Abdeckung aussehen, obwohl eine Klasse verschwunden ist.

Messen Sie browserlosen und Headless-Pfad zunächst getrennt. Speichern Sie die exakten Befehle, die Katana-Version, die Browser-Build-Version, Rückgabecodes und Ausgaben. Normalisieren und diffen Sie die Endpunktmengen statt nur Zeilenanzahlen zu vergleichen. Wenn Standard--jc auf Ihrer Stichprobe nichts Einzigartiges beiträgt, kann eine reine Headless-Policy reichen; wenn die Mengen auseinanderlaufen wie hier, halten Sie die beiden Läufe getrennt und mergen Sie erst danach. Dass beide Flags in einem einzigen Befehl stehen, sollte nicht automatisch als Vereinigung gelten, bis der target-spezifische Diff das belegt.

Validieren Sie den Scope mit Belegen außerhalb von Katana-Ausgaben. Legen Sie eine Canary-URL auf einem Host ab, der ausgeschlossen bleiben sollte, und prüfen Sie das Request-Log dieses Servers. Testen Sie auch einen vorgesehenen zweiten Host, wenn der Crawl erweitert werden soll. Der Lauf -cs localhost erzeugte hier eine leere Ausgabe, weil das Content-Scope-Filtering den Field Scope nicht erweitert hat; der benutzerdefinierte Aufruf -fs '(127.0.0.1|localhost)' kontaktierte dagegen den zweiten Server. Das exakte Regex zu dokumentieren ist wichtig, weil eine Änderung um ein Zeichen den regulären Ausdruck selbst verändert und nicht nur seine Darstellung.

Testen Sie Unterbrechung und Known Files getrennt von der Discovery-Recall-Messung. Für Resume unterbrechen Sie einen repräsentativen Seed nach einigen Seiten, speichern den erzeugten Checkpoint-Pfad und zählen, wie viele bereits abgeschlossene URLs erneut abgerufen werden. Für -kf bestätigen Sie sowohl, dass robots/sitemap angefordert wurden, als auch dass die platzierten <loc>-URLs tatsächlich eingeplant wurden. Das sind unterschiedliche Aussagen. In diesem Fixture wurden die Dateien abgerufen, während die beiden Sitemap-Endpunkte fehlten — daher brauchte es sowohl Request-Logs als auch Endpoint-Ausgabe, um die Grenze zu sehen.

Schließlich sollten Sie eine lokale Kostenbasis mit sequenziellen Läufen auf einem sonst ruhigen Rechner festlegen und dann auf repräsentativen Hosts wiederholen. Bewahren Sie Minimum, Maximum und Median auf, nicht nur einen Multiplikator. Die hier gemessenen 5,1x enthalten das Fehler- und Timeout-Verhalten dieses Fixtures; sie sagen Ihnen, dass Headless ein eigenes Budget verdient, nicht wie lange ein Produktionsinventar dauern wird.

Pro und Contra

Pro:

  • Vollständiger Recall bei normalem HTML in jedem Modus — 4/4 Links und die komplette 3/3-Tiefenkette, ganz ohne Zusatzkonfiguration.
  • -jc funktioniert tatsächlich auch ohne Browser: 2/2 Endpunkte aus String-Literalen in einer verlinkten JS-Datei, ohne Browserkosten.
  • -headless ist das einzige, was einen zur Laufzeit zusammengesetzten Endpunkt gefunden hat — eine Klasse, die aus Quelltextanalyse konstruktionsbedingt unsichtbar ist.
  • Die Standard-Scope-Einstellungen sind konservativ. Der Host außerhalb des Scopes wurde weder unter Standard, noch mit -fs fqdn, noch mit -cs abgefragt.
  • Ein einziges Go-Binary, MIT-Lizenz, vorkompilierte Builds und ein Docker-Image, Pipeline-taugliche Ein-/Ausgabe.
  • Robust bei Fehlern: 500er und tote Links stoppen den Crawl nicht.

Contra:

  • Kein einzelner Lauf deckte sowohl JS-Datei- als auch Laufzeit-DOM-Endpunkte ab. Vollständige Abdeckung braucht zwei Läufe und ein Merge.
  • -jc brachte unter -headless keinen Zusatznutzen — 0/2 bei Klasse B in jedem Headless-Lauf.
  • Headless kostet 5,1x Laufzeit (66.82s vs. 13.08s p50, nicht überlappende Bereiche).
  • -resume crawlt bereits fertiggestellte Seiten innerhalb eines Seeds erneut. Es stellt den Endpunkt-Satz wieder her, nicht Ihre verstrichene Zeit.
  • Known Files holte robots.txt und sitemap.xml an, fand aber 0/2 Sitemap-<loc>-Endpunkte gegen ein IP-Ziel.
  • Headless setzt stillschweigend Chromium auf der Maschine voraus; die Geschichte vom „einen Binary“ endet beim Browser.
  • Nur Discovery. Keine strukturierte Extraktion, keine Inhaltskonvertierung, kein Feldschema.

Nicht getestet und daher außerhalb dessen, was diese Zahlen abdecken: -jsluice, ein gezielter Tiefenabbruchtest bei -d 1/-d 2, Multi-Seed-Resume, automatisches Ausfüllen von Formularen und jede echte JavaScript-lastige oder geschützte Produktionsseite. Alle Zahlen stammen von einer Maschine (macOS arm64) gegen ein lokales Fixture.

Für wen es ist — und wer es lieber lässt

Wenn Ihr Job darin besteht, ein Endpunkt-Inventar für Infrastruktur zu erstellen, die Sie autorisiert testen dürfen, hat Katana die passende Pipeline-Form: STDIN/STDOUT-Verkabelung, ein verteilbares Binary und sowohl browserlose als auch browsergestützte Modi. Der Zwei-Pass-Merge war für die hier platzierten Klassen notwendig; ob Ihre Ziele beide Durchgänge brauchen, müssen Sie anhand repräsentativer Seiten feststellen.

Lassen Sie es weg, wenn Sie Daten statt Adressen wollen. Katana liefert Ihnen nie eine Produkttabelle; es liefert URLs, unter denen Produkte liegen könnten, und etwas anderes übernimmt die Extraktion. Lassen Sie es auch weg, wenn Sie für Vollständigkeit einen einzelnen Befehl brauchen — der Zwei-Pass-Merge ist in einer Pipeline in Ordnung, an der Konsole aber lästig. Und wenn Ihre Enumeration auf Sitemap-<loc>-Endpunkten bei IP-Zielen basiert, prüfen Sie vorher, was tatsächlich zurückkommt, denn in meinem Fixture lieferte dieser Pfad nichts.

Alternativen und die Grenze zur Extraktion

Katana ist kostenlos, MIT-lizenziert und selbst gehostet. Es behält Erkennung, Moduswahl, Browser-Bereitstellung und Ergebniszusammenführung auf Ihrer Seite der Grenze.

Innerhalb von Open Source sind die nützlichen Vergleiche eher arbeitsbezogen als sprachbezogen. Colly ist die andere Go-Option, aber es ist eine Bibliothek, die Sie mit eigenen Callbacks kompilieren; JavaScript rendert sie überhaupt nicht. Crawl4AI startet einen echten Browser und erzeugt Markdown für LLM-Pipelines — also eine ganz andere Ausgabe. Wenn Sie mehrere dieser Tools gegeneinander abwägen, ordnet unser Open-Source-Scraper-Überblick die Kategorien nebeneinander ein.

Offenlegung: Thunderbit ist das Produkt des Herausgebers und wurde in diesem Katana-Fixture nicht getestet. Es liegt in der verwalteten Extraktionskategorie und verwandelt Seiten in Text oder strukturierte Datensätze, statt die Endpunktfläche eines autorisierten Ziels aufzulisten. Ein Workflow kann beide Kategorien nutzen, aber dieser Test liefert Belege nur für das Erkennungsverhalten von Katana.

Thunderbit für Web-Datenextraktion testen

Fazit

Setzen Sie Katana ein, wenn das Ergebnis eine Endpunktliste für Ziele ist, die Sie autorisiert crawlen dürfen, und wenn Sie die Modus-Abdeckung gegen diese Ziele validieren können. In diesem Fixture fand Standard--jc die absichtlich platzierten JavaScript-Dateiliterale, während Headless den Laufzeit-DOM-Endpunkt fand; die getesteten browserlosen Modi von Katana fanden diesen Laufzeitpfad nicht. Der Standard-Scope hielt außerdem den zweiten Host fern, und browserlose Läufe arbeiteten trotz 500er und totem Link weiter.

Die Einschränkungen sind operativ: Für gemischte Endpunktklassen kann ein Zwei-Pass-Merge nötig sein, Headless brauchte etwa fünfmal so viel lokale Laufzeit, ein Single-Seed-Resume rief abgeschlossene Pfade erneut ab, und die Known-Files-Abdeckung lag gegen das IP-Ziel bei 0/2. Das sind Ergebnisse aus v1.6.1 und einem Fixture, keine Zusagen für jede beliebige Website. Sie reichen aber aus, um die Prüfungen zu definieren, die eine Produktionsbewertung wiederholen sollte.

Thunderbit für Web-Datenextraktion testen Get Started Free

FAQs

Wo speichert Katana seine Resume-Datei, und überspringt das Fortsetzen bereits gecrawlte Seiten? Der Checkpoint landete bei mir in ~/.config/katana/resume-<xid>.cfg und nicht in einer resume.cfg im Arbeitsverzeichnis, wie es der Hilfetext des Flags nahelegt. Und nein, bereits abgeschlossene Seiten werden nicht übersprungen: Die Datei speichert nur in-flight Seed-URLs, daher hat ein fortgesetzter Single-Seed-Crawl alle 11 Baseline-Pfade erneut abgefragt, einschließlich der 10 bereits erledigten. Sie erhalten denselben finalen Endpunkt-Satz, aber nicht die gesparte Zeit.

Warum hat -kf all meine sitemap.xml angefordert, aber die darin enthaltenen URLs nicht gecrawlt? Bei einem IP-Ziel ist das eher eine Grenze der Scope-Validierung als ein Fehler des Flags. Katana baut im Sitemap-Parser jeden <loc>-Request, ohne den Root-Hostname mitzuschleppen, und die DNS-Scope-Prüfung für IP-literal-Hosts vergleicht dann den Host der URL mit diesem leeren Root, scheitert an der Prüfung und verwirft die URL. Das blieb über alle Flag-, Tiefen- und Seed-Varianten hinweg bei 0 Recall. Ein eigener -fs-Host-Regex nimmt einen anderen Validierungszweig und ist die vom Quellcode erwartete Lösung — auf meinem Rechner konnte ich das aber nicht mit -kf bestätigen, also behandeln Sie es bitte als ungetestet. Die <loc>-URLs selbst zu extrahieren und Katana damit zu seeden, ist derzeit der Ansatz, dem ich vertrauen würde.

Was sollte ich bei der Berichterstattung eines Katana-Coverage-Tests festhalten? Dokumentieren Sie die exakte Katana-Version und den Befehl, einschließlich des Byte-für-Byte--fs-Ausdrucks; definieren Sie die Endpunktklassen vor dem Lauf; bewahren Sie neben Stdout auch die serverseitigen Hit-Logs auf; und trennen Sie gemessene Beobachtungen von quellenbasierten Hypothesen. Bei Headless-Läufen sollte auch die Browser-Build-Version mitprotokolliert werden — das ist in diesem Test nicht geschehen, was die Reproduzierbarkeit einschränkt.

Soll ich -jc, -headless oder beides verwenden? Wählen Sie nach den Endpunktklassen, die Sie brauchen. In diesem Fixture fand Standard--jc Literale in einer JavaScript-Datei, während Headless den in das Laufzeit-DOM eingefügten Endpunkt fand. Keine der beiden Varianten deckte beide Klassen allein ab, daher war ein Zwei-Pass-Lauf mit anschließendem Deduplizieren die vertretbare Wahl für gemischte Ziele.

Stoppt ein fehlerhafter URL den Crawl? In diesem kontrollierten Lauf nicht. Katana lief nach einer 500-Antwort und einem toten Link weiter und lieferte trotzdem die übrigen erreichbaren Pfade. Das ersetzt allerdings keine Fehlerbilanz in der Produktion: Führen Sie Logs über fehlgeschlagene Requests und legen Sie eine akzeptable Fehlerrate fest, damit ein teilweise erfolgreicher Crawl nicht fälschlich als vollständige Abdeckung gilt.

Ke
Ke
CTO bei Thunderbit | Senior Data Scientist & ML-Experte Mit fast zehn Jahren Erfahrung in Machine Learning und Data Science ist Ke Shen Absolvent der Columbia University und ehemaliger Senior Data Scientist bei Walmart Labs. Mit tiefgreifender, von Fachkollegen anerkannter Expertise in Python, R, Java und Statistik teilt er praxiserprobte Einblicke dazu, wie sich komplexe KI-Algorithmen von der Theorie in eine produktionsreife Architektur überführen lassen.
Inhaltsverzeichnis
Von der Webseite zur Tabelle
Beschreibe, was du brauchst — Thunderbits KI-Agent erfasst es und exportiert es nach Excel, Google Sheets, Airtable oder Notion. Kostenlos loslegen.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week