Đánh giá Apache Tika: Nó đọc bytes, không nhìn tên tệp — cho đến khi gặp Markdown

Cập nhật lần cuối vào August 14, 2026
Đánh giá Apache Tika: Nó đọc bytes, không nhìn tên tệp — cho đến khi gặp Markdown
Tóm tắt bằng AI
Apache Tika là bộ công cụ phân tích tài liệu của Apache Software Foundation: chỉ cần đưa vào gần như bất kỳ loại tệp nào, nó sẽ trả lại văn bản thuần cùng một từ điển metadata đã được chuẩn hóa. README của dự án cho biết Tika hỗ trợ hơn một nghìn định dạng tệp, và để làm được điều đó, Tika tự đóng gói sẵn các thư viện chuyên biệt — PDFBox cho PDF, Apache POI cho tài liệu Office, jsoup cho HTML, bộ đọc ODF cho ODT — nên toàn bộ công cụ được phát hành dưới dạng một fat jar duy nhất, không cần tải thêm gì lúc phân tích. Trong một pipeline dữ liệu, nó thường là bước đầu khá âm thầm: thành phần đứng trước search index, bộ hồ sơ e-discovery, hay corpus cho LLM, biến một đống tệp hỗn tạp thành thứ đồng nhất hơn.

Keywords

đánh giá apache tika, web scraping, mã nguồn mở, benchmark

Content

Apache Tika là bộ công cụ phân tích tài liệu của Apache Software Foundation: chỉ cần ném vào gần như bất kỳ loại tệp nào, nó sẽ trả về văn bản thuần và một bộ metadata đã được chuẩn hóa. README của dự án cho biết Tika hỗ trợ hơn một nghìn định dạng tệp, và để làm được điều đó, Tika tự đóng gói sẵn các thư viện chuyên biệt — PDFBox cho PDF, Apache POI cho tài liệu Office, jsoup cho HTML, bộ đọc ODF cho ODT — nên toàn bộ công cụ được phát hành dưới dạng một fat jar duy nhất, không cần tải thêm gì lúc phân tích. Trong một pipeline dữ liệu, nó thường là bước đầu khá âm thầm: thành phần đứng trước search index, bộ hồ sơ e-discovery, hay corpus cho LLM, biến một đống tệp hỗn tạp thành thứ đồng nhất hơn. Nói ngắn gọn, nó làm hai việc: xác định luồng byte đó là gì, rồi trích xuất văn bản và metadata ra ngoài.

Đây là một trong những công cụ ít gây phiền nhất mà tôi từng cài trong một thời gian dài. Chỉ một file jar, java -jar tika-app-3.3.2.jar --text file.pdf, không file cấu hình, không model weights, không bước hậu cài đặt, và nó chạy ngon lành trên một JDK thế hệ mới, trong khi cùng buổi chiều đó các công cụ Java khác trên cùng máy lại bị đứng hẳn. Tuy nhiên, tôi không muốn kiểm tra lời quảng cáo về catalog tính năng; câu hỏi có thể kiểm chứng được thì hẹp hơn nhiều. Khi đầu vào nói dối bạn, Tika thực sự sẽ làm gì? Vì thế tôi dựng một bộ fixture có kiểm soát, mỗi khối nội dung đều mang một token đánh dấu duy nhất, rồi render cùng một tài liệu logic sang chín định dạng khác nhau, sau đó đem đi thử với phần mở rộng sai, thiếu phần mở rộng, không có tên tệp, file rỗng 0 byte, và các binary bị cắt dở.

Phần thú vị nhất nằm ở khâu nhận diện. Tôi đổi đuôi một file PDF sang .txt rồi hỏi Tika đó là gì; nó trả lời application/pdf. Sau đó tôi xóa hẳn tên tệp, bơm raw bytes qua stdin, và nhận cùng một câu trả lời. Trên năm định dạng có thể nhận diện bằng nội dung trong bộ test của tôi, kết quả này đúng trong cả 20 điều kiện logic duy nhất: ba điều kiện về tên tệp cộng với một điều kiện stream không có tên cho mỗi định dạng. Bộ harness còn chạy trường hợp stream ba lần dưới ba nhãn khác nhau, tạo ra 30 lượt chạy raw thành công, nhưng các lượt lặp đó không phải là bằng chứng độc lập. PDF và RTF có byte nhận dạng rõ ràng; DOCX lộ qua container của nó; HTML và XML có thể được xác định từ markup hoặc root content. Cơ chế khác nhau, kết quả hữu ích giống nhau trong bộ fixture này: phần mở rộng không lấn át nội dung. Còn ở nhóm định dạng văn bản, Markdown lại rơi xuống text/plain ngay khi tên tệp sai hoặc bị bỏ trống. Trong trường hợp này, nhận diện của nó hoàn toàn phụ thuộc vào .md.

