Apache Tika 评测:它看字节,不看文件名——直到遇上 Markdown

最后更新于 August 19, 2026
Apache Tika 评测:它看字节,不看文件名——直到遇上 Markdown
AI 摘要

Apache Tika 是 Apache 软件基金会推出的文档解析工具箱:把几乎任何类型的文件丢给它,它就会返回纯文本以及一份标准化的元数据字典。项目 README 声称它支持上千种文件类型,而 Tika 的做法是把各类专门库直接打包进去——PDF 用 PDFBox,Office 文档用 Apache POI,HTML 用 jsoup,ODT 用 ODF 读取器——所以整个项目以一个单独的大型 jar 形式发布,解析时不需要再去拉取其他依赖。在数据流水线里,它通常是最不起眼的第一步:站在搜索索引、电子取证审阅集或 LLM 语料库前面,把一堆五花八门的文件统一成同一种可处理的形态。

Apache Tika 是 Apache 软件基金会推出的文档解析工具包:你把几乎任何类型的文件丢给它,它都能返回纯文本,以及一份规范化的元数据字典。项目 README 声称它支持上千种文件类型,而 Tika 的实现方式是把各类专用库直接打包进来——PDF 用 PDFBox,Office 文档用 Apache POI,HTML 用 jsoup,ODT 用 ODF reader——所以最终会以一个单独的胖 JAR 形式发布,解析时不需要再额外下载任何依赖。放到数据管道里,它就是那个不太显眼、但又不可或缺的第一环:站在搜索索引、电子取证审查集或 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。其实它不是,越早弄清这一点,越能看出这个工具的价值。

本次测试关注的路径有三个关键阶段:内容类型检测器、把字节交给正确解析器的 分发器,以及 CLI 的 --text 输出处理器,它会输出扁平文本,并把元数据单独提供出来。在这个输出契约里,没有 Title 对象,没有 ListItem,也不会重建表格网格。Tika 还提供了其他处理器和 API,包括面向 XHTML/SAX 的输出;我没有测试那些。因此,下面所有关于结构的结论,都只针对 tika-app --text,并不意味着工具在任何地方都没有结构化事件流。

听起来像是一个限制,而且从某个角度看确实如此。但这也意味着 Tika 没有“误判结构”的空间,而这恰恰是许多更复杂工具反过来要承担的代价。

检测本身遵循文档里定义好的顺序:先看签名字节,再检查 XML 根节点,然后匹配文件名模式,最后才考虑你自己指定的类型(Tika 自己的检测文档 有完整说明)。只有类型解析完毕后,分发器才会把字节交给对应的内置解析器——PDFBox、POI、jsoup,以及文本家族对应的 TextAndCSVParser

这种“先检测、后解析”的拆分不是内部八卦。它解释了为什么一个已经坏到无法解析的文件,仍然可能被正确识别类型;而一旦文件出问题,这反而成了 Tika 最实用的能力之一。

环境搭建:一个 JAR,一条命令,还有一套不挑食的 JVM

安装过程就是下载而已。Maven Central 上的 tika-app-3.3.2.jar 大约 67 MB——一个把所有解析器都打包进去的胖 JAR——之后直接跑 java -jar tika-app-3.3.2.jar --text file.pdf 就行。没有配置文件,没有模型权重,没有安装后步骤,也不用一路折腾 brew install

JDK 兼容性这件事倒是让我有点意外。我在 OpenJDK 26.0.1 上完整跑了这套测试,这是一个前沿的非 LTS 构建,而 --version--text--metadata--detect 全都以退出码 0 正常返回,没有任何兼容性抱怨。之所以特别点名这一点,是因为我在同一台机器上同一时间测试 Apache Nutch 时,它的爬取流程在 JDK 26 上根本跑不起来——由于新版本 JDK 移除了 SecurityManager,它要求 21 或更低的 LTS 版本。Tika 没受影响。如果你一直因为这类 JVM 历史包袱而回避 Java 工具链,Tika 不是让你头疼的那个。

不过,环境搭建方面也有两个必须如实说明的点。CLI 每次调用都会启动一个新的 JVM,所以冷启动成本是真实存在的——我的测试框架总共执行了 131 次调用,主要时间都花在 JVM 热身上。如果你要大批量处理文件,应该用库模式或服务模式,而不是在 shell 里循环调用 JAR。另一个边界是“无需外部依赖”这件事有明确前提:PDF 的文本层提取不需要外部程序,但 OCR 需要 tesseract 和 poppler。 在没有安装这两个工具的机器上,文本层 PDF、DOCX、ODT、RTF、HTML、XML、TXT、Markdown、CSV 都可以正常解析;扫描文档则不会,我也没有假装自己测过。

