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

最后更新于 August 14, 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 读取器——所以整个项目以一个单独的大型 jar 形式发布,解析时不需要再去拉取其他依赖。在数据流水线里,它通常是最不起眼的第一步:站在搜索索引、电子取证审阅集或 LLM 语料库前面,把一堆五花八门的文件统一成同一种可处理的形态。说到底,它做两件事:先判断一段字节流“是什么”,再把其中的文本和元数据提取出来。

这是我最近搭过的、最省心的工具之一。一个 jar 文件,java -jar tika-app-3.3.2.jar --text file.pdf,不需要配置文件,不需要模型权重,也不用安装后再做额外处理;而且它还能在一个前沿版 JDK 上正常运行——同一天里,其他 Java 工具在这台机器上都直接停摆了。虽然目录里写着支持海量格式,但这并不是我真正想验证的点;更值得测试的问题其实更窄:当输入“撒谎”时,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 构建形式存在。 同一天我看到这个项目在 GitHub 上大约有 3.9k 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.jar67 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,它的抓取流程在 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 的文本层。

伪装文件名测试:无视你给文件起的名字,它照样识别 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

(流式这一列会把三种扩展名条件合并起来,因为没有文件名时,通配规则根本没有东西可读。)

那五种可以靠内容识别的格式——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 的通配规则会给出 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 列 × 3 行表格最终被识别成了 text/plain,而不是 text/csv。这只是一个在极简样本上的单点观察。更大、带引号的 CSV 很可能会触发检测器。我并不是说 CSV 内容检测坏了;我只是说,在这张网格上,是扩展名决定了 text/csv

为什么这件事在真实上传流程里很重要

最典型的场景就是上传路由。假设你允许用户上传文件,并按类型分流:PDF 进发票解析器,电子表格进账本导入器,其余文件进文本索引。如果你相信扩展名,那么一个名为 notes.txt 的 PDF 就会进错分支——而这还算是温和情况;更坏的情况,是一个外表友好的扩展名背后藏着一个 polyglot 文件。

对于这里测试过的二进制和标记类样本,即使文件名被去掉,Tika 仍然会根据内容进行路由,这在对象存储或 HTTP body 处理器丢失文件名时特别有用。这个结果并不覆盖 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 丢失:每个带标记的表格单元格、列表项和标题都还在。每个载体在热身后连续跑三次,输出都完全一致。这个结果只能说明带标记的块还在,不能说明未标记字符、顺序、空白、Unicode 规范化、重复内容、链接、页眉页脚或嵌入对象都被准确保留。它是一个“块存在性”检查,而不是“整份文档完全保真”的证明。

但扁平文本输出会丢掉源文档的大部分结构。

下面就是 HTML 表格文档经过 --text 后的结果:

	Tool	Throughput

	zztblcell_alpha	120

	zztblcell_beta	95

只有用制表符拼接的行。表头没有被标记为表头。没有网格,没有单元格边界,除了一个 tab 之外,看不出它曾经是一个 <table>。DOCX 表格也会以同样的方式被拍平。

列表的情况更微妙,它取决于源文档里到底存的是什么:

源文档里的项目符号是什么载体--text 的返回结果
字面字符——这些渲染里都是把 - 当作普通文本写进去的纯文本、Markdown、RTF、ODT、PDF- 会保留,因为 Tika 只是把字符原样传递出来
真实结构——比如 HTML 的 <li>,或者 DOCX 的 List Bullet 样式HTML、DOCX标记会完全消失,只剩下条目文本本身:HTML 里是带缩进的行,DOCX 里是普通的无装饰文本行

Tika 从不会重新生成它没有收到为文本的标记。内容一样,但输出长得不一样。

Markdown 的例子尤其说明问题。给 Tika 一个带管道表格的 .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 字节文件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 致命错误:"XML document structures must start and end within the same entity"exit 0 → OOXML 类型
UTF-8,无 BOM,未声明编码exit 0exit 0 → text/plain,charset 为 UTF-8

提取会明确失败,而且这些失败的外在形态很相似。 零字节文件、截断的 PDF、截断的 DOCX 都会抛异常、返回 exit 1,并且 stdout 为空。CLI 不会把失败悄悄吞掉,假装成一个干净的空结果。就进程安全性而言,这些场景没有挂死,也没有崩溃,但调用方必须检查退出码和 stderr,而不能只盯着空字符串。

检测与解析是解耦的。 对两个被截断的二进制文件,--detect 都会返回 exit 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 而受阻

一个是保留标记但输出扁平文本,另一个是返回类型化元素但会出现分类错误。你该选哪一个,取决于下游到底需要什么。如果只是搜索索引或 LLM 的上下文窗口,扁平文本可能已经够了。如果下游是按元素类型来做规则判断,那 Tika 的 --text 路径根本提供不了这种契约。

我们俩都没有扫描件数据。

优点和缺点

优点

  • 在五种可通过内容识别的样本上,内容类型检测在 20/20 个唯一条件中都无视了伪装文件名;重复的流式执行也一致。
  • 十四种载体渲染中的所有植入标记都保住了,包括带标记的表格单元格和列表项。
  • 三次本地复跑结果一致:在这个环境里,每个载体的输出字节完全相同。
  • 跨格式元数据已标准化——无论源格式如何,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 个无签名单元格里有 10 个会退化成 text/plain
  • --text 不返回元素类型;表格会被拍平成 tab 拼接的行,结构化列表标记会消失。
  • 遇到空文件和损坏文件时会直接抛异常;这两种情况仅从提取调用本身看起来是一样的。
  • 67 MB 的 jar,再加上 CLI 模式每次调用都要冷启动 JVM。
  • OCR 和扫描图像 PDF 在这里完全没有测试——由于没有安装 tesseract 和 poppler,我无法对那条路径做任何结论。
  • 这里的所有数字都来自单机、单版本的合成样本。真实语料准确率、加密文件、嵌套/递归文档以及规模化吞吐都没有测。