Có hai giới hạn cần nhớ cho mọi con số phía dưới. Tôi đã test Apache Tika 3.3.2 — kiểm tra ngày 27/07/2026 thì đây vẫn là bản stable mới nhất; nhánh 4.0.0 mới chỉ tồn tại dưới dạng alpha và beta trên Maven Central. Dự án có khoảng 3,9k GitHub stars vào thời điểm tôi kiểm tra ngày 27/07/2026, và dùng giấy phép Apache-2.0, một kiểu giấy phép gần như không gây vướng mắc thương mại. Và tôi hoàn toàn không test OCR. Không một trang scan nào, không một PDF chỉ chứa ảnh nào. Máy tôi dùng không cài Tesseract và poppler, nên mọi nhánh OCR đều bị chặn từ đầu. Ở đây không có số liệu OCR nào, vì thực tế là không hề có số liệu OCR nào.

Tika là gì, sau khi bạn ngừng đọc phần marketing trên hộp

Cách hiểu phổ biến là Apache Tika là một công cụ chuyển đổi tài liệu — đưa vào DOCX, lấy ra Markdown sạch sẽ với heading và table nguyên vẹn. Nhưng Tika không phải như thế, và càng hiểu rõ điều này thì công cụ càng có vẻ hợp lý hơn.

Luồng được test ở đây có ba giai đoạn liên quan: một bộ nhận diện content-type, một dispatcher chuyển bytes sang parser phù hợp, và bộ xử lý đầu ra --text của CLI, xuất ra văn bản phẳng cùng metadata có thể lấy riêng. Trong kiểu output đó không có đối tượng Title, không có ListItem, và cũng không có lưới table được tái tạo. Tika còn có các handler và API khác, bao gồm đầu ra theo hướng XHTML/SAX; tôi không test những phần đó. Vì vậy, mọi kết luận về cấu trúc dưới đây chỉ áp dụng cho tika-app --text, chứ không phải khẳng định rằng toàn bộ toolkit không hề có luồng sự kiện có cấu trúc ở đâu đó.

Nghe có vẻ là một hạn chế, và đúng là ở một khía cạnh nó là vậy. Nhưng điều đó cũng có nghĩa là Tika không có gì để nhận nhầm, mà đó lại chính là cái giá mà các công cụ “tham” hơn thường phải trả theo chiều ngược lại.

Bản thân quá trình nhận diện chạy theo thứ tự đã được mô tả: byte chữ ký trước, rồi kiểm tra root XML, rồi đối chiếu glob theo tên tệp, rồi mới đến kiểu bạn tự cung cấp (tài liệu nhận diện của Tika mô tả rõ điều này). Chỉ khi type đã được xác định, dispatcher mới chuyển bytes sang parser được đóng gói tương ứng — PDFBox, POI, jsoup, hoặc TextAndCSVParser cho nhóm văn bản.

Tách riêng giữa nhận diện và phân tích không phải là chi tiết nội bộ vô nghĩa. Đó là lý do một tệp hỏng đến mức không parse được vẫn có thể được gán đúng type, và đây cũng là mẹo thực tế nhất mà Tika mang lại khi mọi thứ bắt đầu vỡ.

Thiết lập: một jar, một lệnh, và một JVM khá dễ tính

Cài đặt thực ra chỉ là tải về. tika-app-3.3.2.jar từ Maven Central nặng khoảng 67 MB — một fat jar gói sẵn mọi parser — rồi sau đó chỉ cần java -jar tika-app-3.3.2.jar --text file.pdf. Không file cấu hình, không model weights, không bước hậu cài đặt, không phải lần mò chuỗi brew install nào cả.

Điều khiến tôi ngạc nhiên là câu chuyện JDK. Tôi chạy toàn bộ trên OpenJDK 26.0.1, một bản non-LTS ở tuyến đầu, và --version, --text, --metadata, --detect đều trả về exit 0, không hề có lời than phiền tương thích. Điểm này đáng nhắc đến, vì cùng máy đó và cùng thời điểm, tôi cũng test Apache Nutch, và vòng crawl của nó hoàn toàn không chạy được trên JDK 26; nó cần bản LTS ở mức 21 hoặc thấp hơn do việc loại bỏ SecurityManager ở các JDK mới. Tika thì không quan tâm. Nếu bạn vẫn né các công cụ JVM vì kiểu đau đầu đó, Tika không phải nơi gây đau.

Có hai kết luận thẳng thắn ở phần thiết lập. CLI sẽ khởi tạo một JVM mới mỗi lần chạy, nên cold start là có thật — 131 lượt chạy cho harness của tôi mất khoảng một phút, chủ yếu là thời gian JVM khởi động. Nếu phải xử lý số lượng lớn tệp, bạn nên dùng thư viện hoặc chế độ server, chứ không nên loop shell qua file jar. Và câu chuyện “không phụ thuộc” cũng có giới hạn cứng: trích xuất text layer của PDF không cần gì bên ngoài, nhưng OCR thì cần tesseract và poppler. PDF có text layer, DOCX, ODT, RTF, HTML, XML, TXT, Markdown, CSV đều parse được trên một máy không cài hai thứ đó. Còn tài liệu scan thì không, và tôi cũng không hề cố giả vờ là có.

