Recenzja Apache Tika: Odczytuje bajty, a nie nazwę pliku — aż trafia na Markdown

Ostatnia aktualizacja: August 14, 2026
Recenzja Apache Tika: Odczytuje bajty, a nie nazwę pliku — aż trafia na Markdown
Podsumowanie AI
Apache Tika to zestaw narzędzi Apache Software Foundation do analizowania dokumentów: podajesz plik niemal dowolnego typu, a w zamian dostajesz zwykły tekst oraz ujednolicony słownik metadanych. W pliku README projektu reklamowanych jest ponad tysiąc obsługiwanych typów plików, a Tika osiąga to, dołączając własne biblioteki specjalistyczne — PDFBox dla PDF-ów, Apache POI dla dokumentów Office, jsoup dla HTML, czytnik ODF dla ODT — dzięki czemu całość działa jako pojedynczy, „gruby” JAR, bez potrzeby pobierania czegokolwiek w trakcie parsowania. W potoku danych pełni mało efektowną, ale kluczową rolę: stoi przed indeksem wyszukiwania, zbiorem do e-discovery albo korpusem dla LLM i zamienia heterogeniczny stos plików w coś jednolitego.

Apache Tika to zestaw narzędzi Apache Software Foundation do analizowania dokumentów: podajesz plik niemal dowolnego typu, a w zamian dostajesz zwykły tekst oraz ujednolicony słownik metadanych. W pliku README projektu reklamowanych jest ponad tysiąc obsługiwanych typów plików, a Tika osiąga to, dołączając własne biblioteki specjalistyczne — PDFBox dla PDF-ów, Apache POI dla dokumentów Office, jsoup dla HTML, czytnik ODF dla ODT — dzięki czemu całość działa jako pojedynczy, „gruby” JAR, bez potrzeby pobierania czegokolwiek w trakcie parsowania. W potoku danych pełni mało efektowną, ale kluczową rolę: stoi przed indeksem wyszukiwania, zbiorem do e-discovery albo korpusem dla LLM i zamienia heterogeniczny stos plików w coś jednolitego. Tak naprawdę robi dwie rzeczy: rozpoznaje, czym jest strumień bajtów, a potem wydobywa z niego tekst i metadane.

To najprostsze narzędzie, jakie konfigurowałem od dawna. Jeden JAR, java -jar tika-app-3.3.2.jar --text file.pdf, bez pliku konfiguracyjnego, bez wag modelu, bez kroku po instalacji — i działał bez problemu na najnowszym JDK, które tego samego popołudnia unieruchomiło na tym samym hoście inne narzędzia Javowe. Nie to jednak chciałem sprawdzać; ważniejsze pytanie było węższe. Co Tika faktycznie robi, gdy wejście kłamie? Zbudowałem więc kontrolowany zestaw testowy, w którym każdy blok treści miał unikalny znacznik, wyrenderowałem ten sam logiczny dokument do dziewięciu formatów nośnikowych, a potem zaatakowałem całość złymi rozszerzeniami, brakującymi rozszerzeniami, plikami bez nazw oraz pustymi i uciętymi binarkami.

Najciekawsze zachowanie widać na etapie detekcji. Przemianowałem PDF na .txt i zapytałem Tikę, czym on jest; odpowiedziała application/pdf. Potem usunąłem nazwę pliku całkowicie, podałem surowe bajty przez stdin i dostałem dokładnie tę samą odpowiedź. We wszystkich pięciu formatach, które da się rozpoznać po treści, rezultat był taki sam w 20 unikalnych warunkach logicznych: trzy warianty nazw pliku plus jeden wariant bez nazwy dla każdego formatu. Testy w harnesie uruchamiały przypadek streamu trzy razy pod różnymi etykietami, co dało 30 udanych uruchomień surowych, ale te powtórki nie są niezależnym dowodem. PDF i RTF mają rozpoznawalne nagłówki bajtowe; DOCX ujawnia swój kontener; HTML i XML można wykryć po znacznikach lub elemencie głównym. Inny mechanizm, ten sam praktyczny efekt w tym zestawie: rozszerzenie nie przebiło treści. A potem jest jeszcze rodzina tekstowa, gdzie Markdown wpada do text/plain w momencie, gdy nazwa pliku jest błędna albo znika całkiem. Tutaj jego tożsamość opierała się wyłącznie na .md.

