Apache Tika 評測:它讀的是位元組,不是檔名——直到遇上 Markdown

最後更新於 August 19, 2026
Apache Tika 評測:它讀的是位元組,不是檔名——直到遇上 Markdown
AI 摘要
Apache Tika 是 Apache Software Foundation 的文件解析工具包:只要丟給它幾乎任何格式的檔案,它就會回傳純文字,以及一份標準化的 metadata 字典。專案 README 宣稱它支援超過一千種檔案類型,而 Tika 之所以能做到這點,是因為它把各類專用函式庫直接打包進來——PDF 用 PDFBox、Office 文件用 Apache POI、HTML 用 jsoup、ODT 用 ODF reader——因此整套工具可以做成單一 fat jar,解析時不需要再額外抓任何依賴。放到資料流程裡,它是最不起眼、卻最關鍵的第一站:在搜尋索引、電子蒐證審查集,或 LLM 語料庫前面,把一堆格式各異的檔案整理成統一的內容。

Apache Tika 是 Apache Software Foundation 的文件解析工具箱:你幾乎把任何格式的檔案丟進去,它就會回傳純文字,以及一份標準化的中繼資料字典。專案 README 宣稱支援超過一千種檔案類型,而 Tika 的作法是把各類專門函式庫直接包進來——像是 PDFBox 負責 PDF、Apache POI 處理 Office 文件、jsoup 解析 HTML、ODF reader 讀取 ODT——所以整個套件可以直接用單一 fat jar 形式運作,解析時不需要再另外下載任何東西。在資料管線裡,它扮演的是不太顯眼、但非常關鍵的第一站:放在搜尋索引、e-discovery 審查資料集,或 LLM 語料庫前面,把一堆格式各異的檔案整理成一致的輸出。簡單講,它就做兩件事——先判斷這串位元流「是什麼」,再把文字和中繼資料抽出來。

這大概是我近來裝過最省事的工具。只要一個 jar,java -jar tika-app-3.3.2.jar --text file.pdf,不用設定檔、不用模型權重、不用安裝後處理步驟,而且它在一台同日下午把其他 Java 工具都卡死的最新 JDK 上,也能乾脆俐落地跑完。我真正想測的倒不是它宣稱支援多少格式;那個題目太大了。更值得驗證的是:當輸入檔案「說謊」時,Tika 到底會怎麼反應?所以我做了一組受控測試素材:每個內容區塊都塞入獨特標記 token,把同一份邏輯文件渲染成九種不同的承載格式,再用錯誤副檔名、缺少副檔名、完全沒有檔名、零位元組檔案,以及只寫到一半的二進位檔去攻擊它。

真正有意思的行為,出現在偵測階段。把 PDF 改名成 .txt 後,我問 Tika 這是什麼;它回答 application/pdf。接著我把檔名整個拿掉,把原始位元資料透過 stdin 丟進去,答案還是一樣。在我那組五種可由內容辨識的格式裡,這個結果在 20 個獨立的邏輯條件 都成立:每種格式有三種檔名條件,再加上一種沒有檔名的串流條件。測試框架把串流案例以不同標籤跑了三次,產生 30 次成功的原始執行,但那些重複不是獨立證據。PDF 和 RTF 有可辨識的位元特徵;DOCX 會暴露其容器結構;HTML 和 XML 則可從標記或根內容辨識。機制不同,但在這組素材裡得到的實用結果相同:副檔名沒有蓋過內容。再來是文字類格式的規則,Markdown 一旦檔名錯了或沒檔名,立刻就退化成 text/plain。在這裡,它的身分完全依賴 .md

接下來所有數字都有兩個前提。測的是 Apache Tika 3.3.2——我在 2026 年 7 月 27 日確認時,它仍是最新穩定版;4.0.0 目前只在 Maven Central 上以 alpha 和 beta 形式存在。專案在我查閱時大約有 3.9k GitHub stars,授權是 Apache-2.0,幾乎是商用上最不會讓人有顧慮的那種授權。還有一點很重要:我完全沒有測 OCR。 沒有任何掃描頁面,沒有任何純圖片型 PDF。因為我執行測試的那台機器沒有安裝 Tesseract 和 poppler,所以所有 OCR 路徑在開始前就被擋住了。這裡沒有 OCR 數據,因為真的沒有 OCR 數據,就是這麼簡單。