这点和我同一天测的另一个库 unstructured 对比会更明显:它的电子 PDF 路径在导入 PDF 模块时就会拉起推理栈(torch 等依赖),是在策略分发之前加载的,所以即使是“fast”策略也无法在缺少这些依赖时导入。Tika 则直接用一个普通的 java -jar 就把同一个 PDF 的文本层解析出来了。

撒谎扩展名测试:Tika 的 MIME 类型识别不看文件名

Measured results chart: Type detection across filename conditions

八种格式,每种都分别提供了正确扩展名、故意错误的扩展名或没有扩展名,再加上一条在 stdin 上输入的无文件名字节流。这一共是 32 个唯一逻辑条件。原始测试框架还把相同的流字节在每个文件名标签下各跑了一次,总计 48 次原始执行;但那三条流记录本质上都算同一个条件,因为 stdin 不携带文件名。

样本实际类型改名为正确扩展名错误扩展名无扩展名原始流,无文件名
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 有可识别的头部,DOCX 是基于 ZIP 的容器,而 HTML/XML 则可以通过标记或根内容识别。在这些样本里,撒谎的扩展名没有赢。

再看文本家族。Markdown 只有在 .md 扩展名存在且可读取时,才会被解析为 text/markdown。把它改名、去掉扩展名,或者直接以流的形式输入,这次测试里它都会退化成 text/plain。CSV 在这张刻意做得很小的测试网格里表现相同:只有通过 .csv glob 才会得到 text/csv。按唯一条件计算,Markdown 和 CSV 各自只在四个条件中的一个里被识别为专属类型;纯文本本来就是 text/plain,所以也不存在“退化”这一说。48 次原始运行的意义主要在于说明结果可重复,而不是扩大分母。

这里有一点对 Tika 是加分项:撒谎的扩展名也没有“获胜”。 我的 Markdown 样本改名成 .pdf 后返回的是 text/plain,而不是 application/pdf。Tika 没有相信谎言,只是无法确认真相。退回到父类型是一种比“自信地给出错误类型”好得多的失败方式,而且 text/markdown 本身就是 text/plain 的已定义子类型,因此这种回退是有依据的,不是随便拍脑袋。

不过,CSV 这里有一个需要单独说明的例外。Tika 也有统计型 CSV 检测器,而在解析阶段——从 X-TIKA:Parsed-By 链里出现 TextAndCSVParser 就能确认这一点——我这个 2 列 x 3 行的小网格被解析成了 text/plain,而不是 text/csv。这只是对一个刻意做得很小的样本的单次观察。更大一些,或者带引号的 CSV,很可能会触发检测器。我不是在说 CSV 内容检测坏了;我是说,在这个网格上,是扩展名决定了 text/csv

这对真实上传管道有什么意义

一个很现实的场景是上传路由。假设你接收用户上传,并按类型分流:PDF 走发票解析器,表格文件走账本导入器,其余都进文本索引。如果你只信扩展名,那么一个把 PDF 命名成 notes.txt 的文件就会被送进错误分支——这还只是温和情况;更糟的是带着友好扩展名的 polyglot 文件。

对于这里测试的二进制和标记类样本,Tika 即使在文件名消失后也依然按内容路由,这在对象存储或 HTTP 请求体处理器丢掉文件名时特别有用。不过,这个结果并不覆盖 Tika 的长尾格式、歧义文件或 polyglot 文件。测试过的文本家族样本则表现不同:当管道去掉文件名后,Markdown 和 CSV 都被当成 text/plain,因此依赖具体媒体类型的规则就不会再触发。最好把原始文件名当作旁路元数据保留下来,而不是指望内容检测能把它“猜回来”。

植入的内容都保住了,但 --text 把结构压平了

保真度是第二个维度,而且它分得很清楚。我把一份标准文档(包含标题、两段正文、一个无序列表、一个有序列表和结尾段落)分别渲染成 HTML、Markdown、纯文本、DOCX、PDF、RTF、ODT 和 XML;另外又把一份表格文档渲染成 HTML、Markdown、文本、DOCX、CSV 和 XML。总共十四种载体渲染。每个块都带有唯一 token——比如 zztitle1zzitem3zztblcell_beta 等——因此“保住了”还是“丢掉了”可以直接用子串检查精确判断,而不是主观感受。