Dwie ważne granice dla wszystkich dalszych liczb. Testowałem Apache Tika 3.3.2 — sprawdzone 27 lipca 2026, nadal była to najnowsza stabilna wersja; linia 4.0.0 istnieje wyłącznie jako buildy alpha i beta w Maven Central. Projekt miał wtedy około 3,9 tys. gwiazdek na GitHubie i licencję Apache-2.0, czyli jedną z najbardziej przyjaznych komercyjnie, jakie istnieją. I w ogóle nie testowałem OCR. Ani jednej skanowanej strony, ani jednego PDF-a zawierającego wyłącznie obraz. Tesseract i poppler nie były zainstalowane na maszynie, na której to uruchamiałem, więc każda ścieżka OCR była zablokowana zanim się zaczęła. Nie ma tu żadnych liczb dla OCR, bo po prostu nie ma żadnych liczb dla OCR.

Czym Tika jest naprawdę, gdy przestaniesz czytać marketing na pudełku

Powszechne założenie jest takie, że Apache Tika to konwerter dokumentów — wrzucasz DOCX-a i dostajesz czysty Markdown z zachowanymi nagłówkami i tabelami. To nie to, a im szybciej to wybrzmi, tym lepiej narzędzie wygląda.

Testowana tutaj ścieżka ma trzy istotne etapy: detektor typu zawartości, dispatcher, który przekazuje bajty do właściwego parsera, oraz obsługę wyjścia CLI --text, która emituje płaski tekst razem z osobno dostępnymi metadanymi. W tym kontrakcie wyjścia nie ma obiektów Title, ListItem ani odtworzonej siatki tabeli. Tika udostępnia też inne handlery i API, w tym wyjście oparte na XHTML/SAX; nie testowałem ich. Każdy wniosek o strukturze poniżej dotyczy więc tika-app --text, a nie twierdzenia, że toolkit nigdzie nie ma strumienia zdarzeń o strukturze.

Brzmi to jak ograniczenie — i pod jednym względem nim jest. Ale oznacza też, że Tika nie ma czego błędnie zaklasyfikować, a to dokładnie ta wymiana, którą jego bardziej „gadatliwi” kuzyni robią w drugą stronę.

Sam proces detekcji przebiega w udokumentowanej kolejności: najpierw sygnatury bajtowe, potem sprawdzenie korzenia XML, następnie dopasowanie nazwy pliku, a na końcu typ podany przez użytkownika (własna dokumentacja detekcji Tiki opisuje to wprost). Dopiero po rozpoznaniu typu dispatcher przekazuje bajty do odpowiedniego dołączonego parsera — PDFBox, POI, jsoup, TextAndCSVParser dla rodziny tekstowej.

Ten podział na detekcję i parsowanie nie jest wewnętrzną ciekawostką. Dzięki niemu plik zbyt uszkodzony, by go sparsować, nadal może zostać poprawnie zidentyfikowany — i właśnie to staje się najpraktyczniejszym trikiem Tiki, kiedy coś zaczyna się psuć.

Konfiguracja: jeden JAR, jedna komenda i JVM, który nie marudzi

Instalacja to po prostu pobranie pliku. tika-app-3.3.2.jar z Maven Central ma około 67 MB — to „gruby” JAR zawierający każdy parser — a potem wystarczy java -jar tika-app-3.3.2.jar --text file.pdf. Bez konfiguracji, bez wag modeli, bez kroku po instalacji, bez łańcuszka brew install do przejścia.

Historia z JDK mnie zaskoczyła. Uruchomiłem wszystko na OpenJDK 26.0.1, czyli najnowszym, nie-LTS buildzie, i --version, --text, --metadata oraz --detect wszystkie zwracały exit 0 bez żadnych uwag o kompatybilności. Warto to odnotować, bo tego samego dnia, na tym samym hoście, testowałem Apache Nutch i jego cykl crawl w ogóle nie chciał ruszyć na JDK 26 — potrzebuje LTS 21 lub niżej, przez usunięcie SecurityManagera w nowszych JDK. Tika miał to gdzieś. Jeśli unikasz narzędzi JVM właśnie z powodu takiego bólu, to Tika nie jest miejscem, w którym Cię to ugryzie.

Dwie uczciwe uwagi po stronie konfiguracji. CLI uruchamia nową JVM przy każdym wywołaniu, więc zimny start jest realny — 131 wywołań w moim harnesie zajęło około minutę, głównie przez rozgrzewanie JVM. Jeśli przetwarzasz pliki na dużą skalę, lepsza będzie biblioteka albo tryb serwerowy, a nie pętla shellowa wokół JAR-a. I historia „bez zależności” ma twardą granicę: wydobywanie tekstu z warstwy PDF nie wymaga niczego zewnętrznego, ale OCR potrzebuje tesseract i poppler. PDF-y z warstwą tekstową, DOCX, ODT, RTF, HTML, XML, TXT, Markdown i CSV parsowały się na hoście, gdzie nie było zainstalowane nic z tego. Skanowane dokumenty nie zrobiłyby tego, i nie udawałem, że jest inaczej.