先別看包裝文案:Tika 到底是什麼

一般人常以為 Apache Tika 是文件轉換器——丟進 DOCX,就吐出乾淨的 Markdown,標題和表格都原封不動保留。它不是這樣;越早釐清這件事,越能看出它的優點。

這次測試的路徑包含三個相關階段:內容類型偵測器、把位元資料交給正確 parser 的 dispatcher,以及 CLI 的 --text 輸出處理器,它會把扁平文字和可另外取用的中繼資料一起輸出。這種輸出合約裡,沒有 Title 物件、沒有 ListItem,也沒有重建出的表格格線。Tika 也提供其他 handler 和 API,包括以 XHTML/SAX 為導向的輸出;那些我沒有測。所以,下面所有關於結構保留的結論,都只針對 tika-app --text,不是在宣稱整個工具箱哪裡都沒有結構化事件流。

這聽起來像限制,某一個層面上確實是。但它也代表 Tika 沒有什麼可以誤判的東西,這正是那些更「多話」的同類工具反向取捨時常付出的代價。

偵測本身是有文件說明的順序:先看 signature bytes,再看 XML root,再看副檔名 glob,最後才是你自己提供的型別(Tika 自己的偵測文件 有列出來)。只有在型別被判定之後,dispatcher 才會把位元資料交給對應的內建 parser——像是 PDFBox、POI、jsoup、以及文字類型用的 TextAndCSVParser

這個「先偵測、再解析」的拆分並不是內部瑣事。正因如此,檔案就算壞到不能解析,仍然可能先被正確分類;而這也正是 Tika 在事情開始壞掉時,最實用的一個特點。

安裝:一個 jar、一條指令,還有不挑 JVM 的表現

安裝其實就是下載而已。Maven Central 上的 tika-app-3.3.2.jar 大約 67 MB——一個把所有 parser 都打包進去的 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 不會在這裡踩你。

安裝面還有兩個誠實的結論。CLI 每次呼叫都會啟動一個新的 JVM,所以冷啟動是真的存在——我那個測試框架跑了 131 次呼叫,花了差不多一分鐘,主要時間都耗在 JVM warmup。如果你要處理大量檔案,該用 library 或 server mode,而不是拿 shell loop 去包 jar。至於「不依賴外部程式」這件事,也有明確邊界:PDF 文字層抽取不需要外部工具,但 OCR 需要 tesseract 和 poppler。 在沒有安裝這兩個工具的主機上,文字層 PDF、DOCX、ODT、RTF、HTML、XML、TXT、Markdown、CSV 都能正常解析;但掃描文件不行,而我也沒有假裝它行。

這種差異和我同一天測的另一個函式庫 unstructured 對比更明顯:它的電子 PDF 路徑完全被擋住,因為匯入 PDF 模組時就會把推論堆疊(torch 等)一起載入——是在 strategy dispatch 之前,所以就算是「快」策略,沒把那些依賴載好也無法匯入。Tika 則是用一條乾淨的 java -jar 就把同一份 PDF 的文字層抽了出來。

會說謊的副檔名測試:內容型別偵測不吃你幫檔案取的名字

測量結果圖表:不同檔名條件下的類型偵測

八種格式,每一種都提供正確副檔名、故意給錯副檔名、或完全不給副檔名,再加上透過 stdin 輸入、沒有檔名的原始位元串流。這就是 32 個獨立的邏輯條件。原始測試框架還把相同的串流資料在每個檔名標籤下各跑了一次,總共 48 次原始執行;但那三個串流列其實可以合併成一個條件,因為 stdin 沒有檔名可供 glob 使用。

測試素材真實型別改名為正確副檔名錯誤副檔名無副檔名原始串流,無檔名
PDFapplication/pdf.txt
DOCXOOXML wordprocessingml.jpg
RTFapplication/rtf.html
HTMLtext/html.csv
XMLapplication/xml.txt
純文字text/plain.pdf
Markdowntext/markdown.pdftext/plaintext/plaintext/plain
CSVtext/csv.txttext/plaintext/plaintext/plain

(串流欄位把三種副檔名條件都合併了,因為沒有檔名時,glob 根本沒東西可讀。)

