## 引言:元數據的重要性
照片元數據(Metadata)是嵌入在圖像文件中的隱藏信息,記錄了拍攝設備、時間、地理位置、光圈快門參數等關鍵數據。這些信息廣泛應用于**數字取證**、**照片管理**、**地理標記分析**和**版權驗證**等場景。本文將介紹Python中三種主流元數據提取方法,并提供完整的代碼實現。
---
## 一、使用Pillow庫提取基礎EXIF數據
### 安裝與基礎操作
```bash
pip install Pillow
```
### 代碼示例
```python
from PIL import Image
from PIL.ExifTags import TAGS
def get_exif_pillow(image_path):
try:
img = Image.open(image_path)
exif_data = img._getexif()
if exif_data:
return {
TAGS.get(tag_id, tag_id): value
for tag_id, value in exif_data.items()
}
except (AttributeError, OSError) as e:
print(f"Error: {e}")
return None
# 使用示例
metadata = get_exif_pillow("photo.jpg")
print("拍攝設備:", metadata.get("Model", "未知"))
print("拍攝時間:", metadata.get("DateTimeOriginal", "未記錄"))
```
### 特點與局限
- **支持格式**:JPEG/TIFF等格式
- **數據范圍**:僅提取EXIF標準字段
- **常見問題**:部分設備自定義標簽無法解析
---
## 二、使用ExifRead進行精準解析
### 安裝與高級解析
```bash
pip install exifread
```
### 代碼示例
```python
import exifread
def get_exif_exifread(image_path):
with open(image_path, 'rb') as f:
tags = exifread.process_file(f, details=False)
return {
str(tag): str(value)
for tag, value in tags.items()
}
# 提取GPS坐標
metadata = get_exif_exifread("photo.jpg")
gps_latitude = metadata.get("GPS GPSLatitude", "").strip("[]").split(", ")
gps_longitude = metadata.get("GPS GPSLongitude", "").strip("[]").split(", ")
```
### 優勢
- 支持原始十六進制數據解析
- 更完整的EXIF標簽覆蓋
- 可直接處理RAW格式文件(如.CR2/.NEF)
---
## 三、使用PyExifTool實現全能解析
### 安裝與配置
```bash
pip install PyExifTool
# 需預先安裝exiftool:https://exiftool.org/
```
### 代碼示例
```python
import exiftool
def get_all_metadata(image_path):
with exiftool.ExifToolHelper() as et:
metadata = et.get_metadata(image_path)[0]
return {
key.split(":")[-1]: value
for key, value in metadata.items()
}
# 獲取XMP和IPTC數據
full_data = get_all_metadata("photo.dng")
print("作者信息:", full_data.get("Creator", "未記錄"))
print("版權聲明:", full_data.get("Rights", "未標注"))
```
### 核心優勢
- 支持**XMP**、**IPTC**、**ICC Profile**等多標準
- 可處理**視頻文件**元數據
- 保留原始數據類型(非字符串)
---
## 四、GPS坐標轉換實戰
### 度分秒轉十進制
```python
def dms_to_decimal(dms, ref):
degrees = dms[0].num / dms[0].den
minutes = dms[1].num / dms[1].den
seconds = dms[2].num / dms[2].den
decimal = degrees + minutes/60 + seconds/3600
return -decimal if ref in ["S", "W"] else decimal
# 使用ExifRead數據示例
lat = dms_to_decimal(metadata["GPS GPSLatitude"], metadata["GPS GPSLatitudeRef"])
lon = dms_to_decimal(metadata["GPS GPSLongitude"], metadata["GPS GPSLongitudeRef"])
print(f"坐標:{lat:.6f}, {lon:.6f}")
```
---
## 五、技術選型建議
| 方法 | 適用場景 | 性能 | 數據完整性 |
|-------------|----------------------------|--------|------------|
| Pillow | 快速獲取基礎拍攝信息 | ★★★★☆ | ★★☆☆☆ |
| ExifRead | 專業級EXIF解析 | ★★★☆☆ | ★★★★☆ |
| PyExifTool | 跨格式元數據提取 | ★★☆☆☆ | ★★★★★ |
---
## 六、注意事項
1. **隱私安全**:刪除GPS標簽可使用`exiftool -GPS*= image.jpg`
2. **文件保護**:操作前備份原始文件
3. **編碼問題**:使用`chardet`庫處理字符編碼異常