Điểm này còn rõ hơn khi so với thư viện anh em tôi test cùng ngày, unstructured, vì nhánh xử lý PDF điện tử của nó bị chặn hoàn toàn: chỉ cần import module PDF là nó đã kéo theo cả stack suy luận (torch và các thư viện liên quan) ở thời điểm load — trước cả khi dispatch chiến lược, nên ngay cả “fast strategy” cũng không import được nếu thiếu chúng. Tika chỉ cần một lệnh java -jar là có thể parse text layer của cùng file PDF đó.

Bài test phần mở rộng nói dối: nhận diện mime type bất chấp tên file

Biểu đồ kết quả đo: Nhận diện kiểu dữ liệu qua các điều kiện tên tệp

Tám định dạng, mỗi định dạng được đưa vào với phần mở rộng đúng, phần mở rộng cố tình sai, hoặc không có phần mở rộng, cộng thêm một luồng byte không có tên tệp trên stdin. Đó là 32 điều kiện logic duy nhất. Harness ban đầu còn chạy cùng một byte stream thêm một lần dưới mỗi nhãn tên tệp, tạo thành 48 lượt thực thi raw; ba hàng stream đó gộp lại thành một điều kiện vì stdin không mang tên tệp.

FixtureKiểu thậtĐổi thànhĐuôi đúngĐuôi nói dốiKhông đuôiStream raw, không có tên tệp
PDFapplication/pdf.txt
DOCXOOXML wordprocessingml.jpg
RTFapplication/rtf.html
HTMLtext/html.csv
XMLapplication/xml.txt
Văn bản thuầntext/plain.pdf
Markdowntext/markdown.pdftext/plaintext/plaintext/plain
CSVtext/csv.txttext/plaintext/plaintext/plain

(Cột stream gộp cả ba điều kiện về phần mở rộng, vì khi không có tên tệp thì glob không có gì để đọc.)

Năm định dạng có thể nhận diện bằng nội dung — PDF, DOCX, RTF, HTML và XML — đều trả về kiểu thật trong 20/20 điều kiện logic duy nhất (và 30/30 lượt thực thi raw của harness, gồm cả các lượt stream lặp lại). Một file PDF đặt tên report.txt vẫn là PDF. Một DOCX đặt tên photo.jpg vẫn là DOCX. Không cần tên tệp. Điều này không có nghĩa cả năm định dạng đều dùng chữ ký byte cố định: PDF và RTF có header nhận dạng được, DOCX là container dựa trên ZIP, còn HTML/XML được xác định từ markup hoặc root content. Trong bộ fixture này, phần mở rộng nói dối không thắng.

Còn ở nhóm văn bản thì khác. Markdown chỉ được nhận là text/markdown khi phần mở rộng .md còn hiện diện và đọc được. Đổi tên, bỏ phần mở rộng, hoặc gửi qua stream thì trong test này nó rơi xuống text/plain. CSV cũng hành xử tương tự trên grid nhỏ được cố tình thiết kế như vậy: text/csv chỉ xuất hiện khi có glob .csv. Nếu đếm theo điều kiện duy nhất, thì Markdown và CSV mỗi loại chỉ được nhận đúng kiểu riêng trong 1/4 điều kiện; còn văn bản thuần vốn đã là text/plain, nên không có gì để “rơi xuống” nữa. Bộ harness 48 lượt raw vẫn hữu ích như một ghi nhận tính lặp lại, nhưng không nên dùng như mẫu số lớn hơn.

Có một điểm Tika làm tốt ở đây: phần mở rộng nói dối cũng không thắng. Fixture Markdown bị đổi tên sang .pdf vẫn trả về text/plain, chứ không phải application/pdf. Tika không tin lời nói dối; nó chỉ không xác nhận được sự thật. Việc hạ xuống type cha là một kiểu thất bại tốt hơn nhiều so với khẳng định sai một cách đầy tự tin, và việc text/markdown là subtype đã được định nghĩa của text/plain khiến fallback này có cơ sở chứ không hề tùy tiện.

Riêng với CSV thì có một lưu ý. Tika có bộ nhận diện CSV theo thống kê, và ở thời điểm parse — được xác nhận qua chuỗi X-TIKA:Parsed-ByTextAndCSVParser — grid nhỏ 2 cột x 3 hàng của tôi lại được nhận là text/plain thay vì text/csv. Đây chỉ là một quan sát trên fixture nhỏ có chủ đích. Một CSV lớn hơn hoặc có dấu ngoặc kép rất có thể sẽ kích hoạt detector. Tôi không nói nhận diện content của CSV bị hỏng; tôi chỉ nói rằng trên grid này, chính phần mở rộng mới là thứ tạo ra text/csv.

