一、python-magic 库核心概述
1.1 核心用途
python-magic 是一款基于 libmagic 库封装的 Python 工具库,其核心功能是通过文件内容而非扩展名来识别文件的真实类型。在日常开发中,我们经常会遇到文件扩展名被篡改、后缀名丢失的场景,比如下载的压缩包被恶意修改为 .txt 后缀,或者老旧文件的扩展名损坏,此时 python-magic 就能通过解析文件的二进制特征码,准确判断出文件的真实格式,广泛应用于文件校验、爬虫数据处理、系统安全检测等领域。

1.2 工作原理
python-magic 的底层依赖于 Unix/Linux 系统中的 libmagic 库(Windows 系统需手动安装对应依赖),该库内置了一个魔法数字数据库,这个数据库中存储了各种文件格式对应的二进制特征值。当 python-magic 处理文件时,会读取文件头部的若干字节数据,将其与魔法数字数据库中的特征值进行匹配,从而判定文件的真实类型。整个过程无需解析文件完整内容,因此执行效率高,且不受文件扩展名的干扰。
1.3 优缺点分析
优点
- 识别精度高:基于文件内容的检测方式,能够绕过扩展名伪装,识别出文件的真实格式。
- 支持格式广泛:涵盖了文档、图片、音频、视频、压缩包等数千种常见文件格式。
- 跨平台兼容:支持 Windows、macOS、Linux 等主流操作系统(需注意依赖库的安装差异)。
- 轻量级易用:API 设计简洁,几行代码即可完成文件类型检测,学习成本低。
缺点
- 依赖外部库:Windows 系统下需要手动安装
libmagic依赖包,相比纯 Python 库安装步骤稍复杂。 - 对部分小众格式支持有限:对于一些冷门的自定义文件格式,可能无法匹配到对应的魔法数字,导致识别失败。
- 无法解析文件内容细节:该库仅能判断文件类型,不能提取文件的具体内容信息,如图片分辨率、文档字数等。
1.4 License 类型
python-magic 采用的是 MIT License,这是一种宽松的开源许可证。用户可以自由地使用、复制、修改、分发该库的源代码,无论是个人项目还是商业项目,都无需支付任何费用,只需在分发的软件中保留原作者的版权声明即可。
二、python-magic 安装步骤
2.1 系统依赖准备
python-magic 依赖系统底层的 libmagic 库,不同操作系统的安装方式有所不同,具体步骤如下:
- Linux 系统
对于 Debian/Ubuntu 系列发行版,执行以下命令安装:bash sudo apt-get update sudo apt-get install libmagic1
对于 CentOS/RHEL 系列发行版,执行以下命令安装:bash sudo yum install file-devel - macOS 系统
使用 Homebrew 包管理器安装,执行命令:bash brew install libmagic - Windows 系统 Windows 系统没有默认的包管理器,需要手动下载
libmagic依赖文件:- 访问 GnuWin32 网站,下载
file-5.39-bin.zip、file-5.39-dep.zip两个压缩包。 - 解压两个压缩包,将
bin目录下的libmagic-1.dll、magic.exe文件复制到 Python 的安装目录下的Scripts文件夹中。 - 将
share目录下的magic文件夹复制到 Python 安装目录的根目录下。
- 访问 GnuWin32 网站,下载
2.2 Python 库安装
在完成系统依赖安装后,通过 pip 命令即可安装 python-magic 库,执行以下命令:
pip install python-magic安装完成后,可以在 Python 交互环境中执行以下代码验证是否安装成功:
import magic
print(magic.__version__)如果没有报错,并且输出了对应的版本号(如 0.4.27),则说明安装成功。
三、python-magic 核心 API 与使用实例
python-magic 提供了两种核心使用方式:一种是直接调用函数式 API,另一种是创建 Magic 类实例进行自定义配置。下面我们分别介绍这两种方式的使用方法,并结合实例代码进行演示。
3.1 函数式 API 快速使用
函数式 API 封装了最常用的文件类型检测功能,适合快速开发场景,核心函数包括 detect_from_filename、detect_from_content、detect_from_fobj。
3.1.1 detect_from_filename:通过文件名检测文件类型
该函数接收一个文件路径作为参数,返回一个包含文件类型信息的字典,字典中包含 mime_type(MIME 类型)和 encoding(编码格式,仅文本文件有该字段)两个键。
实例代码
import magic
# 定义测试文件路径(替换为你自己的文件路径)
test_file_path = "test.jpg"
# 检测文件类型
result = magic.detect_from_filename(test_file_path)
# 输出检测结果
print(f"文件 MIME 类型: {result.mime_type}")
print(f"文件编码格式: {result.encoding}")代码说明
- 首先导入
magic库,然后定义需要检测的文件路径。 - 调用
detect_from_filename函数,传入文件路径,该函数会自动读取文件内容并进行类型检测。 - 打印返回结果中的 MIME 类型和编码格式。对于图片文件,
encoding字段通常为None;对于文本文件(如.txt),会返回具体的编码格式(如utf-8、gbk等)。
运行结果示例
文件 MIME 类型: image/jpeg
文件编码格式: None3.1.2 detect_from_content:通过文件内容检测文件类型
在某些场景下,我们可能没有完整的文件,只有文件的二进制内容(如网络请求中获取的文件流),此时可以使用 detect_from_content 函数,直接传入二进制数据进行检测。
实例代码
import magic
# 读取文件的二进制内容
with open("test.txt", "rb") as f:
file_content = f.read()
# 通过二进制内容检测文件类型
result = magic.detect_from_content(file_content)
# 输出检测结果
print(f"文件 MIME 类型: {result.mime_type}")
print(f"文件编码格式: {result.encoding}")代码说明
- 使用
rb模式打开文本文件,读取其二进制内容并存储到file_content变量中。 - 调用
detect_from_content函数,传入二进制内容,函数会根据内容特征判断文件类型。 - 打印检测结果,对于 UTF-8 编码的文本文件,运行结果会显示
mime_type为text/plain,encoding为utf-8。
运行结果示例
文件 MIME 类型: text/plain
文件编码格式: utf-83.1.3 detect_from_fobj:通过文件对象检测文件类型
如果已经打开了一个文件对象,不需要再次读取文件内容,直接使用 detect_from_fobj 函数传入文件对象即可完成检测,这种方式适合处理大文件,避免重复读取数据。
实例代码
import magic
# 打开文件对象
with open("test.zip", "rb") as f:
# 通过文件对象检测文件类型
result = magic.detect_from_fobj(f)
# 输出检测结果
print(f"文件 MIME 类型: {result.mime_type}")
print(f"文件编码格式: {result.encoding}")代码说明
- 使用
rb模式打开压缩包文件,得到文件对象f。 - 调用
detect_from_fobj函数,传入文件对象,函数会从文件头部读取特征字节进行检测。 - 打印检测结果,压缩包文件的 MIME 类型通常为
application/zip,编码格式为None。
运行结果示例
文件 MIME 类型: application/zip
文件编码格式: None3.2 Magic 类实例化使用
函数式 API 虽然方便,但可配置性较低。如果需要自定义检测规则(如只检测 MIME 类型、显示详细的文件描述信息等),可以通过实例化 Magic 类来实现。Magic 类的构造函数支持多个参数,常用参数如下:
mime:布尔值,设置为True时,仅返回 MIME 类型;默认为False,返回详细的文件描述信息。mime_encoding:布尔值,设置为True时,返回 MIME 类型和编码格式;默认为False。keep_going:布尔值,设置为True时,会输出所有匹配到的文件类型信息;默认为False,仅输出第一个匹配结果。uncompress:布尔值,设置为True时,会自动解压压缩文件后再进行检测;默认为False。
3.2.1 自定义检测 MIME 类型
通过设置 mime=True,可以让 Magic 实例仅返回文件的 MIME 类型,适合需要标准化文件类型标识的场景。
实例代码
import magic
# 实例化 Magic 类,指定仅返回 MIME 类型
mime_magic = magic.Magic(mime=True)
# 检测图片文件的 MIME 类型
image_type = mime_magic.from_file("test.png")
print(f"PNG 图片 MIME 类型: {image_type}")
# 检测音频文件的 MIME 类型
audio_type = mime_magic.from_file("test.mp3")
print(f"MP3 音频 MIME 类型: {audio_type}")代码说明
- 实例化
Magic类时传入mime=True参数,创建一个专门用于检测 MIME 类型的实例mime_magic。 - 调用实例的
from_file方法,传入文件路径,分别检测 PNG 图片和 MP3 音频文件的 MIME 类型。 - 打印检测结果,PNG 图片的 MIME 类型为
image/png,MP3 音频的 MIME 类型为audio/mpeg。
运行结果示例
PNG 图片 MIME 类型: image/png
MP3 音频 MIME 类型: audio/mpeg3.2.2 获取文件详细描述信息
默认情况下,Magic 实例会返回文件的详细描述信息,包括文件格式、版本等内容,适合需要向用户展示直观文件类型的场景。
实例代码
import magic
# 实例化 Magic 类,获取详细文件描述
detail_magic = magic.Magic()
# 检测不同类型文件的详细信息
txt_detail = detail_magic.from_file("test.txt")
pdf_detail = detail_magic.from_file("test.pdf")
exe_detail = detail_magic.from_file("test.exe")
# 输出详细信息
print(f"文本文件详细信息: {txt_detail}")
print(f"PDF 文件详细信息: {pdf_detail}")
print(f"EXE 程序详细信息: {exe_detail}")代码说明
- 实例化
Magic类时不传入任何参数,创建的detail_magic实例会返回详细的文件描述信息。 - 分别调用
from_file方法检测文本文件、PDF 文件和 Windows 可执行文件的详细信息。 - 打印检测结果,文本文件会显示编码格式和文件类型,PDF 文件会显示
PDF document相关描述,EXE 文件会显示PE32 executable相关信息。
运行结果示例
文本文件详细信息: UTF-8 Unicode text
PDF 文件详细信息: PDF document, version 1.5
EXE 程序详细信息: PE32 executable (GUI) Intel 80386, for MS Windows3.2.3 同时获取 MIME 类型和编码格式
通过设置 mime_encoding=True,可以让 Magic 实例同时返回文件的 MIME 类型和编码格式,这种方式比函数式 API 中的 detect_from_filename 更灵活,支持自定义其他参数。
实例代码
import magic
# 实例化 Magic 类,同时获取 MIME 类型和编码格式
mime_enc_magic = magic.Magic(mime_encoding=True)
# 检测文本文件和 CSV 文件
result1 = mime_enc_magic.from_file("test.txt")
result2 = mime_enc_magic.from_file("test.csv")
# 输出结果
print(f"文本文件 MIME 及编码: {result1}")
print(f"CSV 文件 MIME 及编码: {result2}")代码说明
- 实例化
Magic类时传入mime_encoding=True参数,创建的mime_enc_magic实例会返回MIME 类型; 编码格式的组合字符串。 - 分别检测文本文件和 CSV 文件,CSV 文件本质上也是文本文件,但其 MIME 类型通常为
text/csv。 - 打印检测结果,UTF-8 编码的文本文件和 CSV 文件会分别显示对应的 MIME 类型和编码格式。
运行结果示例
文本文件 MIME 及编码: text/plain; charset=utf-8
CSV 文件 MIME 及编码: text/csv; charset=utf-83.3 处理特殊场景文件
3.3.1 检测伪装扩展名的文件
在实际开发中,经常会遇到文件扩展名被篡改的情况,比如将 .exe 病毒文件伪装成 .jpg 图片文件,此时使用 python-magic 可以轻松识别出文件的真实类型。
实例代码
import magic
# 假设存在一个伪装为图片的可执行文件 fake.jpg(实际是 exe 文件)
fake_file_path = "fake.jpg"
# 使用 Magic 类检测真实类型
real_magic = magic.Magic()
real_type = real_magic.from_file(fake_file_path)
# 使用 MIME 类型检测
mime_magic = magic.Magic(mime=True)
real_mime = mime_magic.from_file(fake_file_path)
# 输出检测结果
print(f"文件伪装扩展名: .jpg")
print(f"文件真实类型描述: {real_type}")
print(f"文件真实 MIME 类型: {real_mime}")代码说明
- 准备一个伪装扩展名的文件
fake.jpg,其实际是 Windows 可执行文件。 - 分别使用返回详细描述的
real_magic和返回 MIME 类型的mime_magic实例检测文件。 - 打印检测结果,可以看到文件的真实类型是 PE32 可执行文件,MIME 类型为
application/x-dosexec,从而识破文件的伪装。
运行结果示例
文件伪装扩展名: .jpg
文件真实类型描述: PE32 executable (GUI) Intel 80386, for MS Windows
文件真实 MIME 类型: application/x-dosexec3.3.2 检测压缩包内的文件类型
通过设置 uncompress=True,Magic 实例可以自动解压压缩文件(如 .gz、.bz2 等格式),并检测压缩包内文件的真实类型,适合处理压缩文件的场景。
实例代码
import magic
# 实例化 Magic 类,开启自动解压功能
uncompress_magic = magic.Magic(uncompress=True)
# 检测 gz 压缩包内的文件类型
gz_file_detail = uncompress_magic.from_file("test.txt.gz")
print(f"gz 压缩包内文件类型: {gz_file_detail}")
# 检测 bz2 压缩包内的文件类型
bz2_file_detail = uncompress_magic.from_file("test.csv.bz2")
print(f"bz2 压缩包内文件类型: {bz2_file_detail}")代码说明
- 实例化
Magic类时传入uncompress=True参数,开启自动解压功能。 - 分别检测
.gz和.bz2格式的压缩包文件,uncompress_magic会先解压压缩包,再检测内部文件的类型。 - 打印检测结果,
.txt.gz压缩包内的文件会显示为 UTF-8 编码的文本文件,.csv.bz2压缩包内的文件会显示为 CSV 文本文件。
运行结果示例
gz 压缩包内文件类型: UTF-8 Unicode text (gzip compressed data, was "test.txt", last modified: ...)
bz2 压缩包内文件类型: CSV text (bzip2 compressed data, block size = 900k)四、python-magic 实际应用案例
4.1 批量检测文件夹内文件类型
在数据处理场景中,我们经常需要对一个文件夹内的所有文件进行类型检测,筛选出特定类型的文件。下面的案例实现了批量检测文件夹内所有文件的类型,并将结果保存到 CSV 文件中。
实例代码
import os
import csv
import magic
def batch_detect_file_type(folder_path, output_csv):
"""
批量检测文件夹内文件类型,并将结果保存到 CSV 文件
:param folder_path: 目标文件夹路径
:param output_csv: 输出 CSV 文件路径
"""
# 实例化 Magic 类,获取 MIME 类型和编码
mime_enc_magic = magic.Magic(mime_encoding=True)
# 准备 CSV 表头
headers = ["文件名", "文件路径", "MIME类型及编码"]
# 打开 CSV 文件并写入数据
with open(output_csv, "w", newline="", encoding="utf-8") as csv_file:
writer = csv.writer(csv_file)
writer.writerow(headers)
# 遍历文件夹内所有文件
for root, dirs, files in os.walk(folder_path):
for file_name in files:
# 获取文件完整路径
file_path = os.path.join(root, file_name)
try:
# 检测文件类型
file_type = mime_enc_magic.from_file(file_path)
# 写入 CSV 数据
writer.writerow([file_name, file_path, file_type])
print(f"已检测: {file_path} -> {file_type}")
except Exception as e:
# 捕获异常,处理无法检测的文件
print(f"检测失败: {file_path} -> 错误信息: {str(e)}")
writer.writerow([file_name, file_path, f"检测失败: {str(e)}"])
# 调用函数,批量检测 test_folder 文件夹内文件,并保存到 file_types.csv
if __name__ == "__main__":
target_folder = "test_folder"
output_file = "file_types.csv"
batch_detect_file_type(target_folder, output_file)代码说明
- 定义
batch_detect_file_type函数,接收目标文件夹路径和输出 CSV 文件路径作为参数。 - 实例化
Magic类并开启mime_encoding模式,用于获取文件的 MIME 类型和编码格式。 - 使用
os.walk遍历目标文件夹内的所有文件,获取每个文件的完整路径。 - 调用
from_file方法检测文件类型,将文件名、文件路径和检测结果写入 CSV 文件。 - 捕获检测过程中的异常(如文件无法访问、权限不足等),并将错误信息写入 CSV 文件。
- 在
if __name__ == "__main__"代码块中,指定目标文件夹和输出 CSV 文件路径,调用函数执行批量检测。
运行效果
运行代码后,会在当前目录下生成 file_types.csv 文件,文件中包含了文件夹内所有文件的名称、路径和类型信息,方便后续数据分析和筛选。
4.2 基于文件类型的爬虫数据过滤
在爬虫开发中,我们经常需要下载网络资源,但有时候会遇到链接返回的文件类型与预期不符的情况(如预期下载图片,实际下载的是 HTML 错误页面)。下面的案例结合 requests 库和 python-magic,实现爬虫数据的类型过滤,只保存符合预期类型的文件。
实例代码
import os
import requests
import magic
def download_file_by_type(url, save_folder, expected_mime):
"""
根据预期 MIME 类型下载文件,过滤不符合类型的资源
:param url: 文件下载链接
:param save_folder: 文件保存文件夹
:param expected_mime: 预期的 MIME 类型(如 image/jpeg、application/pdf 等)
"""
# 创建保存文件夹(如果不存在)
if not os.path.exists(save_folder):
os.makedirs(save_folder)
try:
# 发送 GET 请求,获取文件二进制内容
response = requests.get(url, stream=True)
response.raise_for_status() # 抛出 HTTP 错误异常
# 读取文件二进制内容(读取前 1024 字节即可满足类型检测需求)
file_content = response.raw.read(1024)
# 检测文件 MIME 类型
mime_magic = magic.Magic(mime=True)
file_mime = mime_magic.from_buffer(file_content)
# 判断是否符合预期 MIME 类型
if file_mime == expected_mime:
# 提取文件名
file_name = url.split("/")[-1]
save_path = os.path.join(save_folder, file_name)
# 完整下载文件并保存
with open(save_path, "wb") as f:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
print(f"成功下载符合预期的文件: {save_path} -> MIME 类型: {file_mime}")
else:
print(f"文件类型不符,跳过下载 -> 预期: {expected_mime}, 实际: {file_mime}")
except requests.exceptions.RequestException as e:
print(f"下载失败: {url} -> 错误信息: {str(e)}")
# 调用函数,下载预期为 JPG 图片的资源
if __name__ == "__main__":
# 测试链接(替换为实际的下载链接)
test_urls = [
"https://example.com/valid_image.jpg",
"https://example.com/fake_image.html"
]
save_dir = "downloaded_images"
expected_mime_type = "image/jpeg"
for url in test_urls:
download_file_by_type(url, save_dir, expected_mime_type)代码说明
- 定义
download_file_by_type函数,接收下载链接、保存文件夹和预期 MIME 类型作为参数。 - 首先创建保存文件夹(如果不存在),然后使用
requests.get方法发送请求,开启流式传输模式(stream=True)。 - 读取响应的前 1024 字节数据,这部分数据足够 python-magic 进行文件类型检测,避免下载完整文件后才发现类型不符。
- 实例化
Magic类并开启mime模式,检测读取到的二进制内容的 MIME 类型。 - 判断检测到的 MIME 类型是否与预期类型一致,如果一致,则提取文件名并完整下载文件到保存文件夹;如果不一致,则跳过下载。
- 捕获
requests库的请求异常(如网络错误、HTTP 404 错误等),并输出错误信息。 - 在
if __name__ == "__main__"代码块中,定义测试链接列表、保存目录和预期 MIME 类型,遍历链接并调用函数进行下载。
运行效果
运行代码后,只有 MIME 类型为 image/jpeg 的文件会被下载并保存到 downloaded_images 文件夹中,不符合预期类型的资源会被跳过,有效过滤了无效数据。
五、相关资源链接
- Pypi地址:https://pypi.org/project/python-magic
- Github地址:https://github.com/ahupp/python-magic
- 官方文档地址:https://python-magic.readthedocs.io/en/latest/
关注我,每天分享一个实用的Python自动化工具。

