告别瞎猜文件类型:Google 开源 Magika,用 AI 精准识别文件内容

你有没有遇到过这种情况:同事发来一个没有后缀名的文件,或者从某个老旧系统里导出一批文件,扩展名全是 .dat。你试着用文本编辑器打开,看到一堆乱码;用系统自带的 file 命令试试,结果模棱两可;只好一个个拖进不同软件里试,看哪个能打开。运气好几分钟搞定,运气不好半小时就搭进去了。

Google 开源了一个叫 Magika 的工具,就是来解决这个问题的。它用深度学习模型识别文件类型,不依赖文件名、不依赖扩展名,直接读文件内容给出判断。官方说他们在 Gmail、Google Drive 和 Safe Browsing 里已经用上了,每周处理数千亿次识别请求。

我第一时间在自己的机器上试了一下,确实有点东西。这篇文章就把它的安装、使用和实际体验拆开来说清楚。

这玩意儿到底有多准?接近 99% 的判断正确率

Magika 说白了就是一个 AI 模型,它专门用来回答一个问题:「这个文件到底是什么格式?」

和传统工具不一样的是,它不靠文件头部的“魔数”硬匹配,也不看扩展名,而是用一种更灵活的方式——深度学习。所谓深度学习,你可以理解成让模型看了海量的样本之后,自己学会了判断逻辑。官方给的数据是,训练和评估用的样本接近 1 亿个,覆盖了 200 多种文件类型。这个规模其实挺夸张的,基本上你日常能碰到的文件格式都在里面了。

测试集上的准确率能做到 99% 左右。我自己测试了十几个不太常见的格式,包括一些没有扩展名的文本文件,基本都识别对了。

技术层面的另一个特点是快。模型加载是一次性开销,加载完成后,单次识别大概 5 毫秒。5 毫秒什么概念?你眨一下眼大概需要 100 到 150 毫秒,也就是说你眨一次眼的时间,Magika 能跑完二三十次识别。而且这个速度跟文件大小几乎没关系,它只读取文件的一小部分内容做判断,所以不管是 1KB 的配置文件还是 1GB 的视频文件,识别时间差不多。

还有一个细节我觉得挺有意思:Magika 内置了一套阈值机制。如果模型对自己的判断信心不足,它不会硬猜一个具体类型,而是返回一个更宽泛的标签,比如“Generic text document”或者“Unknown binary data”。这个设计在安全场景下尤其重要——宁可承认不确定,也不要给一个错误的确定性结论。

怎么装?三种方式,三分钟搞定

安装方式有好几种,看你习惯用哪种工具链。

「第一种,如果你日常写 Python:」

pipx install magika

如果你没装 pipx,直接用 pip 也行:

pip install magika

不过 pip 装的话最好在虚拟环境里操作,避免依赖冲突。

「第二种,macOS 或 Linux 用户,用 Homebrew:」

brew install magika

这条命令会把 Magika 的命令行工具装到系统路径,装完直接在终端敲 magika 就能用。

「第三种,通用方案,用官方提供的安装脚本:」

macOS / Linux:

curl -LsSf https://securityresearch.google/magika/install.sh | sh

Windows 用 PowerShell:

powershell -ExecutionPolicy Bypass -c "irm https://securityresearch.google/magika/install.ps1 | iex"

这种方式的优势是不依赖任何语言环境,直接下载二进制文件。装完之后用 magika --version 检查一下,能看到版本号就说明搞定了。

另外如果你是 Rust 开发者,也可以用 Cargo 安装:

cargo install --locked magika-cli

命令行上手:最常用的几种玩法

装好之后,最基础的使用方式就是直接给一个文件路径:

magika myfile

输出会告诉你这个文件是什么类型。默认输出是人类可读的描述文字,但实际用起来你会发现有不少场景需要更灵活的格式。

「需要简洁标签的时候,加 -l:」

magika -l myfile

输出只有一个短标签,比如 pythonjpgpdf,适合脚本里做逻辑判断。

「需要 MIME 类型的时候,加 -i:」

magika -i myfile

做 Web 开发的时候经常需要根据文件内容动态设置 Content-Type 头,这个组合就很顺手。

「想看置信度分数,加 -s:」

magika -s myfile

分数范围 0 到 1,越接近 1 表示模型越有把握。我试下来大多数正常文件的分数都在 0.98 以上,但也有少数边缘情况在 0.7 左右徘徊。这时候你就知道“哦,模型对这个判断其实不是特别确定”。

「批量处理目录,用 -r:」

magika -r ./some_folder/