Ten kontrast jest jeszcze ostrzejszy w zestawieniu z siostrzaną biblioteką, którą testowałem tego samego dnia, unstructured, gdzie ścieżka dla elektronicznych PDF-ów była całkowicie zablokowana, bo import modułu PDF wciąga stos inferencyjny (torch i spółkę) już przy ładowaniu — zanim w ogóle dojdzie do wyboru strategii, więc nawet strategia „fast” nie zaimportuje się bez tego. Tika wyciągnęła tekst z tego samego PDF-a zwykłym java -jar.

Test kłamliwego rozszerzenia: wykrywanie typu MIME, które ignoruje nazwę pliku

Measured results chart: Type detection across filename conditions

Osiem formatów, każdy pokazany z poprawnym rozszerzeniem, celowo błędnym rozszerzeniem albo bez rozszerzenia, plus strumień bajtów bez nazwy na stdin. To daje 32 unikalne warunki logiczne. Oryginalny harness uruchamiał też identyczne bajty streamu raz pod każdą etykietą nazwy pliku, co dało 48 surowych uruchomień; te trzy wiersze streamu sklejają się w jeden warunek, bo stdin nie niesie nazwy pliku.

FixturePrawdziwy typPrzemianowano naPoprawne rozszerzenieKłamliwe rozszerzenieBez rozszerzeniaSurowy stream, bez nazwy pliku
PDFapplication/pdf.txt
DOCXOOXML wordprocessingml.jpg
RTFapplication/rtf.html
HTMLtext/html.csv
XMLapplication/xml.txt
Zwykły teksttext/plain.pdf
Markdowntext/markdown.pdftext/plaintext/plaintext/plain
CSVtext/csv.txttext/plaintext/plaintext/plain

(Kolumna streamu scala wszystkie trzy warianty rozszerzeń, bo bez nazwy pliku nie ma czego dopasowywać po globie.)

Pięć formatów wykrywanych po treści — PDF, DOCX, RTF, HTML i XML — trafiło w prawdziwy typ w 20 z 20 unikalnych warunków (i w 30 z 30 surowych uruchomień harnesu, wliczając zduplikowane uruchomienia streamu). PDF nazwany report.txt nadal był PDF-em. DOCX nazwany photo.jpg nadal był DOCX-em. Żaden z nich nie potrzebował nazwy pliku. Nie znaczy to jednak, że wszystkie pięć używa sztywnych sygnatur bajtowych: PDF i RTF mają rozpoznawalne nagłówki, DOCX jest kontenerem opartym na ZIP-ie, a HTML/XML wykrywa się po znacznikach albo elemencie głównym. W tych fixture’ach kłamliwe rozszerzenie nie wygrało.

Potem przychodzi rodzina tekstowa. Markdown był rozpoznawany jako text/markdown tylko wtedy, gdy rozszerzenie .md było obecne i czytelne. Zmień je, usuń rozszerzenie albo wyślij plik jako stream, a w tym teście degradacja prowadziła do text/plain. CSV zachowywał się tak samo na tej celowo małej siatce: text/csv pochodziło wyłącznie z globu .csv. Licząc unikalne warunki, Markdown i CSV rozpoznawały swój konkretny typ tylko w jednym z czterech przypadków; zwykły tekst i tak był text/plain, więc nie było z czego „spadać”. Surowe 48 uruchomień w harnesie nadal są użyteczne jako zapis powtarzalności, ale nie jako większy mianownik.

Jedna rzecz działa tu na korzyść Tiki: kłamliwe rozszerzenie też nie wygrywa. Mój fixture Markdown przemianowany na .pdf wrócił jako text/plain, a nie application/pdf. Tika nie uwierzyła w kłamstwo; po prostu nie mogła potwierdzić prawdy. Degradacja do typu nadrzędnego jest znacznie lepszą porażką niż pewne, ale błędne stwierdzenie, a to, że text/markdown jest udokumentowanym podtypem text/plain, sprawia, że ten fallback jest zasadny, a nie arbitralny.

Jest tu jednak zastrzeżenie dotyczące CSV. Tika ma statystyczny detektor CSV, a w czasie parsowania — co potwierdził łańcuch X-TIKA:Parsed-By z TextAndCSVParser — moja mała siatka 2 kolumn × 3 wiersze rozpoznała się jako text/plain, a nie text/csv. To pojedyncza obserwacja na celowo minimalnym fixture. Większy albo cytowany CSV może jak najbardziej uruchomić detektor. Nie twierdzę, że wykrywanie CSV po treści jest zepsute; twierdzę, że na tej siatce to rozszerzenie było tym, co dawało text/csv.