适合谁,不适合谁

如果你的输入是已经拿在手里的文件,而你的输出需要的是可被机器索引的文本加元数据,那 Tika 很合适。比如搜索索引、电子取证、档案处理、给 LLM 提供语料、构建上传流水线里的内容类型校验层。它很适合作为第一道分诊和标准化步骤,放在更智能的组件前面:先识别测试过的格式,抽取扁平文本,再把内容连同显式检查结果交给后面的系统。

如果你需要的是类型化元素、重建表格或文档版式,那就别只停在 --text;如果你的文档是扫描件,也别急着用,至少要先装好 tesseract 并自己跑一遍,因为我这里没有任何 OCR 数据可供参考。做大规模处理时,最好拿库模式或服务模式去和 CLI 在代表性文档上做基准测试。我的小文件测试里,进程启动的开销是能看见的,但吞吐和资源成本没有被测量。

最容易让人踩坑的一点是:如果你的存储层会去掉文件名,而你处理的是 Markdown 或 CSV,那就别指望 Tika 能把它们和纯文本区分开。原始文件名一定要留着。

替代方案,以及 Thunderbit 在哪里

先把边界说清楚,因为这里最诚实的比较对象其实是输入来源,不是质量。Tika 是一个免费、Apache-2.0、可自托管的文件解析工具。它处理的是你已经放在磁盘或桶里的文件。它不会抓网页,不会执行 JavaScript,不会处理反爬机制,也不会假装自己能。

而这正是托管式网页提取服务,包括我们自己的 Thunderbit,可能进入架构的位置:它负责抓取实时页面,而 Tika 负责解析你手里已经拥有的文件。本文没有把这些服务和 Tika 做直接对比,它们也不是同一种输入的替代品。

最清晰的划分是:Tika 用来处理你已经拥有的文档,托管式提取 API 用来获取你还得去抓的网页。很多流水线两者都会一起用——网页侧负责爬取和提取,返回来的 PDF 和 DOCX 附件则交给 Tika。

如果你在对比更广泛的开源生态,我还写过一篇 开源爬虫全景对比,以及一篇 GitHub 上 最值得用的爬虫项目汇总、一篇关于浏览器驱动式 Markdown 路线的实战 Crawl4AI 评测,还有一篇更全面的 网页抓取工具盘点。如果你更偏向无代码方案,也可以看看如何用 AI 抓取任意网站

试试 Thunderbit 做网页数据提取

结论

要不要用 Apache Tika?如果你的任务是把各种异构文件变成扁平文本和标准化元数据,并且你会校验自己流水线里不能丢的字段或标记,那答案是肯定的。

这次测试里最强的部分是检测器。它在五种可内容识别样本的 20 个唯一条件里都返回了正确类型,包括没有文件名的流式输入。十四种渲染里的所有植入标记都保住了,而且在三次本地复跑中输出逐字节一致。这些证据很有用,但仍然是合成证据。在这个 JDK 上只用一个 jar、而且非 OCR 路径没有依赖任何外部二进制文件,让部署体验异常平淡。

不过也要正确评估它的边界。你喂给它的每张表,最后都会变成 tab 拼接的行。任何结构化列表标记都会消失。文件名一旦没了,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 模式下不会。表格会变成由 tab 拼接的行,既没有单元格语义,也没有表头语义;结构化列表标记(比如 HTML 的 <li> 或 DOCX 的 List Bullet 样式)会消失。十四种载体渲染里的所有植入标记都保住了,但这并不能证明内容完全保真,而且 --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 错误。三者都会 exit 1,而且 stdout 为空,所以仅靠提取调用本身,空文件和损坏文件是分不出来的。不过检测功能仍然很稳——--detect 在这两个被截断的二进制文件上都返回了 exit 0,并给出了正确类型,这意味着你可以在真正解析之前先做一个可靠分诊。

这次对 Tika 的测试没有覆盖什么? 有四项,我明确没覆盖。OCR 和扫描图像(被阻断,未测试)。真实语料准确率——所有结果都来自带植入标记的受控合成样本,衡量的是与已知标签的一致性,而不是在混乱真实文档上的准确率。资源消耗、吞吐和峰值内存,我都没有测。还有“上千种文件类型”这条长尾——我只测试了九种有代表性的、无外部依赖的格式,并没有把整个目录都跑一遍。这里的所有结果都来自 Tika 3.3.2、OpenJDK 26.0.1、macOS arm64、单机环境。

Ke
Ke
Thunderbit 首席技术官 | 高级数据科学家与机器学习专家 Ke Shen 拥有近十年的机器学习和数据科学经验,毕业于哥伦比亚大学,曾任 Walmart Labs 高级数据科学家。他在 Python、R、Java 和统计学方面拥有深厚且备受同行认可的专业能力,并分享如何将复杂的 AI 算法从理论落地到生产级架构的实战经验。
目录
Thunderbit · AI 网页数据代理

一键 内提取任意页面数据

深受 250,000+ 用户信赖
提供免费方案
从网页到表格
描述你的需求——Thunderbit 的 AI 代理会帮你抓取并导出到 Excel、Google Sheets、Airtable 或 Notion。可免费开始。
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week