五種可由內容偵測的格式——PDF、DOCX、RTF、HTML、XML——在 20/20 個獨立條件 都命中正確型別(如果把重複的串流執行也算進去,就是 30/30 次原始執行)。被命名成 report.txt 的 PDF 仍然是 PDF。被命名成 photo.jpg 的 DOCX 仍然是 DOCX。這一點不需要檔名。這不代表這五種格式都只是靠固定位元簽章判定:PDF 和 RTF 有可辨識的 header,DOCX 是 ZIP 型容器,HTML/XML 則可由標記或 root content 辨識。但在這組素材裡,會說謊的副檔名沒有贏。

接下來是文字類格式。Markdown 只有在 .md 副檔名存在且可讀時,才會被判定為 text/markdown。如果改名、移除副檔名,或改用串流送入,它在這次測試裡都退化成 text/plain。CSV 也一樣,至少在這個刻意做得很小的格子裡是如此:text/csv 只會從 .csv 的 glob 來。用獨立條件來算,Markdown 和 CSV 都只在四個條件中的一個條件下被辨識為專屬型別;純文字本來就是 text/plain,所以它沒有什麼可「退化」的。那 48 次原始執行的框架仍然有價值,因為它記錄了可重現性,但不能當成更大的分母。

這裡有個對 Tika 很加分的細節:會說謊的副檔名也沒有贏。 我那個被改名成 .pdf 的 Markdown 素材回傳的是 text/plain,不是 application/pdf。Tika 沒有相信那個謊言;只是無法確認真相。退回到父類型,比起自信地判錯,顯然是好得多的失敗方式,而 text/markdown 本來就是 text/plain 的文件化子型別,所以這個 fallback 合理,不是隨便猜的。

CSV 這裡要加一個保留說明。Tika 其實有一個統計式的 CSV 偵測器,而且在解析時——從 X-TIKA:Parsed-By 鏈中出現 TextAndCSVParser 可以證實——我那個 2 欄 × 3 列的小型格子最後被判成 text/plain,不是 text/csv。這只是針對一個刻意極小的素材所得到的一次觀察。更大或帶引號的 CSV 很可能會觸發偵測器。我不是在說 CSV 內容偵測壞了;我是說,在這個格子裡,只有副檔名把它帶成了 text/csv

這件事在真實上傳管線裡為什麼重要

實際場景就是上傳路由。假設你接受使用者上傳檔案,並依類型分流:PDF 送到發票解析器、試算表送到總帳匯入器、其他都進文字索引。如果你只信副檔名,某個把 PDF 命名成 notes.txt 的人就會被送進錯誤分支——而這還是溫和版本;更糟的是帶有友善副檔名的 polyglot 檔案。

對這裡測過的二進位和標記型素材來說,Tika 就算把檔名拿掉,還是能依內容分流,這對 blob store 或 HTTP body handler 已經把檔名丟掉的情況很有用。但這個結果不涵蓋 Tika 的長尾、含糊檔案,或 polyglots。測試過的文字類素材則不同:當管線把檔名剝掉時,Markdown 和 CSV 都只剩 text/plain,因此那些依賴特定 media type 的規則就不會再觸發。若你需要保留原始名稱,請把它當成旁路中繼資料存起來,不要期待內容偵測能幫你重建。

植入的內容都在,但 --text 把結構整個壓平了

保真度是第二個維度,而且它清楚分成兩半。我把一份標準文件(標題、兩段正文、項目符號清單、編號清單、結尾段落)渲染成 HTML、Markdown、純文字、DOCX、PDF、RTF、ODT 和 XML,另外再把一份表格文件渲染成 HTML、Markdown、文字、DOCX、CSV 和 XML。總共十四種承載格式。每個區塊都帶有獨特 token——像 zztitle1zzitem3zztblcell_beta 之類——因此「有沒有存活」可以直接用子字串檢查,不是主觀判斷。

在全部十四種渲染結果中,標記 token 的回收率都是 1.000。 沒有任何植入 token 遺失:每個帶標記的表格儲存格、清單項目和標題都還在。每種承載格式在 warmup 後重複三次,本地回傳的 --text 輸出完全一致。這個 oracle 只能說明有沒有區塊存在,不能證明未標記字元、順序、空白、Unicode 正規化、重複內容、連結、頁首頁尾或內嵌物件都完好無缺。它是一個區塊存在性的檢查,不是完整文件保真度的證明。

