Apache Tika は、Apache Software Foundation が提供する文書解析ツールキットです。ほぼあらゆる形式のファイルを渡すと、プレーンテキストと正規化されたメタデータ辞書を返してくれます。 project README では 1,000 種類を超えるファイル形式に対応すると案内されており、その実現のために Tika は専門ライブラリを内部に同梱しています。PDF には PDFBox、Office 文書には Apache POI、HTML には jsoup、ODT には ODF reader を使い、解析時に追加で何かを取りに行く必要がない、ひとつの fat jar として配布されます。データパイプラインの中では地味な最初の関門で、検索インデックス、eDiscovery のレビュー対象、LLM コーパスの前段に置かれ、バラバラなファイル群を均質な形に整えます。要するに仕事は 2 つです。バイト列が「何者か」を判定し、それから中身のテキストとメタデータを取り出すことです。
ここしばらく触ったツールの中で、これほど手のかからないものはありませんでした。jar が 1 つあって、java -jar tika-app-3.3.2.jar --text file.pdf を実行するだけ。設定ファイルも、モデルの重みも、インストール後の追加作業も不要で、同じホスト上の他の Java ツールがその日のうちに完全停止していた最先端 JDK でも、何事もなかったかのように動きました。ただし、私はカタログ上の対応形式数を検証したかったわけではありません。検証したかったのはもっと狭い問いです。入力が嘘をついたとき、Tika は実際にどう振る舞うのか。そこで、各コンテンツブロックに一意のマーカートークンを埋め込んだ制御済みのフィクスチャセットを作り、同じ論理文書を 9 種類のキャリア形式へ書き出し、そのうえで拡張子の誤り、拡張子なし、ファイル名なし、0 バイトファイル、途中までしか書かれていないバイナリをぶつけました。
面白い挙動が出るのは検出の部分です。PDF を .txt にリネームして Tika に尋ねると、返答は application/pdf でした。さらにファイル名を完全に消して、生のバイト列を stdin で流し込んでも、同じ答えが返ってきました。私のセットに含めた 5 つのコンテンツ検出可能形式では、これは 20 個のユニークな論理条件 すべてで成り立ちました。各形式につき、ファイル名ありの 3 条件に加え、ファイル名なしストリーム 1 条件です。ハーネスは同じストリームケースを 3 回、異なるラベルで実行し、raw 実行回数としては 30 回成功していますが、その重複は独立した証拠ではありません。PDF と RTF は認識可能なバイト列を持ち、DOCX はコンテナ構造そのもので見分けられ、HTML と XML はマークアップやルート要素から判定できます。仕組みは違っても、このフィクスチャセットでは同じ実用的な結果になりました。拡張子は内容を上書きしませんでした。そしてテキスト系では、Markdown はファイル名が間違っているか消えてしまうと、その瞬間に text/plain に落ちます。ここでは識別の根拠は .md だけでした。
この先に出てくる数値には、前提が 2 つあります。私は Apache Tika 3.3.2 をテストしました。2026 年 7 月 27 日時点で、これはまだ最新の安定版でした。4.0.0 系は Maven Central 上では alpha と beta のビルドしか存在していません。2026 年 7 月 27 日時点でプロジェクトの GitHub スター数はおよそ 3.9k、ライセンスは Apache-2.0 でした。商用利用のしやすさという意味では、かなり気楽な部類です。さらに、OCR は一切テストしていません。 スキャンページも、画像のみの PDF も 1 つも試していません。実行したマシンには Tesseract も poppler も入っていなかったため、OCR の経路は始まる前にすべて塞がれていました。OCR の数値はここにはありません。単純に、OCR の数値がないからです。
箱の中の宣伝文句を読むのをやめたとき、Tika は何者か
よくある誤解は、Apache Tika を文書変換ツールだと思うことです。DOCX を渡せば、見出しや表を保ったきれいな Markdown が返ってくる、というイメージです。しかし実際はそうではありません。その点を早めに理解したほうが、このツールの良さがはっきり見えます。
今回試した経路は、重要な段階が 3 つあります。コンテンツタイプ検出器、バイト列を適切なパーサーに振り分ける ディスパッチャ、そして CLI の --text 出力ハンドラです。これはフラットなテキストを出しつつ、別途取り出せるメタデータも返します。この出力契約には Title オブジェクトも、ListItem も、再構成された表のグリッドもありません。Tika には XHTML/SAX 指向の別ハンドラや API もありますが、それらは今回試していません。したがって、以下の構造に関する結論はすべて tika-app --text に対するものであり、ツールキットに構造化イベントストリームがどこにもないと言っているわけではありません。
これは制約のように聞こえますし、ある意味ではその通りです。ただし裏を返せば、Tika は誤分類する材料を持たないということでもあります。むしろそれこそが、このツールが雑多な競合製品と逆方向にしている取引です。
検出そのものは、文書化された順序で動きます。まずシグネチャバイト、次に XML のルート要素の確認、次にファイル名の glob、そして最後にユーザーが明示した型です(Tika 自身の検出ドキュメント に整理されています)。型が確定して初めて、ディスパッチャは一致する同梱パーサーにバイト列を渡します。PDFBox、POI、jsoup、テキスト系の TextAndCSVParser などです。
この「検出してから解析する」分離は、内部事情の小ネタではありません。壊れすぎて解析できないファイルでも正しく型判定できる、ということです。実務で壊れ始めたときに Tika が一番役に立つのは、この性質です。
セットアップ: jar 1 つ、コマンド 1 本、気難しくない JVM
インストールはダウンロードだけです。Maven Central から取得できる tika-app-3.3.2.jar は約 67 MB で、すべてのパーサーを束ねた fat jar です。あとは java -jar tika-app-3.3.2.jar --text file.pdf を打つだけ。設定ファイルも、モデルの重みも、インストール後の追加処理も、brew install の連鎖も必要ありません。
JDK の話は少し意外でした。私は全体を OpenJDK 26.0.1、つまり非 LTS の最先端版で実行しましたが、--version、--text、--metadata、--detect はすべて exit 0 で返り、互換性に関する文句もありませんでした。ここをわざわざ名前付きで書くのは理由があります。同じホストで同じ日に Apache Nutch も試したのですが、そちらの crawl 循環は JDK 26 ではまったく動かず、新しい JDK で SecurityManager が削除された影響で、21 以下の LTS が必要でした。Tika は気にしませんでした。JVM ツールの特定の厄介さを避けてきた人にとって、Tika はその壁に当たりにくい部類です。
セットアップ面での正直な注意点も 2 つあります。CLI は起動のたびに新しい JVM を立ち上げるので、コールドスタートは現実にあります。私のハーネスで 131 回実行したところ、ほとんどが JVM のウォームアップで、全体で約 1 分かかりました。大量処理するなら、jar をシェルループで回すより、ライブラリかサーバーモードを使うべきです。そして「依存なし」には明確な境界があります。PDF のテキスト層抽出には外部依存が不要ですが、OCR には tesseract と poppler が必要です。 テキスト層だけの PDF、DOCX、ODT、RTF、HTML、XML、TXT、Markdown、CSV は、どちらも入っていないホストで問題なく解析できました。スキャン文書はそうはいかず、私はそのふりもしませんでした。
この対比は、同日に試した兄弟ライブラリ unstructured と比べるとさらにはっきりします。unstructured の電子 PDF 経路は、PDF モジュールを import した時点で推論スタック(torch など)を読み込むため、戦略の分岐前に完全に塞がれていました。つまり、最速戦略であっても、その依存関係がないと import すらできません。Tika は同じ PDF のテキスト層を、ただの java -jar で解析しました。
嘘の拡張子テスト: ファイル名を無視する MIME タイプ検出