Điều này có ý nghĩa gì trong một pipeline upload thực tế

Tình huống điển hình là một bộ điều phối upload. Giả sử bạn nhận file người dùng tải lên và chia luồng theo type: PDF đưa sang bộ parse hóa đơn, spreadsheet đưa sang bộ nhập sổ cái, còn lại đưa vào text index. Nếu bạn tin vào phần mở rộng, một file PDF tên notes.txt sẽ rơi nhầm sang nhánh sai — và đó còn là trường hợp nhẹ; phiên bản xấu hơn là file polyglot với phần mở rộng thân thiện.

Với các fixture binary và markup trong test này, Tika điều phối dựa trên nội dung ngay cả khi tên tệp biến mất, điều này rất hữu ích khi blob store hoặc HTTP body handler đã làm mất thông tin đó. Tuy nhiên, kết quả này không phủ hết “đuôi dài” của Tika, các file mơ hồ, hay file polyglot. Các fixture thuộc nhóm văn bản lại hành xử khác: khi pipeline xóa tên tệp, Markdown và CSV đến nơi dưới dạng text/plain, nên các rule dựa trên media type riêng của chúng sẽ không còn kích hoạt. Hãy giữ tên gốc như metadata đi kèm thay vì trông đợi content detection tự phục dựng nó.

Nội dung được cấy vẫn sống. --text làm phẳng cấu trúc.

Độ trung thực là trục thứ hai, và ở đây nó tách thành hai phần rất rõ. Tôi render một tài liệu canonical (heading, hai đoạn nội dung, một danh sách bullet, một danh sách đánh số, một đoạn kết) sang HTML, Markdown, văn bản thuần, DOCX, PDF, RTF, ODT và XML, rồi thêm một tài liệu bảng sang HTML, Markdown, text, DOCX, CSV và XML. Tổng cộng 14 bản render theo carrier. Mỗi khối đều có một token riêng — zztitle1, zzitem3, zztblcell_beta và tương tự — nên việc “sống sót” hay “bị rớt” được kiểm tra bằng substring chính xác, không phải cảm tính.

Độ nhớ token đánh dấu đạt 1.000 trên cả 14 bản render. Không một token nào bị mất: mọi ô bảng, mục list và heading đã gắn nhãn đều có mặt. Ba lần lặp cục bộ cho mỗi carrier sau warmup cho ra output --text giống hệt từng byte. Bài kiểm tra này không nói gì về ký tự không gắn nhãn, thứ tự, khoảng trắng, chuẩn hóa Unicode, nội dung lặp, link, header, footnote hay object nhúng. Đây là kiểm tra sự hiện diện của block, không phải bằng chứng cho độ trung thực hoàn chỉnh của tài liệu.

Tuy nhiên, đầu ra văn bản phẳng sẽ từ bỏ phần lớn cấu trúc nguồn.

Đây là tài liệu table HTML sau khi đi qua --text:

	Công cụ	Thông lượng

	zztblcell_alpha	120

	zztblcell_beta	95

Các dòng được nối bằng tab. Hàng tiêu đề không được đánh dấu là header. Không có grid, không có ranh giới ô ngoài dấu tab, không có cách nào biết rằng nó từng là một <table>. Bảng trong DOCX cũng phẳng ra y như vậy.

Danh sách thì tinh tế hơn, và chúng tách ra theo đúng thứ mà nguồn thực sự chứa:

Dấu bullet trong nguồn là gìCarrier--text trả về gì
Một ký tự nguyên văn — các bản render này đều viết - thành text thậtvăn bản thuần, Markdown, RTF, ODT, PDFký tự - vẫn còn, vì Tika chỉ truyền nguyên các ký tự qua
Cấu trúc thật — một <li> của HTML, style List Bullet trong DOCXHTML, DOCXmarker biến mất hoàn toàn, chỉ còn text của item: thụt vào bằng tab trong HTML, và một dòng thẳng không trang trí trong DOCX

Tika không bao giờ tự dựng lại một marker mà nó không nhận được dưới dạng text. Cùng nội dung, nhưng đầu ra nhìn rất khác.

Trường hợp Markdown cho thấy điều này rất rõ. Đưa cho Tika một file .md có bảng pipe, các dấu | sẽ được trả lại nguyên văn, khiến nó trông như đã giữ cấu trúc. Nhưng thực ra không phải. Tika chỉ parse nó như text rồi trả bytes lại. Không có gì ở đó hiểu được cái table ấy.