扁平文字輸出會丟掉源文件裡大部分結構。

這是 HTML 表格文件經 --text 輸出的樣子:

	Tool	Throughput

	zztblcell_alpha	120

	zztblcell_beta	95

以 tab 串接的幾行文字。表頭沒有被標成表頭。沒有網格,沒有除了 tab 以外的儲存格邊界,也沒有辦法知道它原本是 <table>。DOCX 表格也是同樣的壓平方式。

清單就更微妙了,會依源內容本身而分裂:

原始來源中的項目符號是什麼承載格式--text 回傳什麼
一個 字面字元 — 這些渲染內容都把 - 當成實際文字寫出來純文字、Markdown、RTF、ODT、PDF- 會保留,因為 Tika 只是把字元原樣傳過去
真實結構 — HTML 的 <li>、DOCX 的 List Bullet 樣式HTML、DOCX標記會完全消失,只剩項目文字本身:HTML 裡會是 tab 縮排,DOCX 裡是毫無裝飾的一行文字

Tika 不會把自己沒收到的結構標記重新渲染出來。內容一樣,但輸出看起來不一樣。

Markdown 的案例把這點說得最清楚。把一個帶 pipe table 的 .md 檔丟給 Tika,pipes 會原樣回來,這看起來像是保留了結構。其實不是。Tika 只是把它當文字解析後再把位元組吐回來,沒有人真正理解那個表格。

所以真正量到的合約其實更窄:所有植入標記都存活了,但 --text 沒有保留 typed elements,也沒有可重建的表格格線。 把這叫 parser 缺陷會錯過重點。扁平抽取刻意避開了元素分類問題;但它也無法滿足下游需要那些元素型別的需求。如果你需要 typed blocks 或重建表格,--text 只是整套流程中的一個元件,不是全部。Tika 的其他 handler 也許能提供更多結構,但那不在這次測試範圍內。

這裡所有保真度數字都有一個共同前提:它們來自單機、單版本、單 JDK 上的受控合成素材。它們能證明帶標記的區塊有出現在輸出中,不能證明在真實混亂語料上也逐字逐字完全無誤。

中繼資料:有標準化,而且意外地不愛亂猜

測量結果圖表:各承載格式的中繼資料回收情況

我在每種有中繼資料層的承載格式裡都嵌入已知的作者、標題和建立日期值,然後檢查回傳結果。

承載格式author → dc:creatortitle → dc:titlecreated → dcterms:created
HTML (<meta name=author><title>)未嵌入
DOCX(核心屬性)✅ 精準 2021-03-15T09:30:00Z
PDF(info dict)有,但那是產生器自己寫入的 timestamp——不計分
ODT (meta.xml)✅ 精準 2021-03-15T09:30:00Z
TXT / MD / CSV / RTF / XML沒有中繼資料層

作者和標題在 4/4 種具備中繼資料層的承載格式中都被成功回收,而且——這點很值得稱讚——它們是標準化的。HTML 的 <meta name="author">、DOCX 的核心屬性、PDF 的 /Author 欄位,以及 ODT 的 dc:creator 元素,最後都會落到同一個 dc:creator key 裡。你只要寫一個 consumer,不需要寫四個。

created 的部分就比較誠實地有起伏。DOCX 和 ODT 回傳了我嵌入的 2021 精準時間戳。PDF 也回傳了一個建立日期,但那是我的產生器函式庫在建置時蓋上的時間,不是我想嵌入的值——所以我把它列為「有出現」,不算「成功回收」。至於沒有中繼資料層的格式,就什麼都沒冒出來,這才是正確答案。Tika 不會根據文字內容去猜作者。

故意把它弄壞,然後看出來的分流技巧

四種有敵意的輸入:零位元組檔案、有效 PDF header 但內文被截斷、被截斷的 DOCX ZIP,以及一個含有多位元組字元、沒有 BOM 也沒有編碼宣告的 UTF-8 檔案。這些都是本地素材形狀,不是 Tika 的臨界值。

底層測試框架、生成的素材、原始 JSON、jar checksum 和環境清單在這裡都沒有公開連結,所以外部讀者無法獨立重現完全相同的分母。請把這些表格視為已報告的觀察結果,而不是第三方可驗證的證據。