它会递归扫描目录下的所有文件,挨个输出识别结果。官方示例里跑过这样一个命令:

cd tests_data/basic && magika -r *

输出结果从 Assembly 代码、批处理文件、C 源代码,到 Word 文档、邮件文件、空文件,一次性全部识别出来,类型标签清晰明了。

「输出 JSON 格式,用 --json:」

magika --json myfile

返回的 JSON 结构包含了完整信息:路径、识别结果、置信度分数、MIME 类型、所属分组、常见扩展名列表等等。这个模式适合把 Magika 集成到自动化流水线或者后端服务里。

[
  {
    "path": "./tests_data/basic/python/code.py",
    "result": {
      "status": "ok",
      "value": {
        "dl": {
          "description": "Python source",
          "extensions": ["py", "pyi"],
          "group": "code",
          "is_text": true,
          "label": "python",
          "mime_type": "text/x-python"
        },
        "output": {
          "description": "Python source",
          "extensions": ["py", "pyi"],
          "group": "code",
          "is_text": true,
          "label": "python",
          "mime_type": "text/x-python"
        },
        "score": 0.996999979019165
      }
    }
  }
]

「自定义输出格式,用 --format:」

如果你对默认输出不满意,可以自己拼装格式。占位符支持这些:

  • %p:文件路径
  • %l:类型标签
  • %d:类型描述
  • %g:类型分组
  • %m:MIME 类型
  • %e:常见扩展名
  • %s:置信度分数
  • %S:百分比显示的置信度

比如我想输出“路径 => 标签(分数)”:

magika --format "%p => %l (%s)" myfile

「从标准输入读数据:」

用短横线 - 代替文件路径,Magika 就会从标准输入读取内容:

cat myfile | magika -

或者:

echo "function log(msg) {console.log(msg);}" | magika -

这样即使文件不在磁盘上,也能做识别。

在代码里调用:Python 和 JavaScript 集成

命令行工具适合一次性任务,但如果你要在应用里集成文件识别能力,用 SDK 更合适。

「Python 集成」

安装:

pip install magika

使用起来非常直接。识别字节数据用 identify_bytes

from magika import Magika

m = Magika()
res = m.identify_bytes(b'function log(msg) {console.log(msg);}')
print(res.output.label)  # 输出: javascript

识别文件路径用 identify_path

from magika import Magika

m = Magika()
res = m.identify_path('./tests_data/basic/ini/doc.ini')
print(res.output.label)  # 输出: ini

识别已打开的文件流用 identify_stream

from magika import Magika

m = Magika()
with open('./tests_data/basic/ini/doc.ini', 'rb') as f:
    res = m.identify_stream(f)
print(res.output.label)  # 输出: ini

这里有一个点值得提一下:Magika 对象的初始化会加载模型文件,这个操作有一点开销。如果是在服务端使用,建议在应用启动时初始化一次,然后复用这个实例,而不是每次请求都重新创建。

「JavaScript / TypeScript 集成」

Magika 也提供了 npm 包。官方提到这个包目前还是实验性质,但已经可以用了:

npm install magika

这个包的运行方式比较有意思——它跑在本地浏览器里,不用把文件上传到任何服务器。Google 官方还做了一个 Web Demo,你直接在浏览器里上传文件,所有计算都在本地完成,隐私方面完全放心。

谁在用这东西?Google 自己的大规模实践

Magika 不是一个实验室里的小玩具,它在 Google 内部已经跑在核心业务上了。

  • 「Gmail」:邮件附件的上传流程里,Magika 负责判断附件类型,然后路由到对应的安全扫描器。不同格式的附件,安全扫描的策略是不一样的。
  • 「Google Drive」:用户上传的文件同样会经过 Magika 识别,用于执行合适的内容安全策略。恶意文件伪装成正常文件的情况并不少见,文件类型识别是第一道防线。
  • 「Safe Browsing」:Google 的安全浏览服务每天要处理海量样本,Magika 在这里也承担了文件类型判断的职责。

另外,安全社区的两个知名平台——VirusTotal 和 abuse.ch——也集成了 Magika。安全分析人员上传可疑文件之后,Magika 会帮忙快速判断文件类型,辅助后续分析决策。

这些场景的共同特点是:数据量巨大,对性能和准确率要求极高。Magika 能在这些地方落地,至少说明它在工程上经得起考验。

和传统 file 命令比,有什么不一样?

Linux 下有个历史悠久的 file 命令,它也做文件类型识别。那 Magika 和它有什么区别?