Dlaczego ma to znaczenie w realnym potoku uploadów

Konkretny scenariusz to router uploadów. Załóżmy, że przyjmujesz pliki od użytkowników i kierujesz je według typu: PDF-y do parsera faktur, arkusze do importera księgowego, wszystko inne do indeksu tekstowego. Jeśli zaufasz rozszerzeniu, ktoś, kto wgra PDF nazwany notes.txt, trafi do złej gałęzi — i to jeszcze wersja łagodna; bardziej złośliwy wariant to plik poliglotyczny z przyjaznym rozszerzeniem.

W przypadku binarnych i znacznikowych fixture’ów testowanych tutaj Tika kierowała po treści nawet wtedy, gdy nazwa pliku zniknęła, co jest bardzo przydatne, gdy magazyn obiektów albo handler body HTTP zgubił tę informację. Ten wynik nie obejmuje jednak długiego ogona Tiki, plików niejednoznacznych ani poliglotów. Testowane fixture’y z rodziny tekstowej zachowywały się inaczej: gdy pipeline usuwał nazwy plików, Markdown i CSV wpadały jako text/plain, więc reguły oparte na ich konkretnych typach mediów przestawały działać. Warto więc zachować oryginalną nazwę jako metadane obok danych, zamiast liczyć, że detekcja treści ją odtworzy.

Wstrzyknięta treść przetrwała. --text spłaszczył strukturę.

Wierność to druga oś i dzieli się tu wyraźnie na dwie części. Jeden kanoniczny dokument (nagłówki, dwa akapity treści, lista punktowana, lista numerowana, akapit końcowy) wyrenderowałem do HTML, Markdowna, zwykłego tekstu, DOCX, PDF, RTF, ODT i XML, a dodatkowo dokument tabelaryczny do HTML, Markdowna, tekstu, DOCX, CSV i XML. Łącznie czternaście renderowań nośnikowych. Każdy blok ma unikalny znacznik — zztitle1, zzitem3, zztblcell_beta i tak dalej — więc „przetrwał” versus „zniknął” to dokładny test obecności podciągu, a nie ocena uznaniowa.

Pamięć znaczników wróciła jako 1.000 dla wszystkich czternastu renderowań. Żaden wstrzyknięty znacznik nie zniknął: każda oznaczona komórka tabeli, pozycja listy i nagłówek były obecne. Trzy lokalne powtórki dla każdego nośnika po rozgrzaniu zwróciły identyczny bajtowo wynik --text. Ten pomiar nic nie mówi o znakach bez znaczników, kolejności, białych znakach, normalizacji Unicode, powtarzającej się treści, linkach, nagłówkach, przypisach ani osadzonych obiektach. To test obecności bloków, nie dowód pełnej wierności dokumentu.

Płaskie wyjście tekstowe porzuca większość struktury źródła.

Oto, jak wygląda dokument HTML z tabelą po przejściu przez --text:

	Tool	Throughput

	zztblcell_alpha	120

	zztblcell_beta	95

Wiersze połączone tabulatorami. Wiersz nagłówka nie jest oznaczony jako nagłówek. Nie ma siatki, nie ma granic komórek poza tabulatorem, nie da się stwierdzić, że kiedykolwiek była to tabela <table>. Tabela z DOCX-a spłaszcza się dokładnie w ten sam sposób.

Listy są bardziej subtelne i zależą od tego, co źródło naprawdę zawierało:

Czym była kropka w źródleNośnikiCo zwraca --text
Dosłownym znakiem — te renderowania zapisały - jako zwykły tekstzwykły tekst, Markdown, RTF, ODT, PDF- zostaje, bo Tika przepuszcza znaki bez interpretacji
Prawdziwą strukturą — HTML-owe <li>, styl List Bullet w DOCXHTML, DOCXznacznik znika całkowicie i zostaje sam tekst pozycji: z wcięciem tabulatorem w HTML, zwykła, nieozdobiona linia w DOCX

Tika nigdy nie odtwarza markera, którego nie dostała jako tekst. To samo źródło, ale inne zachowanie wyjścia.

Przypadek Markdowna pokazuje to najczyściej. Podaj Tice plik .md z tabelą pipe i znaki | wracają dosłownie, co wygląda jak zachowanie struktury. Ale to nie to. Tika potraktowała to jako tekst i oddała bajty z powrotem. Nic nie zrozumiało tej tabeli.

Zatem mierzony kontrakt jest węższy: wszystkie wstrzyknięte markery przetrwały, ale --text nie zachował typowanych elementów ani siatki tabeli możliwej do odtworzenia. Nazywanie tego błędem parsera mijałoby się z celem. Płaskie wydobycie celowo unika problemu klasyfikacji elementów; jednocześnie nie jest w stanie zadowolić odbiorcy downstream, który tych typów potrzebuje. Jeśli potrzebujesz typowanych bloków albo odtworzonych tabel, --text jest tylko jednym komponentem stosu, nie całym stosem. Inne handlery Tiki mogą pokazywać więcej struktury, ale nie były częścią tego przebiegu.