8 形式それぞれについて、正しい拡張子、わざと間違えた拡張子、拡張子なしのいずれか、さらに stdin 上のファイル名なしバイトストリームを用意しました。これは 32 個のユニークな論理条件 です。元のハーネスは、同じストリームバイトをファイル名ラベルごとに 1 回ずつ実行しており、raw 実行回数は 48 回でした。ただし stdin にはファイル名がないため、その 3 行のストリーム条件は 1 つにまとめられます。
| フィクスチャ | 本来の型 | リネーム先 | 正しい拡張子 | 嘘の拡張子 | 拡張子なし | raw ストリーム, ファイル名なし |
|---|---|---|---|---|---|---|
application/pdf | .txt | ✅ | ✅ | ✅ | ✅ | |
| DOCX | OOXML wordprocessingml | .jpg | ✅ | ✅ | ✅ | ✅ |
| RTF | application/rtf | .html | ✅ | ✅ | ✅ | ✅ |
| HTML | text/html | .csv | ✅ | ✅ | ✅ | ✅ |
| XML | application/xml | .txt | ✅ | ✅ | ✅ | ✅ |
| プレーンテキスト | text/plain | .pdf | ✅ | ✅ | ✅ | ✅ |
| Markdown | text/markdown | .pdf | ✅ | ❌ text/plain | ❌ text/plain | ❌ text/plain |
| CSV | text/csv | .txt | ✅ | ❌ text/plain | ❌ text/plain | ❌ text/plain |
(ストリーム列は 3 つの拡張子条件をまとめたものです。ファイル名がないので、glob が読む対象がありません。)
コンテンツ検出可能な 5 形式、つまり PDF、DOCX、RTF、HTML、XML は、20 個のユニークな条件すべてで本来の型に到達しました(重複したストリーム実行を含めると 30/30 の raw 実行でも成功)。report.txt と名付けた PDF は、やはり PDF のままでした。photo.jpg と名付けた DOCX も、やはり DOCX のままでした。どちらもファイル名を必要としませんでした。とはいえ、これは 5 形式すべてが固定のバイトシグネチャで判定される、という意味ではありません。PDF と RTF には認識可能なヘッダがあり、DOCX は ZIP ベースのコンテナで、HTML と XML はマークアップやルート要素から検出されます。このフィクスチャでは、嘘の拡張子が勝ちませんでした。
次にテキスト系です。Markdown が text/markdown として判定されたのは、.md 拡張子があり、読み取れた場合だけでした。リネームする、拡張子を外す、ストリームで送る、といういずれでも、このテストでは text/plain に落ちました。CSV も同じで、この小さなグリッドでは .csv の glob からしか text/csv になりませんでした。ユニーク条件で数えると、Markdown も CSV も 4 条件中 1 条件でだけ個別型として判定されました。プレーンテキストは最初から text/plain なので、そこから「落ちる」ものはありません。raw の 48 回実行は再現性の記録としては有用ですが、分母を大きくするものではありません。
ここで Tika に有利な点が 1 つあります。嘘の拡張子も勝てません。 Markdown のフィクスチャを .pdf にリネームしても、返ってきたのは application/pdf ではなく text/plain でした。Tika は嘘を信じたのではなく、真実を確認できなかっただけです。親型へ降格する失敗は、誤った型を自信満々に断定するよりずっと良い失敗ですし、text/markdown が text/plain の文書化されたサブタイプであることを考えると、このフォールバックは恣意的ではなく理にかなっています。
CSV にはひとつ注記があります。Tika には統計ベースの CSV 検出器があり、解析時には X-TIKA:Parsed-By の連鎖に TextAndCSVParser が現れることを確認しましたが、私の 2 列×3 行という小さなグリッドは text/csv ではなく text/plain に解釈されました。これは意図的に最小化したフィクスチャでの単一観測です。より大きい CSV や引用符付き CSV なら、検出器が働く可能性は十分あります。私は CSV のコンテンツ検出が壊れていると主張しているのではなく、このグリッドでは text/csv を生んだのは拡張子だった、ということを述べています。
これは実運用のアップロード経路でなぜ重要か
具体的な場面はアップロードのルーティングです。たとえばユーザーアップロードを受け付け、種類ごとに振り分けるとします。PDF は請求書パーサーへ、スプレッドシートは台帳インポータへ、それ以外はテキスト索引へ、という具合です。もし拡張子を信用してしまうと、notes.txt という名前の PDF は誤った分岐に入ります。これはまだ穏当なケースで、本当に厄介なのは、見た目だけ無害な拡張子を持つポリグロットファイルです。
今回のバイナリとマークアップのフィクスチャでは、Tika はファイル名が消えても内容でルーティングしました。これは、blob ストアや HTTP ボディハンドラがファイル名を落としてしまう場面で役立ちます。ただし、この結果は Tika の長い尾、曖昧なファイル、ポリグロットまではカバーしません。テストしたテキスト系フィクスチャは違う振る舞いを見せ、パイプラインがファイル名を削除すると Markdown と CSV は text/plain として届いたため、それらの個別メディアタイプに紐づくルールは発火しなくなりました。内容検出にファイル名を再構成させるのではなく、元のファイル名をサイドカーのメタデータとして保持してください。
埋め込んだ内容は生き残った。--text は構造を平坦化した。
忠実度は第 2 の軸で、きれいに 2 つに分かれます。私は 1 つの正規文書(見出し、本文 2 段落、箇条書き、番号付きリスト、締めの段落)を HTML、Markdown、プレーンテキスト、DOCX、PDF、RTF、ODT、XML に書き出し、さらに表ドキュメントを HTML、Markdown、text、DOCX、CSV、XML に書き出しました。合計 14 種類のキャリア表現です。すべてのブロックには zztitle1、zzitem3、zztblcell_beta のような一意のトークンが埋め込まれているため、「残ったか落ちたか」は曖昧な評価ではなく、厳密な部分文字列チェックで判定できます。
マーカー・トークンの再現率は 14 種類すべてで 1.000 でした。 埋め込んだトークンが 1 つも消えていません。タグ付きの表セルも、リスト項目も、見出しもすべて存在しました。ウォームアップ後に各キャリアを 3 回ずつ繰り返したところ、--text の出力はバイト単位で同一でした。このオラクルは、未タグの文字、順序、空白、Unicode 正規化、重複コンテンツ、リンク、ヘッダ、脚注、埋め込みオブジェクトについては何も教えてくれません。これはブロックの存在確認であって、文書全体の完全な忠実度を証明するものではありません。
ただし、フラットテキスト出力は元の構造の大半を手放します。
これは HTML の表ドキュメントを --text で出した結果です。
Tool Throughput
zztblcell_alpha 120
zztblcell_beta 95
タブ区切りの行です。ヘッダ行はヘッダとしては示されません。グリッドはなく、セル境界もタブ以外にはなく、そもそも <table> だったことを知る手段がありません。DOCX の表も同じように平坦化されます。
リストは少し微妙で、元データに何が入っていたかによって分かれます。
| ソース上での箇条書きの正体 | キャリア | --text が返すもの |
|---|---|---|
文字そのもの — これらの表現はすべて - を実際の文字として書き込んだもの | プレーンテキスト、Markdown、RTF、ODT、PDF | Tika は文字をそのまま通すので、- は残る |
本物の構造 — HTML の <li>、DOCX の List Bullet スタイル | HTML、DOCX | マーカーは完全に消え、項目テキストだけが残る。HTML ではタブインデント、DOCX では飾りのない普通の行になる |
Tika は、テキストとして受け取っていないマーカーを再描画しません。同じ内容でも、見た目の出力は変わります。
Markdown のケースはこの点をきれいに示します。パイプ表を含む .md ファイルを Tika に渡すと、パイプはそのまま戻ってきます。見た目は構造保持のように見えますが、実際は違います。Tika はそれをテキストとして解析し、バイト列をそのまま返しただけです。その表を「理解」したものは何もありません。
したがって、測定できる契約はもっと狭いものです。埋め込んだマーカーはすべて残った一方で、--text は型付き要素や再構成可能な表グリッドを保持しませんでした。 これをパーサーの欠陥と呼ぶのは要点を外しています。フラット抽出は意図的に要素分類の問題を避けていますが、下流の消費者がその要素型を必要とする場合には対応できません。型付きブロックや再構成された表が必要なら、--text はスタックの一部であって、スタック全体ではありません。Tika の別ハンドラならもっと構造が出るかもしれませんが、今回はそこまでは含めていません。
ここでの忠実度の数値には、毎回同じ注意書きが付きます。1 台のマシン、1 つのバージョン、制御された合成フィクスチャで得たものです。タグ付きブロックが出力に存在したことは示していますが、雑然とした実世界のコーパスで文字単位の完全保存や正確さを証明するものではありません。
メタデータ: 正規化され、しかもむやみにでっち上げない