Vì thế, hợp đồng đo lường thực sự hẹp hơn: tất cả token được cấy đều sống sót, nhưng --text không bảo toàn các phần tử có kiểu hay một lưới bảng có thể tái tạo. Gọi đó là lỗi parser thì sẽ bỏ lỡ bản chất. Trích xuất phẳng cố ý tránh bài toán phân loại phần tử; đổi lại nó không thể đáp ứng một consumer ở downstream cần chính những kiểu phần tử đó. Nếu bạn cần block có kiểu hay table được phục dựng, --text chỉ là một mắt xích trong stack, không phải toàn bộ stack. Các handler khác của Tika có thể lộ thêm cấu trúc, nhưng chúng nằm ngoài lần chạy này.

Lưu ý quen thuộc cho mọi con số về fidelity ở đây: chúng đến từ các fixture synthetic được kiểm soát trên một máy, một version, một JDK. Chúng cho thấy các block được gắn nhãn có xuất hiện trong output. Chúng không chứng minh việc bảo toàn từng ký tự hay độ chính xác trên một corpus thực tế đầy nhiễu.

Metadata: đã chuẩn hóa, và đáng mừng là không tự bịa thêm

Biểu đồ kết quả đo: Khôi phục metadata theo từng carrier

Tôi nhúng các giá trị author, title và ngày tạo đã biết vào mọi carrier có lớp metadata, rồi kiểm tra xem thứ gì được trả lại.

Carrierauthor → dc:creatortitle → dc:titlecreated → dcterms:created
HTML (<meta name=author>, <title>)không nhúng
DOCX (core properties)✅ chính xác 2021-03-15T09:30:00Z
PDF (info dict)có, nhưng đó là timestamp do generator tự ghi — không tính điểm
ODT (meta.xml)✅ chính xác 2021-03-15T09:30:00Z
TXT / MD / CSV / RTF / XMLkhông có lớp metadata

Author và title được khôi phục trên 4/4 carrier có metadata, và — đây mới là phần đáng giá — chúng được chuẩn hóa. Một <meta name="author"> trong HTML, một core property của DOCX, một mục /Author trong PDF, và một phần tử dc:creator trong ODT đều cùng xuất hiện dưới khóa dc:creator. Bạn chỉ cần viết một consumer, không phải bốn.

created là phần dao động trung thực. DOCX và ODT trả lại đúng timestamp 2021 mà tôi nhúng. PDF trả về một ngày tạo, nhưng đó là ngày mà thư viện generator ghi lúc build chứ không phải giá trị tôi muốn nhúng — nên tôi chấm là có xuất hiện, chứ không phải đã khôi phục đúng. Còn các định dạng không có lớp metadata thì không hiện gì cả, và đó mới là câu trả lời đúng. Tika không tự đoán author từ phần thân văn bản.

Cố tình phá nó, và mẹo phân loại nhờ đó mà lộ ra

Bốn đầu vào có tính đối kháng. Một file rỗng 0 byte. Một PDF hợp lệ ở phần header nhưng bị cắt mất phần thân. Một file DOCX ZIP bị truncate. Và một file UTF-8 chứa ký tự đa byte nhưng không có BOM lẫn khai báo encoding. Đây là hình dạng fixture cục bộ, không phải ngưỡng chịu đựng của Tika.

Bộ harness cơ sở, các fixture đã tạo, JSON thô, checksum của jar và manifest môi trường không được gắn link trong bản nháp này. Vì thế, người đọc bên ngoài hiện chưa thể tự tái tạo chính xác các mẫu số đó. Hãy xem các bảng dưới đây như các quan sát đã được báo cáo; khi xuất bản, nên kèm một bundle ổn định trước khi dùng các con số này làm bằng chứng bên thứ ba.

Đầu vào--text / --jsonNó ném lỗi gì--detect
File 0 byteexit 1, stdout rỗngZeroByteFileException: InputStream must have > 0 bytesexit 0 → text/plain khi có tên tệp, application/octet-stream từ stream
PDF bị cắt dởexit 1, stdout rỗngTikaException: TIKA-198: Illegal IOException from PDFParserexit 0 → application/pdf
DOCX bị cắt dởexit 1, stdout rỗngPOI FATAL: "XML document structures must start and end within the same entity"exit 0 → type OOXML
UTF-8, không BOM, không khai báoexit 0không có gìexit 0 → text/plain, charset UTF-8

Trích xuất sẽ fail rất rõ ràng, và các lỗi này có hình dạng bên ngoài giống nhau. File rỗng 0 byte, PDF bị truncate và DOCX bị truncate đều tạo ra exception, exit 1, và stdout rỗng. CLI không nuốt lỗi để biến nó thành một kết quả rỗng gọn gàng. Trong các trường hợp này, chương trình vẫn an toàn — không treo, không segfault — nhưng caller phải kiểm tra exit status và stderr chứ không thể chỉ nhìn vào chuỗi rỗng.