Standardowe zastrzeżenie dla każdej liczby o wierności tutaj: pochodzą z kontrolowanych, syntetycznych fixture’ów na jednej maszynie, jednej wersji i jednym JDK. Pokazują, że oznaczone bloki były obecne w wyjściu. Nie dowodzą zachowania znak po znaku ani dokładności na chaotycznym, rzeczywistym korpusie.

Metadane: ujednolicone i odświeżająco niechętne do wymyślania czegokolwiek

Measured results chart: Metadata recovery by carrier

W każdym nośniku, który ma warstwę metadanych, osadziłem znane wartości autora, tytułu i daty utworzenia, a potem sprawdziłem, co wróciło.

Nośnikauthor → dc:creatortitle → dc:titlecreated → dcterms:created
HTML (<meta name=author>, <title>)nieosadzone
DOCX (właściwości podstawowe)✅ dokładnie 2021-03-15T09:30:00Z
PDF (słownik info)obecne, ale to była własna sygnatura czasowa generatora — niezaliczone
ODT (meta.xml)✅ dokładnie 2021-03-15T09:30:00Z
TXT / MD / CSV / RTF / XMLbrak warstwy metadanych

Autor i tytuł zostały odzyskane na 4 z 4 nośników posiadających metadane — i to jest część naprawdę cenna — a do tego są ujednolicone. HTML-owy <meta name="author">, właściwość podstawowa DOCX, wpis /Author w PDF i element dc:creator w ODT trafiają pod ten sam klucz dc:creator. Piszesz jednego konsumenta, nie czterech.

created jest tu szczerym wahnięciem. DOCX i ODT zwróciły dokładnie osadzony przeze mnie timestamp z 2021 roku. PDF zwrócił datę utworzenia, ale była to data nadana przez bibliotekę generatora w czasie budowania, a nie wartość, którą chciałem osadzić — więc zaznaczam ją jako obecną, nie odzyskaną. A formaty bez warstwy metadanych nie pokazały niczego, co jest poprawną odpowiedzią. Tika nie zgaduje autora na podstawie treści.

Celowe psucie i wynikający z tego trik triage

Cztery wrogie wejścia. Plik o rozmiarze zero bajtów. Poprawny nagłówek PDF z obciętym ciałem. Ucięty ZIP z DOCX. I plik UTF-8 z wielobajtowymi znakami, bez BOM i bez deklaracji kodowania. To lokalne kształty fixture’ów, a nie progi dla Tiki.

Bazowy harness, wygenerowane fixture’y, surowy JSON, checksum JAR-a i manifest środowiska nie są podlinkowane w tym szkicu. Zewnętrzny czytelnik nie może więc na razie samodzielnie odtworzyć dokładnych mianowników. Traktuj więc tabele jako opublikowane obserwacje; do publikacji trzeba dołączyć stabilny pakiet, zanim te liczby posłużą za dowód dla osób trzecich.

Wejście--text / --jsonCo rzuciło--detect
Plik 0-bajtowyexit 1, puste stdoutZeroByteFileException: InputStream must have > 0 bytesexit 0 → text/plain z nazwą pliku, application/octet-stream ze streamu
Ucięty PDFexit 1, puste stdoutTikaException: TIKA-198: Illegal IOException from PDFParserexit 0 → application/pdf
Ucięty DOCXexit 1, puste stdoutPOI FATAL: "XML document structures must start and end within the same entity"exit 0 → typ OOXML
UTF-8, bez BOM, bez deklaracjiexit 0nicexit 0 → text/plain, charset UTF-8

Ekstrakcja pada głośno i te porażki mają podobny zewnętrzny kształt. Plik 0-bajtowy, ucięty PDF i ucięty DOCX każdy wygenerowały wyjątek, exit 1 i puste stdout. CLI nie udaje ładnego pustego wyniku. To są przypadki bezpieczne procesowo — bez zawieszenia, bez segfaulta — ale wywołujący musi sprawdzić kod wyjścia i stderr, a nie tylko patrzeć, czy string jest pusty.

Detekcja jest odseparowana od parsowania. W obu uciętych binarkach --detect zwrócił exit 0 z oczekiwanym typem wynikającym z nienaruszonej początkowej treści; parser dopiero potem wywalił się na uszkodzonym ciele. Potok może więc użyć detekcji jako osobnego sygnału triage przed albo po nieudanym parsowaniu. Czy detect-first jest dobrym domyślnym rozwiązaniem, zależy od trybu wdrożenia: tego nie benchmarkowałem względem parse-only, a dwie świeże JVM CLI mogą być przy dużej skali złym kompromisem.