所有十四种渲染的标记 token 召回率都是 1.000。 没有任何植入 token 丢失:每个带标记的表格单元格、列表项和标题都还在。每种载体在热身后重复本地运行三次,得到的 --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 的案例把这个问题说明得很清楚。给 Tika 一个带 pipe table 的 .md 文件,管道符会原样返回,看起来像是保留了结构。其实不是。Tika 只是把它当文本解析后又把字节吐回来了,没人真正理解那张表。

所以,测出来的契约其实更窄:所有植入标记都保住了,但 --text 并没有保留带类型的元素,也没有重建出可还原的表格网格。 把这说成解析器缺陷并不准确。扁平提取本来就刻意绕开了元素分类问题;与此同时,它也无法满足那些需要元素类型的下游消费者。如果你需要带类型的块或重建后的表格,--text 只是整条链路中的一环,而不是整条链路本身。Tika 的其他处理器可能会暴露更多结构,但它们不在本次测试范围内。

关于这里所有保真度数字,都要附带一个统一说明:它们来自一台机器、一个版本、一个 JDK 下的受控合成样本。它们能说明这些带标签的块在输出中存在,但不能证明在真实、混乱的语料上逐字逐字符都完全正确。

元数据:规范化,而且很少胡编乱造

Measured results chart: Metadata recovery by carrier

我把已知的作者、标题和创建时间写进了所有带元数据层的载体里,然后查看它们是否被取回。