輸入--text / --json丟出的錯誤--detect
0 位元組檔案exit 1,stdout 空白ZeroByteFileException: InputStream must have > 0 bytesexit 0 → 有檔名時為 text/plain,從串流讀取時為 application/octet-stream
被截斷的 PDFexit 1,stdout 空白TikaException: TIKA-198: Illegal IOException from PDFParserexit 0 → application/pdf
被截斷的 DOCXexit 1,stdout 空白POI FATAL: "XML document structures must start and end within the same entity"exit 0 → OOXML type
UTF-8、無 BOM、未宣告編碼exit 0exit 0 → text/plain,charset UTF-8

抽取會明確失敗,而且這些失敗的外觀很一致。 零位元組檔案、被截斷的 PDF、以及被截斷的 DOCX 都會產生例外、exit 1,且 stdout 是空的。CLI 不會把失敗吞掉變成乾淨的空結果。從程序安全性來看,這些情況都沒卡死、沒 segmentation fault,但呼叫端不能只看空字串,還要檢查 exit status 和 stderr。

偵測與解析是分離的。 兩個被截斷的二進位檔在 --detect 下都回傳 exit 0,並根據完整開頭內容得到預期型別;接著 parser 才在壞掉的內文上失敗。因此,在失敗解析之前或之後,管線都可以把偵測當作獨立的分流訊號。到底要不要預設先 detect,取決於部署模式:這次測試沒有比較 detect-first 和 parse-only 的效能,而且在大量場景裡,兩次新啟動的 CLI JVM 可能未必是好取捨。

字元編碼偵測是有效的。 那個沒有 BOM、也沒有編碼宣告的 UTF-8 檔案被正確解碼成 UTF-8,而且 日本語テスト 原樣通過。給讀中繼資料字典的人一個小提醒:我那些純 ASCII 素材會回報 charset=ISO-8859-1,但在 ASCII 位元上它和 UTF-8 沒差別。這不是漏判,而是平手。

把 Tika 和 unstructured 放在一起看:同樣是文件類型,工作卻不同

這兩個工具是在同一個研究時段中測的,但這是輸出合約的分類,不是對稱式 benchmark。兩者評分的結果本來就不同。

相關評測:Unstructured 評測

Apache Tikaunstructured
我測的是什麼內容保真度:有沒有東西掉掉?元素分類保真度:每個區塊有沒有被判成正確型別?
結果在十四種渲染結果中,所有植入標記都存在在另一組分類測試中,純文字表格的 Table 回收率是 0.000,而一個包含動詞的標題被分類成 narrative text
回傳的 typed elements沒有——完全沒有結構回來TitleNarrativeTextListItemTable——正是 Tika 不做的事
OCR因為主機缺少 tesseract,被擋住因為主機缺少 tesseract,被擋住

保留原樣的扁平輸出 vs. 帶有型別但分類會出錯的元素。要看下游需要什麼再選。若只是搜尋索引或 LLM context window,純文字可能就夠了。若系統是依元素型別運作,Tika 的 --text 路徑就無法提供那種合約。

我們兩邊都沒有掃描文件的數據。

優點與缺點

優點

  • 在五種可由內容偵測的素材上,20/20 個獨立條件都忽略了會說謊的檔名;重複的串流執行也一致。
  • 在 14 種承載格式中,所有植入標記都存活下來,包括帶標記的表格儲存格與清單項目。
  • 可重現性高:在本地重跑三次,每個承載格式都回傳位元級一致的文字。
  • 跨格式的中繼資料有標準化——不論來源格式為何,都會歸到 dc:creator / dc:title / dcterms:created,且在 4/4 個具中繼資料層的格式中都能回收。
  • 對我測的格式來說,確實不需要外部依賴:PDF 文字層、DOCX、ODT、RTF、HTML 都能只靠一個 jar 解析,不需要外部二進位。
  • 在 OpenJDK 26 上可正常運作——沒有只限 LTS 的限制。
  • 即使遇到被截斷的二進位檔,偵測仍能正確回傳 exit 0,提供可靠的分流訊號。
  • Apache-2.0、成熟、而且仍在積極維護。