Wykrywanie kodowania działa. Plik UTF-8 bez BOM i bez deklaracji został zdekodowany jako UTF-8, a 日本語テスト przeszło bez uszkodzeń. Małe zastrzeżenie dla osób czytających słowniki metadanych: moje czysto ASCII-owe fixture’y raportują charset=ISO-8859-1, co na bajtach ASCII jest nieodróżnialne od UTF-8. To nie jest pomyłka, tylko remis.

Tika obok unstructured: te same typy plików, różne zadania

Oba narzędzia testowałem w tej samej sesji badawczej, ale to jest taksonomia kontraktów wyjścia, nie symetryczny benchmark. Oceniano je pod kątem różnych rezultatów.

Powiązana recenzja: Recenzja Unstructured.

Apache Tikaunstructured
Co mierzyłemwierność treści: czy coś zostało utracone?wierność klasyfikacji elementów: czy każdy blok dostał właściwy typ?
Wynikwszystkie wstrzyknięte markery obecne we wszystkich czternastu renderowaniachw osobnym teście klasyfikacji zwykła tabela tekstowa dała recall Table równy 0.000, a jeden nagłówek zawierający czasownik został sklasyfikowany jako tekst narracyjny
Zwracane elementy typowanebrak — żadna struktura nie wracaTitle, NarrativeText, ListItem, Table — dokładnie to, czego Tika nie robi
OCRzablokowane na moim hoście, brak tesseractzablokowane na moim hoście, brak tesseract

Płaskie wyjście zachowujące markery kontra typowane elementy z zaobserwowanymi błędami klasyfikacji. Wybór zależy od tego, czego potrzebuje konsument downstream. Jeśli to indeks wyszukiwania albo okno kontekstu LLM, płaski tekst może wystarczyć. Jeśli opiera się na typie elementu, ścieżka --text Tiki tego nie zapewni.

Żadne z nas nie ma liczb dla dokumentów skanowanych.

Plusy i minusy

Plusy

  • Detekcja typu treści ignorowała kłamliwe nazwy plików w 20/20 unikalnych warunkach dla pięciu formatów wykrywanych po treści; zduplikowane uruchomienia streamu potwierdziły to samo.
  • Każdy wstrzyknięty marker przetrwał we wszystkich 14 renderowaniach, w tym oznaczone komórki tabel i pozycje list.
  • Powtarzalne w trzech lokalnych rerunach: każdy nośnik zwracał identyczny bajtowo tekst w tym środowisku.
  • Metadane ujednolicone między formatami — dc:creator / dc:title / dcterms:created niezależnie od źródła, odzyskane na 4/4 nośnikach z warstwą metadanych.
  • Naprawdę bez zależności zewnętrznych dla testowanych formatów: warstwa tekstowa PDF, DOCX, ODT, RTF, HTML parsują się z jednego JAR-a bez dodatkowych binarek.
  • Działa bez problemu na OpenJDK 26 — bez ograniczenia tylko do LTS.
  • Detekcja pozostaje poprawna (exit 0) na uciętych binarkach, dając wiarygodny sygnał triage, gdy parsowanie się wywala.
  • Apache-2.0, dojrzały, aktywnie rozwijany.

Minusy

  • Tożsamość Markdowna i CSV zależy wyłącznie od rozszerzenia pliku; 10 z 18 komórek bez sygnatury spadło do text/plain, gdy nazwa pliku zniknęła albo była błędna.
  • --text nie zwraca typów elementów; siatki tabel spłaszczają się do linii połączonych tabulatorami, a strukturalne markery list znikają.
  • Ekstrakcja rzuca nieobsłużonym wyjątkiem na pustych i uszkodzonych wejściach; oba przypadki wyglądają identycznie z poziomu samego wywołania ekstrakcji.
  • JAR ma 67 MB, a w trybie CLI każde wywołanie uruchamia nową JVM, co oznacza zimny start.
  • OCR i skanowane PDF-y nie były tu w ogóle testowane — tesseract i poppler były nieobecne, więc nie stawiam żadnych twierdzeń o tej ścieżce.
  • Wszystkie liczby w tym tekście pochodzą z syntetycznej prawdy gruntu na jednej maszynie, jednej wersji. Dokładność na realnym korpusie, pliki zaszyfrowane, dokumenty osadzone/rekurencyjne i wydajność przy skali nie były mierzone.

Dla kogo to jest, a kto powinien odpuścić