载体author → dc:creatortitle → dc:titlecreated → dcterms:created
HTML(<meta name=author><title>未嵌入
DOCX(核心属性)✅,精确到 2021-03-15T09:30:00Z
PDF(info 字典)有,但那是生成器自己写入的时间戳——不计分
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 键返回。你只需要写一个消费者,不用为四种格式分别写四套。

created 的表现就更诚实地有点波动了。DOCX 和 ODT 返回了我嵌入的精确 2021 时间戳。PDF 也返回了一个创建日期,但那是生成器库在构建时写进去的日期,不是我想嵌入的值——所以我把它记为“存在”,而不是“被恢复”。没有元数据层的格式则什么都没返回,这才是正确答案。Tika 不会从正文里硬猜一个作者出来。

故意把它搞坏,然后看看能不能顺手得到一个分流技巧

四种恶意输入:零字节文件、头部有效但主体被截断的 PDF、截断的 DOCX ZIP,以及一个带多字节字符、没有 BOM 也没有编码声明的 UTF-8 文件。这些都是本地样本形态,不是 Tika 的边界阈值。

底层测试框架、生成的样本、原始 JSON、JAR 校验和以及环境清单都没有在这里公开链接,所以外部读者无法独立复现完全相同的分母。请把这些表格当作已报告的观察结果,而不是可由第三方直接验证的证据。

输入--text / --json抛出的错误--detect
0 字节文件退出码 1,stdout 为空ZeroByteFileException: InputStream must have > 0 bytes退出码 0 → 带文件名时为 text/plain,从流输入时为 application/octet-stream
截断的 PDF退出码 1,stdout 为空TikaException: TIKA-198: Illegal IOException from PDFParser退出码 0 → application/pdf
截断的 DOCX退出码 1,stdout 为空POI 致命错误:"XML document structures must start and end within the same entity"退出码 0 → OOXML 类型
UTF-8,无 BOM,未声明编码退出码 0退出码 0 → text/plain,charset UTF-8

提取会明确失败,而且这些失败在外观上很像。 零字节文件、截断 PDF 和截断 DOCX 都会抛出异常、返回退出码 1,且 stdout 为空。CLI 不会把失败悄悄吞成一个干净的空结果。它们在进程层面是安全的——不会卡死,也不会段错误——但调用方必须检查退出状态和 stderr,不能只盯着空字符串。

检测与解析是解耦的。 在两个截断二进制文件上,--detect 都以退出码 0 返回了从完整头部内容推断出的正确类型;然后解析器才在损坏主体上失败。因此,管道可以把检测作为单独的分流信号,在失败解析前后都能用。是否应该默认先 detect 再 parse,取决于部署方式:这次测试没有比较 detect-first 和 parse-only 的性能,而且在大批量场景里,两个新的 CLI JVM 可能反而不是最优选择。

字符集检测是工作的。 那个没有 BOM、也没有声明编码的 UTF-8 文件被正确按 UTF-8 解码,日本語テスト 原样通过。给读元数据字典的人一个小提醒:我那些纯 ASCII 样本都报告 charset=ISO-8859-1,但在 ASCII 字节上它和 UTF-8 没区别。这不是失误,只是平局。

把 Tika 和 unstructured 放在一起:同样的文件类型,不同的职责

这两个工具是在同一次研究会话里测试的,但这更像是输出契约的分类,而不是对称的性能对比。它们测的结果本来就不一样。

相关评测:Unstructured 评测

Apache Tikaunstructured
我衡量的对象内容保真度:有没有东西丢失?元素分类保真度:每个块有没有被分对类型?
结果在十四种渲染里,所有植入标记都存在在单独的分类测试中,一个纯文本表格的 Table 召回率为 0.000,其中一个包含动词的标题被分成了 narrative text
返回的带类型元素没有——完全不返回结构TitleNarrativeTextListItemTable——这正是 Tika 不打算做的事
OCR由于缺少 tesseract,在我的机器上无法运行由于缺少 tesseract,在我的机器上无法运行

扁平、保留标记的输出 vs. 带类型元素但存在分类误差。到底选哪个,要看下游消费者需要什么。如果是搜索索引或 LLM 的上下文窗口,扁平文本可能就够了;如果它依赖元素类型,那 Tika 的 --text 路径就无法提供这种契约。

我们都没有扫描文档的数据。

优点和缺点

优点

  • 在五种可通过内容识别的样本上,内容类型检测在 20/20 个唯一条件中都无视了错误文件名;重复的流执行结果也一致。
  • 所有 14 种载体渲染中,植入标记都完整保留,包括带标记的表格单元格和列表项。
  • 在本地重复运行三次都能稳定复现:同一环境下,每种载体输出的文本字节完全一致。
  • 跨格式的元数据是规范化的——无论源格式如何,都会映射到 dc:creator / dc:title / dcterms:created,并且在 4/4 个带元数据层的载体上成功恢复。
  • 对我测试的这些格式来说,确实可以做到无外部依赖:PDF 文本层、DOCX、ODT、RTF、HTML 都能只靠一个 JAR 解析。
  • 在 OpenJDK 26 上运行正常——没有 LTS 限制。
  • 即使遇到截断二进制文件,检测也能保持正确(退出码 0),在解析失败时给你一个可靠的分流信号。
  • Apache-2.0,成熟,维护活跃。

缺点

  • Markdown 和 CSV 的识别完全依赖文件扩展名;一旦文件名丢失或错误,18 个无签名字节格里有 10 个退化成了 text/plain
  • --text 不返回元素类型;表格会被压平成制表符连接的行,结构化列表标记也会消失。
  • 对空文件和损坏文件会直接抛错;仅凭提取调用本身,这两种情况看起来一样。
  • CLI 模式下,67 MB 的 JAR 以及每次调用都要启动 JVM 的冷启动成本都摆在那儿。
  • 这里完全没有测试 OCR 和扫描图片 PDF——由于缺少 tesseract 和 poppler,我无法对那条路径做任何判断。
  • 这里的所有数字都是在一台机器、一个版本上的合成真值。真实语料准确率、加密文件、嵌套/递归文档以及规模化吞吐都没有测。

谁应该用,谁不该用

如果你的输入是已经拿到手的文件,而输出需要的是可供机器索引的文本加元数据,那 Tika 就很合适。搜索索引、电子取证、档案处理、把语料喂给 LLM、构建上传管道里的内容类型校验层——它适合作为前置的分流和标准化步骤,站在更智能组件之前:先识别本次测试覆盖的类型,抽出扁平文本,再把结果连同那些你不能丢的内容检查一起传下去。

如果你需要的是带类型的元素、重建后的表格或文档版式,那就别把 --text 当成终点;或者更准确地说,别只停在 --text。如果你的文档是扫描件,也先别用,至少要等你装上 tesseract 并自己跑出数据,因为我这里没有。做大规模处理时,最好把库模式或服务模式和 CLI 在代表性文档上做基准测试。在这个小文件测试里,进程启动是能看见的,但吞吐和资源成本都没有量化。

还有一个最容易踩坑的点:如果你的存储层会剥离文件名,而你又在处理 Markdown 或 CSV,别指望 Tika 能把它们和纯文本区分开。把原始文件名保存下来。

备选方案,以及 Thunderbit 的位置

先把边界说清楚,因为这里最诚实的对比其实是关于输入,不是关于质量。Tika 是一个免费、Apache-2.0、自托管的文件解析工具。输入是你磁盘上或存储桶里的文件。它不会抓网页,不会执行 JavaScript,不会处理反爬,也从来没假装会。

这就是像我们自己的 Thunderbit 这样的托管网页提取服务可能进入架构的边界:它负责抓取实时网页,而 Tika 负责解析你已经拿到手的文件。本文没有把这些服务和 Tika 做基准对比,而且它们也不是同一种输入的替代品。

最清晰的分工就是:Tika 处理你已经持有的文档,托管提取 API 负责把你需要的网页抓回来。很多管道两者都会一起用——网页侧负责爬取和提取,返回来的 PDF 和 DOCX 附件则交给 Tika。

如果你想从更广义的开源生态做比较,我还写过一篇完整的开源爬虫对比、一篇关于 GitHub 上最有用的爬虫项目的盘点、一篇动手实测的 Crawl4AI 评测(重点讲浏览器驱动的 Markdown 路线),以及一篇更广泛的爬虫工具综述。如果你偏好无代码方案,也可以看看这篇如何用 AI 抓取网站的实操指南。

试用 Thunderbit 进行网页数据提取

结论

要不要用 Apache Tika?如果你的工作是把杂乱文件转成扁平文本和规范化元数据,而且你会自己校验那些不能丢的字段或标记,那答案是:要。

这次测试里最强的部分是检测器。对于五种可通过内容识别的样本,它在 20 个/20 个唯一条件下都返回了预期类型,包括无文件名流。所有植入标记在十四种渲染中都保住了,而且输出在三次本地重复运行中逐字节一致。证据很有用,但依然是合成证据。用一个 JAR 在这台 JDK 上完成,而且非 OCR 路径不需要外部二进制文件,让部署过程意外地平静。

但它也要放在正确的位置。你喂给它的每张表都会回来一串制表符连接的行。每个结构化列表标记都会消失。Markdown 和 CSV 一旦文件名没了,身份就没了。空文件和损坏文件会抛出同一种失败,而要区分它们,你还得单独调用 detect。至于很多 Tika 用户最关心的 OCR,我这里没有结论:我没法跑,也不会瞎猜。

在这些边界之内,Tika 做的是一件不花哨但非常可靠的工作。它读的是字节,不是盒子上的标签。只是别让它告诉你这些字节原来是什么形状。

试用 Thunderbit 进行网页数据提取 Get Started Free

常见问题

如果文件扩展名是错的,Apache Tika 还能正确识别文件类型吗? 在这里测试的五种可通过内容识别的样本上,答案是可以。PDF、DOCX、RTF、HTML 和 XML 在全部 20 个唯一逻辑条件中都解析成了预期的媒体类型(如果把重复的流运行也算上,则是 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,但我没有测试,而且这里的任何结果都不代表对 OCR 的结论。 我的测试主机上没有安装 Tesseract 和 poppler,所以所有 OCR 和扫描图片路径在运行前就被挡住了。这次测试里没有任何 OCR 数据。如果 OCR 正是你的场景,请自己安装 tesseract 再做基准测试——把那部分 Tika 视为这里未验证。

Tika 会怎么处理空文件或损坏文件? 它会明确报错,而不是悄悄吞掉。0 字节文件会抛出 ZeroByteFileException;截断的 PDF 会从 PDFParser 抛出 TikaException;截断的 DOCX 会触发 POI 的 XML 错误。这三种情况都会以退出码 1 结束,stdout 为空,所以仅凭提取调用本身,空文件和损坏文件是分不出来的。不过检测仍然很稳——在这两个截断二进制文件上,--detect 都以退出码 0 返回了正确类型,因此在真正解析之前,它是一个可靠的分流步骤。

这次 Tika 测试没有覆盖什么? 明确有四项。OCR 和扫描图片(被阻断,未测试)。真实语料准确率——所有结果都是带植入标记 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 次点击 内提取任意页面的数据

25 万+ 用户信赖
提供免费方案
从网页到表格
描述你需要的内容——Thunderbit 的 AI Agent 会帮你抓取并导出到 Excel、Google Sheets、Airtable 或 Notion。免费即可开始。
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week