file 命令主要依赖两种方法。一种是“魔数匹配”——检查文件头部有没有某个固定模式的字节序列,比如 PDF 文件开头一定是 %PDF,PNG 图片开头一定是 \x89PNG。另一种是扩展名映射,看到 .txt 就认为是文本文件,看到 .jpg 就认为是 JPEG 图片。

魔数匹配这个方法本身没有错,但有两个局限。第一,覆盖面依赖于人工维护的特征库,遇到新格式或者变种可能就不认识。第二,对于文本类文件,这个方法基本失效——一段 Python 代码和一段 JavaScript 代码,文件头部没有本质区别,靠魔数根本分不出来。

Magika 的深度学习方案相当于把“识别特征”这件事交给模型自动学习,不需要人工为每个格式编写规则。尤其是对文本类文件的表现,据官方数据是明显优于传统方法的。

但这并不意味着 file 命令就被淘汰了。对于规范的二进制格式,file 足够快、足够可靠。Magika 更像是一个补充选项——当你发现 file 识别不出来,或者识别结果太笼统的时候,换 Magika 试试,大概率有惊喜。

几个容易踩的坑

「1. 模型加载开销」

这个前面提过,但值得再说一遍。Magika 对象初始化的时候会加载模型文件,几 MB 大小,加载需要一点时间。如果你是写命令行脚本那无所谓,但如果是写 Web 服务,别忘了做单例复用。

「2. 不要传整个大文件」

Magika 的设计是只读文件头部,这是它快的根本原因。实际调用的时候,它内部会自动控制读取范围,不需要你手动截断。但是,如果你想在应用里做优化,可以留意这一点——你不用先把整个 1GB 视频文件读进内存再传给 Magika,它只需要前几 KB。

「3. 置信度低的时候怎么办」

如果你看到某个文件的置信度分数只有 0.6 或 0.7,不要强行采信这个结果。这时候 Magika 自己都在摇摆不定,返回的 label 只是“相对最像的那个”。可以考虑走人工复核,或者结合其他信息综合判断。这也是为什么官方提供了不同的预测模式——high-confidence 模式下,Magika 只在分数很高时才给具体类型,否则返回通用标签;best-guess 模式则无论如何都给一个最可能的答案。两种模式没有绝对好坏,看你的业务场景对“误报”还是“漏报”更敏感。

实用摘要

  • Magika 是 Google 开源的文件类型识别工具,基于深度学习,准确率约 99%,支持 200+ 种文件类型。
  • 安装方式:pipx install magikabrew install magika、或官方安装脚本。
  • 基础命令:magika <文件路径>,递归扫描加 -r,JSON 输出加 --json
  • Python 集成:Magika().identify_path()identify_bytes()identify_stream()
  • 速度:单次识别约 5ms,与文件大小无关。
  • 和传统 file 命令互补,文本类文件识别是它的强项。
  • 注意模型加载的一次性开销,服务端应用请复用实例。

一页速览

场景 命令 / 代码
安装(pipx) pipx install magika
安装(brew) brew install magika
基础识别 magika myfile
递归识别目录 magika -r ./folder/
只输出标签 magika -l myfile
输出 MIME 类型 magika -i myfile
显示置信度分数 magika -s myfile
JSON 格式输出 magika --json myfile
自定义输出格式 magika --format "%p: %l (%s)" myfile
从 stdin 读取 cat myfile | magika -
Python 识别字节 Magika().identify_bytes(data)
Python 识别路径 Magika().identify_path(path)
Python 识别流 Magika().identify_stream(file_obj)

常见问题

「Magika 会把我的文件内容上传到服务器吗?」

不会。模型在本地加载,所有计算都在本地完成,不需要联网,也不会上传任何数据。

「支持 Windows 吗?」

支持。Windows、macOS、Linux 都有对应的安装方式。

「能识别哪些文件类型?」

目前覆盖 200 多种内容类型,包括常见二进制格式(图片、音视频、压缩包、可执行程序)和大量文本格式(源代码、配置文件、文档、邮件等)。具体列表可以参考官方文档里的模型说明。

「和系统自带的 file 命令有什么区别?」

file 命令依赖魔数匹配和扩展名,识别文本类文件比较弱。Magika 用深度学习,对文本类文件的识别更准,覆盖面也更广。两者互补使用效果最好。

「这个项目是 Google 官方支持的吗?」

官方声明里说这不是一个正式 Google 项目,不享受 Google 的产品支持。不过它确实在 Google 内部大规模使用,代码质量是有保障的。

「商用的话需要注意什么?」

Magika 采用 Apache 2.0 许可证,商用友好。具体条款可以看项目仓库里的 LICENSE 文件。