Tika pasuje wtedy, gdy Twoim wejściem są pliki, które już masz, a wyjściem ma być tekst i metadane, które maszyna może zindeksować. Indeksowanie wyszukiwania, e-discovery, przetwarzanie archiwów, zasilanie korpusu dla LLM, budowanie warstwy walidacji typu zawartości w potoku uploadów. Jest użyteczna jako pierwszy etap triage i normalizacji przed czymś inteligentniejszym: wykryj testowane typy, wyciągnij płaski tekst i przekaż dalej z wyraźnymi kontrolami tego, czego potok nie może stracić.

Pomiń ją — a właściwie: nie kończ na --text — jeśli potrzebujesz typowanych elementów, odtworzonych tabel albo układu dokumentu. Pomiń ją też, jeśli Twoje dokumenty są skanami, przynajmniej dopóki nie zainstalujesz tesseract i sam nie wykonasz własnych pomiarów, bo ja ich nie mam. Przy pracy na dużą skalę warto benchmarkować bibliotekę albo tryb serwerowy względem CLI na reprezentatywnych dokumentach. Start procesu był widoczny w tym małoplikowym harnesie, ale przepustowości i kosztu zasobów nie mierzyłem.

Rzecz, która najczęściej łapie ludzi: jeśli Twoja warstwa storage usuwa nazwy plików, a obsługujesz Markdown albo CSV, nie zakładaj, że Tika odróżni je od zwykłego tekstu. Zachowaj oryginalną nazwę.

Alternatywy i miejsce Thunderbit

Najpierw uczciwe ujęcie, bo prawdziwe porównanie dotyczy tu wejść, a nie jakości. Tika to darmowy, zgodny z Apache-2.0, hostowany samodzielnie toolkit do parsowania plików. Plików, które masz na dysku albo w bucketcie. Nie pobiera stron, nie uruchamia JavaScriptu, nie walczy z anty-botem i nie udaje, że to robi.

To właśnie ta granica, w której do architektury może wejść zarządzana usługa ekstrakcji webowej, w tym nasz własny Thunderbit: pobiera żywe strony, podczas gdy Tika parsuje pliki już będące w Twoim posiadaniu. Ten artykuł nie benchmarkował tych usług względem Tiki i nie są one zamiennikami dla tego samego wejścia.

Prosty podział: Tika do dokumentów, które już masz, zarządzane API ekstrakcyjne do stron, które musisz dopiero pobrać. Wiele potoków używa obu — crawl i ekstrakcja po stronie webowej, Tika dla załączników PDF i DOCX, które wracają.

Jeśli porównujesz szerszy ekosystem open-source, opisałem już pełne porównanie open-source scraperów, przegląd najbardziej użytecznych projektów scrapujących na GitHubie, praktyczną recenzję Crawl4AI opisującą podejście Markdown oparte na przeglądarce oraz szersze zestawienie narzędzi do scrapingu. Dla ścieżki no-code jest też instrukcja, jak scrapować stronę z użyciem AI.

Wypróbuj Thunderbit do ekstrakcji danych z sieci

Werdykt

Czy warto używać Apache Tika? Tak, jeśli Twoim zadaniem jest zamiana heterogenicznych plików w płaski tekst i ujednolicone metadane, oraz jeśli walidujesz pola albo znaczniki, których Twój własny potok nie może sobie pozwolić stracić.

Detektor był najmocniejszą częścią tego przebiegu. Zwrócił oczekiwany typ w 20 z 20 unikalnych warunków dla pięciu formatów wykrywanych po treści, w tym dla strumieni bez nazwy pliku. Każdy wstrzyknięty marker przetrwał we wszystkich czternastu renderowaniach, a wynik powtarzał się bajt w bajt w trzech lokalnych rerunach. Użyteczny dowód. Nadal syntetyczny dowód. Zrobienie tego z jednego JAR-a na tym JDK, bez zewnętrznych binarek dla testowanych ścieżek bez OCR, sprawiło, że wdrożenie było przyjemnie nudne.

Trzeba jednak dobrać narzędzie we właściwy sposób. Każda tabela, którą do niej wrzucisz, wróci jako linie połączone tabulatorami. Każdy strukturalny marker listy zniknie. Markdown i CSV tracą tożsamość w chwili, gdy nazwa pliku znika. Puste i uszkodzone pliki rzucają taki sam typ błędu, a osobne wywołanie detect będzie potrzebne, by je odróżnić. A o OCR, czyli o pytaniu, które dla wielu użytkowników Tiki jest najważniejsze, nie mam nic do zaoferowania: nie mogłem tego uruchomić i nie będę zgadywał.

W tych granicach Tika wykonuje mało efektowną, ale zaskakująco niezawodną robotę. Czyta bajty, a nie etykietę na pudełku. Tylko nie pytaj jej, w jakim kształcie te bajty były.