Nhận diện được tách rời khỏi parse. Trên cả hai file nhị phân bị truncate, --detect vẫn trả về exit 0 với type đúng từ phần đầu còn nguyên; sau đó parser mới fail ở phần thân hỏng. Vì vậy, một pipeline có thể dùng detect như một tín hiệu phân loại riêng trước hoặc sau khi parse thất bại. Việc detect-first có nên là mặc định hay không còn tùy chế độ triển khai: test này không benchmark detect-first so với parse-only, và việc khởi tạo thêm hai CLI JVM mới có thể là đánh đổi không đúng ở quy mô lớn.

Nhận diện charset hoạt động. File UTF-8 không BOM, không khai báo được decode đúng là UTF-8 và 日本語テスト đi qua nguyên vẹn. Một lưu ý nhỏ cho ai đọc metadata dict: các fixture ASCII thuần của tôi báo charset=ISO-8859-1, điều này không thể phân biệt với UTF-8 khi chỉ có byte ASCII. Đó không phải là sai, mà là hòa.

Tika đặt cạnh unstructured: cùng loại file, khác nhiệm vụ

Cả hai đều được test trong cùng một phiên nghiên cứu, nhưng đây là bảng phân loại output contract chứ không phải một benchmark đối xứng. Hai công cụ được chấm trên những kết quả khác nhau.

Bài viết liên quan: Đánh giá Unstructured.

Apache Tikaunstructured
Tôi đo nó trên cái gìđộ trung thực nội dung: có gì bị mất không?độ chính xác phân loại phần tử: mỗi block có được gán đúng kiểu không?
Kết quảtất cả marker được cấy đều xuất hiện trên cả mười bốn bản rendertrong bài test phân loại riêng, một table văn bản thuần cho ra recall Table bằng 0.000, và một heading chứa động từ bị phân loại thành narrative text
Phần tử có kiểu được trả vềkhông có — không có cấu trúc nào được trả lạiTitle, NarrativeText, ListItem, Table — đúng thứ mà Tika không làm
OCRbị chặn trên máy của tôi vì thiếu tesseractbị chặn trên máy của tôi vì thiếu tesseract

Đầu ra phẳng giữ marker so với các phần tử có kiểu nhưng có lỗi phân loại quan sát được. Hãy chọn theo nhu cầu của consumer downstream. Nếu đó là search index hoặc cửa sổ context của LLM, văn bản phẳng có thể đã đủ. Nếu consumer dựa vào element type, đường --text của Tika không thể cung cấp hợp đồng đó.

Chúng tôi cũng không có số liệu cho tài liệu scan.

Ưu và nhược điểm

Ưu điểm

  • Nhận diện content-type bỏ qua các tên tệp nói dối trong 20/20 điều kiện logic duy nhất trên năm fixture có thể nhận diện bằng nội dung; các lượt stream lặp lại cũng cho kết quả khớp.
  • Mọi token được cấy đều sống sót trong cả 14 bản render theo carrier, bao gồm cả các ô table và mục list đã gắn nhãn.
  • Có thể lặp lại ổn định trong ba lần chạy lại cục bộ: mỗi carrier trả về text giống hệt từng byte trong môi trường này.
  • Metadata được chuẩn hóa giữa các định dạng — dc:creator / dc:title / dcterms:created bất kể định dạng nguồn, khôi phục được trên 4/4 carrier có metadata.
  • Thực sự gần như không phụ thuộc cho các định dạng tôi test: text layer PDF, DOCX, ODT, RTF, HTML đều parse từ một jar mà không cần binary bên ngoài.
  • Chạy ngon trên OpenJDK 26 — không bị ràng buộc chỉ dùng LTS.
  • Detection vẫn đúng (exit 0) trên binary bị truncate, cho bạn một tín hiệu phân loại đáng tin khi parse thất bại.
  • Apache-2.0, trưởng thành, được duy trì tích cực.

Nhược điểm

  • Markdown và CSV phụ thuộc hoàn toàn vào phần mở rộng; 10/18 ô không có chữ ký đã rơi về text/plain khi tên tệp bị mất hoặc sai.
  • --text không trả về element type; lưới table bị làm phẳng thành các dòng nối tab và marker cấu trúc của list biến mất.
  • Extraction sẽ ném lỗi không được bắt ở file rỗng và file hỏng; hai trường hợp này nhìn từ riêng lời gọi extract thì giống hệt nhau.
  • Jar 67 MB cộng với cold start JVM cho mỗi lần chạy ở chế độ CLI.
  • OCR và PDF scan chỉ chứa ảnh hoàn toàn không được test ở đây — thiếu tesseract và poppler, nên tôi không đưa ra bất kỳ khẳng định nào về nhánh đó.
  • Mọi con số ở đây đều là ground truth synthetic trên một máy, một version. Độ chính xác trên corpus thực, file mã hóa, tài liệu nhúng/đệ quy, và throughput ở quy mô lớn đều chưa được đo.

Ai nên dùng, và ai không nên