缺點

  • Markdown 和 CSV 的辨識完全依賴檔名副檔名;一旦檔名消失或錯誤,18 個無 signature 的格子裡有 10 個會退化成 text/plain
  • --text 不會回傳元素型別;表格格線會被壓平成 tab 串接的文字,結構性的清單標記也會消失。
  • 遇到空檔和損壞輸入時會直接丟例外;只看抽取呼叫本身,這兩種情況長得一模一樣。
  • 67 MB 的 jar,加上 CLI 模式每次呼叫都要冷啟動 JVM。
  • OCR 和掃描圖像 PDF 在這裡完全沒測——缺少 tesseract 和 poppler,所以對那條路徑不做任何聲明。
  • 這裡所有數字都只是單機單版本上的合成真值。真實語料的準確率、加密檔案、嵌入/遞迴文件,以及大規模吞吐量都沒有測。

誰適合用,誰不該只靠它

Tika 適合的情境是:你的輸入是你手上已經有的檔案,而輸出需要的是可供機器索引的文字加中繼資料。像是搜尋索引、e-discovery、歸檔處理、把語料餵給 LLM、建立上傳管線的內容類型驗證層。它非常適合作為前端第一步的分流與標準化:先辨識測過的格式、抽出扁平文字,然後帶著明確檢查把資料交給下一個你不能讓它遺失內容的系統。

如果你需要 typed elements、重建表格,或文件排版,就別把流程停在 --text。如果你的文件是掃描檔,也先別急著用它——至少要先安裝 tesseract 並自己測過數據,因為我這裡沒有。若你要做大量處理,請拿代表性文件去比較 library 或 server mode 與 CLI 的表現。這次的小檔案測試裡,程序啟動成本是看得見的,但吞吐量與資源成本沒有量。

還有一個很多人會踩到的點:如果你的儲存層會把檔名抹掉,而你在處理 Markdown 或 CSV,就不要指望 Tika 幫你把它們和純文字區分開來。原始檔名要留著。

替代方案,以及 Thunderbit 的位置

先講公平一點的框架,因為這裡真正該比較的是輸入來源,不是誰比較好。Tika 是一個免費、Apache-2.0、可自架的檔案解析工具。它處理的是你已經存在磁碟或 bucket 裡的檔案。不會去抓網頁、不會跑 JavaScript,也不會跟 anti-bot 機制硬碰硬——它本來就不假裝自己會這些。

這就是管理式網頁擷取服務可能進入架構的位置,包括我們自己的 Thunderbit:它負責抓取即時網頁,而 Tika 則解析你手上已經有的檔案。這篇文章沒有拿這些服務和 Tika 做 benchmark,而且它們也不是同一種輸入的替代品。

乾淨的分工就是:Tika 處理你已經擁有的文件;管理式擷取 API 則去抓你需要從網頁端取得的內容。很多管線兩者都會用到——網頁端負責 crawl 和 extract,回來的 PDF 和 DOCX 附件則交給 Tika。

如果你正在比較更廣泛的開源工具生態,我寫過一篇 完整的開源 scraper 比較,整理了 GitHub 上最實用的 scraping 專案,也有一篇實作型的 Crawl4AI 評測,涵蓋瀏覽器驅動的 Markdown 路線,還有一篇更全面的 scraping 工具總整理。如果你想走免寫程式的路線,也可以參考這篇教你如何 用 AI 抓取任何網站

試試 Thunderbit 進行網頁資料擷取

結論

要不要用 Apache Tika?如果你的工作是把異質檔案轉成扁平文字和標準化中繼資料,而且你會驗證自己管線不能承受遺失的欄位或標記,那答案是要。

這次最強的部分是偵測器。在五種可由內容偵測的素材上,它在 20/20 個獨立條件都回傳了預期型別,包含沒有檔名的串流。所有植入標記在十四種渲染結果裡都存活,而且在本地重跑三次都能逐位元一致地重現輸出。這些都是有用的證據,但仍然是合成證據。在這個 JDK 上只靠一個 jar 完成,而且非 OCR 路徑沒有外部二進位依賴,部署體驗其實相當平淡——而這正是好事。