Wypróbuj Thunderbit do ekstrakcji danych z sieci Get Started Free

FAQ

Czy Apache Tika poprawnie wykrywa typ pliku, jeśli rozszerzenie jest błędne? W przypadku pięciu testowanych tutaj formatów wykrywanych po treści — tak. PDF, DOCX, RTF, HTML i XML zostały rozpoznane jako oczekiwany typ MIME we wszystkich 20 unikalnych warunkach logicznych (30 surowych uruchomień z powtórzonymi streamami), także przy mylących rozszerzeniach, braku rozszerzenia i strumieniach bez nazwy pliku. PDF nazwany .txt nadal był wykrywany jako application/pdf. Markdown i mały fixture CSV zależały od informacji o nazwie pliku i degradują do text/plain, gdy jej brakowało albo była błędna.

Czy Tika zachowuje tabele i strukturę dokumentu? Nie w testowanym tutaj trybie --text. Siatki tabel wracały jako linie połączone tabulatorami, bez semantyki komórek i nagłówków, a strukturalne markery list (HTML-owe <li>, styl List Bullet w DOCX) znikały. Każdy wstrzyknięty marker przetrwał we wszystkich 14 renderowaniach nośnikowych, ale to nie dowodzi pełnej wierności treści, a --text nie zwraca typów elementów. Jeśli potrzebujesz typowanych elementów albo odtworzonych tabel, przetestuj inny handler wyjścia Tiki albo użyj obok niej innego narzędzia.

Czy Apache Tika potrafi robić OCR na skanowanych PDF-ach? Tika wspiera OCR przez Tesseract, ale nie testowałem tego i żaden z tych wyników nie jest twierdzeniem na ten temat. Tesseract i poppler były nieobecne na moim hoście testowym, więc każda ścieżka OCR i skanowanych obrazów była zablokowana zanim się uruchomiła. W tym teście nie ma żadnych liczb dla OCR. Jeśli OCR jest Twoim przypadkiem użycia, zainstaluj tesseract i wykonaj własny benchmark — traktuj tę część Tiki jako tutaj niezweryfikowaną.

Co Tika robi z pustymi lub uszkodzonymi plikami? Nie milczy, tylko zgłasza błąd. Plik o rozmiarze 0 bajtów rzuca ZeroByteFileException; ucięty PDF rzuca TikaException z PDFParser; ucięty DOCX rzuca błąd XML z POI. Wszystkie trzy kończą się code 1 i pustym stdout, więc z perspektywy samego wywołania ekstrakcji puste i uszkodzone są nie do odróżnienia. Detekcja pozostaje jednak solidna — --detect zwracał exit 0 z prawidłowym typem w obu uciętych binarkach, więc nadaje się jako wiarygodny krok triage, zanim poświęcisz czas na parsowanie.

Czego testy Tiki nie objęły? Czterech rzeczy, wprost. OCR i obrazy skanów (zablokowane, nie testowane). Dokładności na realnym korpusie — wszystkie wyniki pochodzą z kontrolowanych, syntetycznych fixture’ów z wstrzykniętymi znacznikami, więc mierzą wierność względem znanych etykiet, a nie trafność na nieuporządkowanych, prawdziwych dokumentach. Kosztu zasobów, przepustowości i maksymalnego zużycia pamięci, których nie mierzyłem. I długiego ogona roszczenia o „tysiącu typów plików”: testowałem dziewięć reprezentatywnych formatów bez zewnętrznych zależności, a nie cały katalog. Wszystko tutaj dotyczy Tika 3.3.2 na OpenJDK 26.0.1, macOS arm64, na jednej maszynie.

Ke
Ke
CTO w Thunderbit | Starszy data scientist i ekspert ML Dzięki prawie dziesięciu latom doświadczenia w uczeniu maszynowym i data science, Ke Shen jest absolwentem Columbia University i byłym starszym data scientistą w Walmart Labs. Dysponując dogłębną, uznaną przez branżowych ekspertów wiedzą w zakresie Python, R, Java i statystyki, dzieli się sprawdzonymi w boju spostrzeżeniami na temat wdrażania złożonych algorytmów AI — od teorii po architekturę gotową do produkcji.
Spis treści
Thunderbit · Agent AI do danych z sieci

Wyodrębnij dane z dowolnej strony w 1 klik

Zaufało nam ponad 250 000 użytkowników
dostępny darmowy plan
Od strony WWW do arkusza
Opisz, czego potrzebujesz — agent AI Thunderbit to zeskrapuje i wyeksportuje do Excel, Google Sheets, Airtable lub Notion. Start jest darmowy.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week