Tika phù hợp khi đầu vào của bạn là những file đã có sẵn và đầu ra cần là văn bản cùng metadata mà máy có thể index. Search indexing, e-discovery, xử lý kho lưu trữ, đưa corpus vào LLM, xây lớp kiểm tra content-type cho pipeline upload. Nó rất hữu ích như một bước triage và chuẩn hóa ban đầu đứng trước một thành phần thông minh hơn: nhận diện các type đã test, trích xuất flat text, rồi chuyển tiếp cùng các kiểm tra rõ ràng cho phần nội dung mà pipeline của bạn không thể đánh mất.

Hãy bỏ qua nó — hoặc đúng hơn, đừng dừng ở --text — nếu bạn cần phần tử có kiểu, table được phục dựng, hay bố cục tài liệu. Cũng nên bỏ qua nếu tài liệu của bạn là bản scan, ít nhất cho đến khi bạn cài tesseract và tự chạy số liệu của mình, vì tôi không có gì để cung cấp ở phần đó. Với công việc ở quy mô lớn, hãy benchmark library hoặc server mode so với CLI trên tài liệu đại diện. Trong harness file nhỏ này, thời gian khởi tạo process là thấy rõ, nhưng thông lượng và chi phí tài nguyên thì chưa được đo.

Điều dễ làm người ta vấp: nếu lớp lưu trữ của bạn xóa tên tệp và bạn xử lý Markdown hoặc CSV, đừng trông chờ Tika phân biệt chúng với văn bản thuần. Hãy giữ tên gốc.

Lựa chọn thay thế, và Thunderbit đứng ở đâu

Cần công bằng trước, vì so sánh thật sự ở đây là về đầu vào, không phải chất lượng. Tika là một toolkit tự host miễn phí, giấy phép Apache-2.0, dùng để parse file. Những file bạn đã có trên đĩa hoặc trong bucket. Nó không đi fetch trang web, không chạy JavaScript, không xử lý anti-bot, và cũng không giả vờ làm thế.

Đó chính là ranh giới mà một dịch vụ trích xuất web được quản lý, trong đó có Thunderbit của chúng tôi, có thể bước vào kiến trúc: nó fetch các trang trực tiếp, trong khi Tika parse những file đã nằm trong tay bạn. Bài viết này không benchmark các dịch vụ đó so với Tika, và chúng không phải là vật thay thế cho cùng một kiểu đầu vào.

Sự phân tách rõ ràng là: dùng Tika cho tài liệu bạn đã có, còn dùng API trích xuất được quản lý cho các trang web bạn cần đi lấy về. Nhiều pipeline chạy cả hai — crawl và extract phía web, Tika cho các file PDF và DOCX đính kèm được trả về.

Nếu bạn đang so sánh trên bức tranh open-source rộng hơn, tôi cũng có bài so sánh đầy đủ các scraper mã nguồn mở, một bài tổng hợp về những dự án scraping hữu ích nhất trên GitHub, một bài đánh giá Crawl4AI thực hành về cách tiếp cận Markdown dựa trên browser, và một tổng hợp rộng hơn về các công cụ scraping. Với hướng no-code, còn có một bài hướng dẫn cách scrape một website bằng AI.

Dùng thử Thunderbit cho trích xuất dữ liệu web

Kết luận

Có nên dùng Apache Tika không? Có, nếu công việc của bạn là biến các file hỗn hợp thành văn bản phẳng và metadata đã chuẩn hóa, và bạn có bước kiểm tra các field hoặc marker mà pipeline của bạn không thể đánh mất.

Phần mạnh nhất của lần test này là bộ detector. Nó trả đúng type trong 20/20 điều kiện logic duy nhất đối với năm fixture có thể nhận diện bằng nội dung, kể cả các stream không có tên tệp. Mọi token được cấy đều sống sót qua mười bốn bản render, và output lặp lại từng byte trong ba lần chạy lại cục bộ. Đó là bằng chứng hữu ích. Nhưng vẫn là bằng chứng synthetic. Việc làm tất cả từ một jar trên JDK này, không dùng binary bên ngoài cho các đường không phải OCR đã test, khiến triển khai khá gọn gàng và ít drama.

Tuy nhiên, hãy hiểu đúng giới hạn. Mỗi table đưa vào sẽ quay ra thành các dòng nối bằng tab. Mỗi marker cấu trúc của list đều biến mất. Markdown và CSV mất bản sắc ngay khi tên tệp mất đi. File rỗng và file hỏng đều ném ra cùng một dạng lỗi, và bạn sẽ cần một lệnh detect riêng để phân biệt chúng. Còn về OCR, thứ mà nhiều người dùng Tika quan tâm nhất, tôi không có gì để đưa ra: tôi không chạy được nó, và tôi sẽ không đoán.