メタデータ層を持つ各キャリアに、既知の author、title、creation-date を埋め込み、それがどう返ってくるかを確認しました。
| キャリア | author → dc:creator | title → dc:title | created → dcterms:created |
|---|---|---|---|
HTML (<meta name=author>, <title>) | ✅ | ✅ | 埋め込みなし |
| DOCX (core properties) | ✅ | ✅ | ✅ 正確に 2021-03-15T09:30:00Z |
| PDF (info dict) | ✅ | ✅ | あり。ただし生成ライブラリ自身のタイムスタンプで、採点対象外 |
ODT (meta.xml) | ✅ | ✅ | ✅ 正確に 2021-03-15T09:30:00Z |
| TXT / MD / CSV / RTF / XML | メタデータ層なし | — | — |
author と title は、メタデータを持つ 4/4 のキャリアすべてで回収できました。そして重要なのは、正規化されていることです。HTML の <meta name="author">、DOCX の core property、PDF の /Author エントリ、ODT の dc:creator 要素は、すべて同じ dc:creator キーとして返ってきます。つまり、4 種類の消費者を書かずに、1 つ書けばよいわけです。
created は正直に揺れました。DOCX と ODT は、埋め込んだ 2021 年のタイムスタンプをそのまま返しました。PDF には creation date がありましたが、それは私が埋め込もうとした値ではなく、生成ライブラリがビルド時に付けた日付でした。そのため、ここでは「回収できた」ではなく「存在した」として扱います。そもそもメタデータ層を持たない形式は何も返さず、それが正しい答えです。Tika はテキスト本文から著者を推測したりしません。
わざと壊してみて、そこから見える切り分けのコツ
4 種類の敵対的入力を用意しました。0 バイトファイル。先頭は有効だが途中で切れた PDF。途中で切れた DOCX の ZIP。BOM も encoding 宣言もない、マルチバイト文字を含む UTF-8 ファイルです。これらは Tika のしきい値ではなく、ローカルなフィクスチャ形状です。
基礎となるハーネス、生成済みフィクスチャ、raw JSON、jar の checksum、環境マニフェストはここでは公開リンクしていないため、外部の読者が分母を完全に再現することはできません。表は第三者が検証可能な証拠というより、報告された観測結果として扱ってください。
| 入力 | --text / --json | 投げた例外 | --detect |
|---|---|---|---|
| 0 バイトファイル | exit 1, stdout 空 | ZeroByteFileException: InputStream must have > 0 bytes | exit 0 → ファイル名ありなら text/plain、stream なら application/octet-stream |
| 途中で切れた PDF | exit 1, stdout 空 | TikaException: TIKA-198: Illegal IOException from PDFParser | exit 0 → application/pdf |
| 途中で切れた DOCX | exit 1, stdout 空 | POI FATAL: "XML document structures must start and end within the same entity" | exit 0 → OOXML type |
| UTF-8、BOM なし、宣言なし | exit 0 | なし | exit 0 → text/plain, charset UTF-8 |
抽出は派手に失敗し、しかも失敗の外形は同じです。 0 バイトファイル、途中で切れた PDF、途中で切れた DOCX は、それぞれ例外、exit 1、stdout 空を返しました。CLI は失敗を静かに空結果へ丸め込みません。このケースでは安全に止まりますが、ハングもしないし segfault もしません。ただし呼び出し側は、空文字列だけを見るのではなく、終了ステータスと stderr を必ず確認する必要があります。
検出は解析と切り離されています。 どちらの途中切れバイナリでも、--detect は intact な先頭部分から期待される型を返して exit 0 でした。その後、パーサーが壊れた本文で失敗します。したがってパイプラインは、解析失敗の前後どちらでも、検出を別のトリアージ信号として使えます。detect-first をデフォルトにするのが良いかは配置次第です。今回のテストでは detect-first と parse-only のベンチマークはしていませんし、CLI を毎回新規起動するのは大量処理では不利かもしれません。
文字コード検出は機能します。 BOM なし・宣言なしの UTF-8 ファイルは UTF-8 としてデコードされ、日本語テスト はそのまま通りました。メタデータ辞書を読む人向けの小さな注記として、純 ASCII のフィクスチャは charset=ISO-8859-1 と報告されますが、ASCII バイトでは UTF-8 と区別できません。これは外れではなく引き分けです。
Tika と unstructured を並べると: 同じファイル型、違う役割
どちらも同じ研究セッションで試しましたが、これは出力契約の分類であって、対称的なベンチマークではありません。ツールごとに評価した結果が違います。
関連レビュー: Unstructured review。
| Apache Tika | unstructured | |
|---|---|---|
| 測定対象 | 内容の忠実度: 何か落ちたか | 要素分類の忠実度: 各ブロックの型が正しいか |
| 結果 | 14 種類すべてのキャリア表現で埋め込んだマーカーがすべて残った | 別の分類テストでは、プレーンテキスト表の Table 再現率は 0.000、動詞を含む見出し 1 つが narrative text と判定された |
| 返してくる型付き要素 | なし — 構造は返らない | Title、NarrativeText、ListItem、Table — Tika がまさに返さないもの |
| OCR | このホストでは tesseract がなく実行不可 | このホストでは tesseract がなく実行不可 |
フラットでマーカーを保持する出力と、分類誤りが観測された型付き要素。下流が何を必要とするかで選べばよいのです。検索インデックスや LLM のコンテキスト窓が相手なら、フラットテキストで足りることもあります。要素型に依存するなら、Tika の --text 経路はその契約を満たせません。
どちらもスキャン文書の数値はありません。
長所と短所
長所
- 5 つのコンテンツ検出可能フィクスチャに対して、嘘のファイル名を無視した型検出が 20/20 のユニーク条件で成功。重複ストリーム実行も一致。
- 14 種類のキャリア表現すべてで埋め込んだマーカーが残り、タグ付きの表セルやリスト項目も欠けなかった。
- ローカルで 3 回再実行しても結果が再現し、この環境では各キャリアのテキストがバイト一致した。
- メタデータは形式をまたいで正規化される —
dc:creator/dc:title/dcterms:createdがソース形式に依らず揃い、メタデータを持つ 4/4 のキャリアで回収できた。 - 今回試した形式では本当に依存が少ない。PDF のテキスト層、DOCX、ODT、RTF、HTML は、外部バイナリなしで 1 つの jar から解析できた。
- OpenJDK 26 でも正常に動作し、LTS 専用という制約がない。
- 途中切れバイナリでも検出は正しいまま exit 0 を返し、解析失敗時の信頼できるトリアージ信号になる。
- Apache-2.0 で、成熟しており、継続的に保守されている。
短所
- Markdown と CSV の識別はファイル拡張子に完全依存し、シグネチャのない 18 セルのうち 10 は、ファイル名が消えるか間違うと
text/plainに落ちた。 --textは要素型を返さない。表のグリッドはタブ区切りの行へ平坦化され、構造的なリストマーカーは消える。- 空ファイルや壊れた入力では例外が未処理で、抽出呼び出しだけでは 2 つのケースが同じに見える。
- 67 MB の jar に加え、CLI モードでは呼び出しごとの JVM コールドスタートがある。
- OCR とスキャン画像 PDF はここでは完全に未検証 — tesseract も poppler もなかったため、その経路については何も断言しません。
- ここにある数値は、1 台のマシン、1 つのバージョンでの合成データです。実データでの精度、暗号化ファイル、埋め込み/再帰文書、大量処理時のスループットは測っていません。
どんな人に向くか、向かないか
Tika が向いているのは、入力が すでに手元にあるファイル で、出力に 機械がインデックスできるテキストとメタデータ を求める場合です。検索インデックス、eDiscovery、アーカイブ処理、LLM 用コーパスの投入、アップロード経路の content-type 検証レイヤーの構築などです。検出済み型を判定し、フラットなテキストを抽出し、パイプラインが失ってはいけない内容を明示的にチェックしながら次へ渡す、そういう最初のトリアージと正規化の段階で役立ちます。
型付き要素、再構成された表、文書レイアウトが必要なら、--text だけで止まらないでください。文書がスキャンなら、少なくとも tesseract を入れて自分で数値を取るまでは使わないほうがいいです。私はそこに関する数値を持っていません。大量処理なら、代表的な文書に対してライブラリ版かサーバーモードを CLI と比較ベンチしてください。今回の小ファイルハーネスではプロセス起動のコストは見えましたが、スループットとリソース消費は測っていません。
見落とされがちなのは次です。ストレージ層がファイル名を削除し、Markdown や CSV を扱うなら、それらをプレーンテキストと区別する判断を Tika に頼らないでください。元の名前を保持してください。
代替案と Thunderbit の立ち位置
まず公平に言うと、ここでの比較は 入力 に関するものであって、品質の優劣ではありません。Tika は、ファイルを解析するための無料・Apache-2.0・セルフホスト型ツールキットです。ディスクやバケットにあるファイルを扱います。ページを取りに行くことも、JavaScript を実行することも、bot 対策に対処することもありませんし、そうだと偽ることもありません。
この境界線のところで、私たち自身の Thunderbit を含むマネージドな Web 抽出サービスがアーキテクチャに入ってきます。こちらはライブページを取得し、Tika はすでに手元にあるファイルを解析します。この記事では、それらのサービスを Tika と直接ベンチマークしていませんし、同じ入力に対する代替品でもありません。
きれいな分担はこうです。すでに所有している文書には Tika、取りに行く必要がある Web ページにはマネージド抽出 API。実際、多くのパイプラインは両方を使います。Web 側でクロールと抽出を行い、返ってきた PDF や DOCX 添付には Tika を使う、という形です。
オープンソース全体で比較したいなら、フルオープンソーススクレイパー比較、GitHub で特に役立つ スクレイピングプロジェクト集、ブラウザ駆動の Markdown アプローチを扱った Crawl4AI review、さらに広い スクレイピングツール総覧 も書いています。ノーコードで進めるなら、AI を使って サイトをスクレイピングする方法 の解説もあります。
結論
Apache Tika を使うべきか。答えはイエスです。異種混在のファイルをフラットテキストと正規化メタデータに変換するのが仕事で、自分のパイプラインで失えないフィールドやマーカーをきちんと検証するなら、使う価値があります。
今回の中で最も強かったのは検出器でした。5 つのコンテンツ検出可能フィクスチャに対して、ファイル名なしストリームを含めた 20 個のユニーク条件すべてで期待通りの型を返しました。埋め込んだマーカーは 14 種類の表現すべてで残り、出力は 3 回のローカル再実行でもバイト単位で同一でした。十分に有用な証拠です。ただし、あくまで合成データです。しかもこの JDK で、今回試した非 OCR 経路には外部バイナリを使わず、1 つの jar から実行できたのは、デプロイを気味悪いほど平凡にしてくれました。
ただし、適切に見積もる必要があります。表を渡せば、どれもタブ区切りの行として返ってきます。構造的なリストマーカーはすべて消えます。Markdown と CSV は、ファイル名がなくなるとその瞬間に身元を失います。空ファイルと壊れたファイルは同じ形の失敗を起こし、区別するには別の detect 呼び出しが必要です。そして、多くの Tika ユーザーが最も気にする OCR については、私は何も提供できません。実行できませんでしたし、推測で埋めるつもりもありません。
その条件の中では、Tika はかなり地味な仕事を、驚くほど高い信頼性でこなします。箱に書いてあるラベルではなく、バイト列を読みます。ただし、そのバイト列がどんな形だったのかまでは尋ねないでください。
Web データ抽出に Thunderbit を試す Get Started Free
FAQ
Apache Tika は拡張子が間違っていてもファイル形式を正しく判定できますか?
今回テストしたコンテンツ検出可能な 5 形式については、はい。PDF、DOCX、RTF、HTML、XML は、誤解を招く拡張子、拡張子なし、ファイル名なしストリームを含む 20 個のユニークな論理条件すべてで期待された media type に解決しました(重複ストリーム実行を含めると raw 実行は 30 回)。.txt と名付けた PDF も、application/pdf として検出されました。一方、Markdown と小さな CSV フィクスチャはファイル名情報に依存し、それが欠けるか間違うと text/plain に落ちました。
Tika は表や文書構造を保持しますか?
今回試した --text モードでは保持しません。表のグリッドはセルやヘッダの意味を持たないタブ区切りの行として返り、構造的なリストマーカー(HTML の <li>、DOCX の List Bullet スタイル)は消えました。14 種類すべてのキャリア表現で埋め込んだマーカーは残りましたが、それは完全な内容忠実度を証明するものではなく、--text には要素の型情報もありません。型付き要素や再構成された表が必要なら、別の Tika 出力ハンドラを試すか、別ツールを併用してください。
Apache Tika はスキャン PDF に OCR を使えますか? Tika は Tesseract 経由で OCR をサポートしていますが、私はテストしていませんし、今回の結果はそれに関する主張でもありません。 テスト環境には Tesseract も poppler もなかったため、OCR やスキャン画像の経路は実行前にすべて塞がれていました。今回のテストには OCR の数値は一切ありません。OCR が用途なら、tesseract を入れて自分でベンチしてください。ここでは Tika のその部分は未検証として扱ってください。
Tika は空ファイルや壊れたファイルをどう扱いますか?
静かに失敗するのではなく、はっきり失敗します。0 バイトファイルは ZeroByteFileException を投げ、途中で切れた PDF は PDFParser から TikaException を投げ、途中で切れた DOCX は POI の XML エラーを投げました。3 つとも exit 1 で stdout は空です。つまり、抽出呼び出しだけでは空ファイルと破損ファイルは区別できません。ただし検出は堅牢で、--detect はどちらの途中切れバイナリでも正しい型を返して exit 0 でした。これは、解析に時間を使う前の信頼できるトリアージ手段になります。
今回の Tika テストでカバーしていないものは何ですか? 明確に 4 つあります。OCR とスキャン画像(ブロックされ、未テスト)。実データでの精度。今回の結果はすべて、既知のマーカートークンを埋め込んだ制御済みの合成フィクスチャであり、汚れた実文書での精度ではなく、ラベル既知の忠実度を測っています。リソース消費、スループット、ピークメモリは測定していません。そして、"1,000 ファイル形式" という主張の長い尾です。今回テストしたのは、外部依存のない代表的な 9 形式にすぎず、カタログ全体ではありません。ここにあるのはすべて Tika 3.3.2、OpenJDK 26.0.1、macOS arm64、単一マシンでの結果です。