但你還是要用對它。你丟進去的每個表格,都會回成 tab 串接文字。每個結構性的清單標記都會消失。Markdown 和 CSV 一旦檔名不見,就失去身分。空檔和損壞檔案會丟出同樣型態的失敗,你得另外呼叫 detect 才分得出來。而對很多 Tika 使用者最在意的 OCR,我這裡沒有答案:我沒辦法執行,也不會憑空估計。

在這些邊界之內,Tika 做的工作雖然不華麗,卻意外可靠。它讀的是位元資料,不是盒子上的標籤。只是別要求它告訴你,這些位元原本長什麼樣。

試試 Thunderbit 進行網頁資料擷取 Get Started Free

常見問題

Apache Tika 在副檔名錯誤時,還能正確偵測檔案類型嗎?
就這裡測過的五種可由內容偵測的素材來說,可以。PDF、DOCX、RTF、HTML 和 XML 在 20 個獨立的邏輯條件中都能回到預期的 media type(如果算上重複串流執行,就是 30 次原始執行),即使副檔名誤導、沒有副檔名,或從沒有檔名的串流送入,也一樣如此。命名成 .txt 的 PDF 仍然會被偵測成 application/pdf。Markdown 和那個小型 CSV 素材則依賴檔名資訊,一旦檔名缺失或錯誤,就會退化成 text/plain

Tika 能保留表格和文件結構嗎?
在這次測的 --text 模式裡不行。表格格線會變成 tab 串接的文字,沒有儲存格或表頭語意;結構性的清單標記(例如 HTML 的 <li>、DOCX 的 List Bullet 樣式)也會消失。雖然所有植入標記都在 14 種承載格式中存活,但這不代表完整內容保真;--text 也不提供元素型別。如果你需要 typed elements 或重建表格,請測其他 Tika 輸出 handler,或搭配別的工具使用。

Apache Tika 可以對掃描 PDF 做 OCR 嗎?
Tika 透過 Tesseract 支援 OCR,但我沒有測,而且這裡的任何結果都不能拿來宣稱它有或沒有這個能力。 因為我的測試主機沒有安裝 Tesseract 和 poppler,所以所有 OCR 與掃描圖像路徑都在開始前就被擋住了。這次測試裡完全沒有 OCR 數據。如果 OCR 是你的使用情境,請自己安裝 tesseract 再做 benchmark——把那部分 Tika 視為在這裡尚未驗證。

Tika 遇到空檔或損壞檔案時會怎麼做?
它會明確失敗,不會默默吞掉。0 位元組檔案會丟出 ZeroByteFileException;被截斷的 PDF 會從 PDFParser 丟出 TikaException;被截斷的 DOCX 會丟出 POI 的 XML 錯誤。三者都會 exit 1,而且 stdout 是空的,所以只靠抽取呼叫本身,空檔和損壞檔案是分不出來的。不過偵測仍然很穩——--detect 在這兩種被截斷的二進位檔上都回傳 exit 0,且型別正確,因此在正式解析前,這會是很可靠的分流步驟。

這次的 Tika 測試沒有涵蓋什麼?
四件事,我直接講清楚。OCR 與掃描圖像(被阻擋,未測)。真實語料的準確率——所有結果都來自受控合成素材,並植入 marker token,所以量到的是相對於已知標籤的保真度,而不是面對混亂真實文件時的準確率。資源成本、吞吐量與峰值記憶體,我都沒量。還有那句「一千種檔案類型」的長尾部分:我只測了九種具代表性的、無外部依賴的格式,不是整個目錄。這裡全部結果都來自 Tika 3.3.2、OpenJDK 26.0.1、macOS arm64、單一機器。

Ke
Ke
Thunderbit 技術長|資深資料科學家與機器學習專家 Ke Shen 在機器學習與資料科學領域擁有近十年經驗,畢業於哥倫比亞大學,曾任 Walmart Labs 資深資料科學家。他精通 Python、R、Java 與統計學,且具備深受同儕認可的深厚專業,分享如何將複雜的 AI 演算法從理論落實到可投入生產的架構的實戰見解。
目錄
Thunderbit · AI 網頁資料代理

1 次點擊 內擷取任何頁面的資料

深受 250,000+ 用戶信賴
提供免費方案
從網頁到試算表
描述你需要的內容——Thunderbit 的 AI 代理會幫你爬取,並匯出到 Excel、Google Sheets、Airtable 或 Notion。免費即可開始。
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week