Trong những giới hạn đó, Tika làm một công việc khá tẻ nhạt nhưng lại đáng tin một cách bất thường. Nó đọc bytes, chứ không đọc nhãn dán trên hộp. Chỉ đừng bắt nó nói hình dạng ban đầu của các bytes đó là gì.

Dùng thử Thunderbit cho trích xuất dữ liệu web Get Started Free

Câu hỏi thường gặp

Apache Tika có nhận diện đúng loại tệp nếu phần mở rộng sai không? Với năm fixture có thể nhận diện bằng nội dung trong bài test này, có. PDF, DOCX, RTF, HTML và XML đều được gán đúng media type trong cả 20 điều kiện logic duy nhất (30 lượt chạy raw với các stream lặp lại), kể cả khi đuôi gây hiểu nhầm, không có đuôi, và stream không có tên tệp. Một file PDF đặt tên .txt vẫn được nhận là application/pdf. Markdown và fixture CSV nhỏ lại phụ thuộc vào thông tin tên tệp và rơi về text/plain khi nó bị thiếu hoặc sai.

Tika có giữ lại bảng và cấu trúc tài liệu không? Không phải trong chế độ --text mà tôi test ở đây. Lưới table quay về thành các dòng nối tab, không còn ngữ nghĩa cell hay header, và các marker cấu trúc của list (một <li> của HTML, style List Bullet trong DOCX) biến mất. Tất cả token được cấy đều sống sót trên cả 14 bản render theo carrier, nhưng điều đó không chứng minh toàn bộ nội dung được bảo toàn hoàn chỉnh, và --text cũng không cung cấp phân loại element. Nếu cần element có kiểu hoặc table được phục dựng, hãy test một handler đầu ra khác của Tika hoặc dùng thêm công cụ khác.

Apache Tika có OCR cho PDF scan không? Tika có hỗ trợ OCR thông qua Tesseract, nhưng tôi không test phần đó, và mọi kết quả ở đây không phải là khẳng định cho nhánh này. Máy test của tôi không có Tesseract và poppler, nên mọi đường OCR và ảnh scan đều bị chặn trước khi chạy. Không có số liệu OCR nào trong toàn bộ bài test này. Nếu OCR là nhu cầu của bạn, hãy cài tesseract và benchmark riêng — hãy xem phần đó của Tika là chưa được xác minh ở đây.

Tika xử lý file rỗng hoặc file hỏng thế nào? Nó fail rất rõ ràng chứ không âm thầm. File 0 byte ném ZeroByteFileException; PDF bị truncate ném TikaException từ PDFParser; DOCX bị truncate ném lỗi XML của POI. Cả ba đều exit 1 với stdout rỗng, nên chỉ nhìn riêng lời gọi extract thì file rỗng và file hỏng không thể phân biệt. Tuy nhiên, detection vẫn ổn định — --detect trả exit 0 với type đúng trên cả hai binary bị truncate, nên đây là một bước triage đáng tin trước khi bạn tốn công parse.

Bài test Tika này không bao phủ những gì? Bốn thứ, nói rõ ràng. OCR và ảnh scan (bị chặn, chưa test). Độ chính xác trên corpus thực — tất cả kết quả đều là fixture synthetic có token được cấy, đo độ trung thực so với nhãn đã biết chứ không phải độ chính xác trên tài liệu thực đầy nhiễu. Chi phí tài nguyên, thông lượng và peak memory, vì tôi chưa đo. Và “đuôi dài” của tuyên bố “một nghìn loại tệp” — tôi chỉ test chín định dạng tiêu biểu, không phụ thuộc bên ngoài, chứ không phải toàn bộ catalog. Tất cả những gì ở đây là Tika 3.3.2 trên OpenJDK 26.0.1, macOS arm64, một máy duy nhất.

Ke
Ke
CTO tại Thunderbit | Chuyên gia Khoa học Dữ liệu cấp cao & ML Với gần một thập kỷ kinh nghiệm trong học máy và khoa học dữ liệu, Ke Shen là cựu sinh viên Đại học Columbia và từng là Chuyên gia Khoa học Dữ liệu cấp cao tại Walmart Labs. Sở hữu chuyên môn sâu về Python, R, Java và Thống kê, được đồng nghiệp công nhận, anh chia sẻ những góc nhìn thực chiến về cách đưa các thuật toán AI phức tạp từ lý thuyết vào kiến trúc sẵn sàng cho môi trường sản xuất.
Mục lục
Thunderbit · Tác nhân dữ liệu web AI

Trích xuất dữ liệu từ bất kỳ trang nào trong 1 lần nhấp

Được hơn 250.000+ người dùng tin tưởng
có gói miễn phí
Từ trang web đến bảng tính
Mô tả điều bạn cần — AI Agent của Thunderbit sẽ cào dữ liệu và xuất ra Excel, Google Sheets, Airtable hoặc Notion. Bắt đầu miễn phí.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week