用Python读取图片exif信息,为何有一段乱码?

{36864: b’0221’, 37121: b’\x01\x02\x03\x00’, 37377: (54823, 10760), 36867: ‘2019:07:08 11:22:43’, 36868: ‘2019:07:08 11:22:43’, 37378: (54823, 32325), 37379: (87417, 20593), 37380: (0, 1), 37383: 5, 37385: 16, 37386: (399, 100), 40961: 65535, 40962: 4032, 41989: 28, 41990: 0, 271: ‘Apple’, 272: ‘iPhone 7’, 40963: 3024, 274: 1, 531: 1, 37521: ‘872’, 37522: ‘872’, 37396: (2015, 1511, 2217, 1330), 41495: 2, 282: (72, 1), 283: (72, 1), 33434: (1, 34), 33437: (9, 5), 41729: b’\x01’, 34850: 2, 34853: {1: ‘N’, 2: ((24, 1), (28, 1), (1310, 100)), 3: ‘E’, 4: ((118, 1), (6, 1), (848, 100)), 5: b’\x00’, 6: (191089, 12880), 7: ((3, 1), (22, 1), (4076, 100)), 12: ‘K’, 13: (0, 1), 16: ‘T’, 17: (427210, 3809), 23: ‘T’, 24: (427210, 3809), 29: ‘2019:07:08’, 31: (65, 1)}, 34855: 25, 296: 2, 41986: 0, 40960: b’0100’, 41987: 0, 305: ‘12.0’, 306: ‘2019:07:08 11:22:43’, 42034: ((399, 100), (399, 100), (9, 5), (9, 5)), 42035: ‘Apple’, 42036: ‘iPhone 7 back camera 3.99mm f/1.8’, 34665: 204, 37500: b’Apple iOS\x00\x00\x01MM\x00\x14\x00\x01\x00\t\x00\x00\x00\x01\x00\x00\x00\n\x00\x02\x00\x07\x00\x00\x02.\x00\x00\x01\x04\x00\x03\x00\x07\x00\x00\x00h\x00\x00\x032\x00\x04\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x05\x00\t\x00\x00\x00\x01\x00\x00\x00\xbd\x00\x06\x00\t\x00\x00\x00\x01\x00\x00\x00\xbd\x00\x07\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x08\x00\n\x00\x00\x00\x03\x00\x00\x03\x9a\x00\x0c\x00\n\x00\x00\x00\x02\x00\x00\x03\xb2\x00\r\x00\t\x00\x00\x00\x01\x00\x00\x00"\x00\x0e\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x0f\x00\t\x00\x00\x00\x01\x00\x00\x00\x02\x00\x10\x00\t\x00\x00\x00\x01\x00\x00\x00\x01\x00\x14\x00\t\x00\x00\x00\x01\x00\x00\x00\x05\x00\x17\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x19\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x1f\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00%\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00&\x00\t\x00\x00\x00\x01\x00\x00\x00\x00\x00’\x00\n\x00\x00\x00\x01\x00\x00\x03\xc2\x00\x00\x00\x00bplist00O\x11\x02\x00#\x00*\x00.\x002\x00<\x00E\x00e\x00k\x00\\x00P\x00K\x00@\x00_\x00x\x00\\x007\x00\x1d\x00\x1a\x00\x17\x00\x14\x00\x11\x00\x17\x00#\x00/\x00(\x006\x00D\x00#\x00W\x00s\x00\x96\x00<\x002\x004\x005\x004\x000\x00)\x00#\x00\x1c\x00\x16\x00\x11\x00\x0f\x00\x12\x00-\x00G\x00\x90\x00_\x00K\x00R\x00W\x00X\x00V\x00P\x00I\x00?\x003\x00*\x00!\x00\x18\x00\x12\x00\x0e\x00\x12\x00)\x00r\x00}\x00\x88\x00\x8e\x00\x8b\x00\x82\x00v\x00f\x00S\x00A\x003\x00&\x00\x1b\x00\x14\x00\x12\x00\x17\x00\xa7\x00\xb8\x00\xca\x00\xd9\x00\xd4\x00\xc2\x00\x90\x00\x8b\x00~\x00d\x00M\x008\x00&\x00\x19\x00\x19\x00\x1f\x00\xe9\x00\x06\x01\x1e\x01*\x01 \x01\xfc\x00\x16\x01Z\x01\xe9\x00\xaa\x00p\x00O\x006\x00 \x00\x15\x00\x15\x002\x01S\x01j\x01s\x01`\x01$\x01y\x01\xbe\x01\xf2\x01\x1f\x01\x93\x00j\x00G\x00(\x00\x19\x00\x1c\x00x\x01\x95\x01\xac\x01\xa7\x01\x95\x01!\x01\xe6\x01\xbc\x01\xe4\x01-\x01\xb1\x00\x80\x00V\x001\x00\x1a\x00\x1e\x00\xae\x01\xcb\x01\xd9\x01\xcb\x01\xc0\x01$\x01\xf8\x01\x0c\x02\x12\x02F\x01\xc5\x00\x93\x00e\x00:\x00\x19\x00 \x00\xde\x01\xfa\x01\xf5\x01\xea\x01\xc8\x01C\x01a\x01\xf3\x01\xf2\x01\x1b\x01\xcf\x00\xa3\x00t\x00B\x00\x12\x00\x1e\x00\xf4\x01\x03\x02\xff\x01\xee\x01\xe1\x01\xc4\x01\xa3\x01\x88\x01e\x01\n\x01\xd8\x00\xad\x00\x82\x00I\x00\x0f\x00\x17\x00\xf8\x01\xfa\x01\xf7\x01\xea\x01\xde\x01\xc4\x01\x9f\x01s\x01>\x01\n\x01\xdd\x00\xb3\x00\x8e\x00Q\x00\x1a\x00\x19\x00\xfa\x01\xf5\x01\xee\x01\xe4\x01\xda\x01\xbb\x01\x9a\x01t\x01@\x01\xf7\x00\xb5\x00\x81\x00W\x00-\x00\x19\x00*\x00\xcb\x01\x8c\x01O\x01\x15\x01\xdc\x00\xa0\x00j\x00B\x00\x14\x00\r\x00\x0c\x00\x0b\x00\x10\x00\x1c\x00.\x00 \x00\x0f\x00\r\x00\r\x00\r\x00\r\x00\r\x00\x0e\x00\x12\x00\r\x00\x10\x00\x19\x00\x1f\x00!\x00-\x003\x00.\x00\x00\x08\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0cbplist00\xd4\x01\x02\x03\x04\x05\x06\x07\x08UflagsUvalueYtimescaleUepoch\x10\x01\x13\x00\x00N\n_I&^\x12;\x9a\xca\x00\x10\x00\x08\x11\x17\x1d’-/8=\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xff\xfd@\xaf\x00\x02\xc4\xa4\x00\x00\x07\xbc\x00\x00\xe0\x95\xff\xff\xcb\xdc\x00\x01G\xe1\x00\x00\x00?\x00\x00\x01\x00\x00\x00\x00\x81\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x01’}
用Python读取图片exif信息,为何有一段乱码?


1 回复

遇到图片EXIF信息里有乱码,这通常是因为编码问题。EXIF里的字符串字段(比如相机型号、拍摄者信息)可能用ASCII、UTF-8、JIS等不同编码存储,但有些软件写入时没规范处理,或者用了本地字符集(比如GBK),你用默认UTF-8去解码就出乱码了。

PIL(Pillow库)可以读EXIF,但解码得自己处理。下面是个例子,它会尝试常见编码,尽量把乱码转回来:

from PIL import Image
from PIL.ExifTags import TAGS

def decode_exif_string(value):
    """尝试用多种编码解码EXIF字符串"""
    if not isinstance(value, str):
        return value
    encodings = ['utf-8', 'latin-1', 'cp1252', 'gbk', 'shift_jis']
    for enc in encodings:
        try:
            # 如果value已经是str但乱码,先转回bytes再试
            if isinstance(value, str):
                b = value.encode('latin-1')  # 先转回原始字节
            else:
                b = value
            return b.decode(enc)
        except:
            continue
    return value  # 实在解不了就原样返回

def get_exif(image_path):
    img = Image.open(image_path)
    exif_data = img._getexif()
    if not exif_data:
        return None
    
    decoded_exif = {}
    for tag_id, value in exif_data.items():
        tag_name = TAGS.get(tag_id, tag_id)
        # 只处理字符串类型的值
        if isinstance(value, (str, bytes)):
            decoded_value = decode_exif_string(value)
        else:
            decoded_value = value
        decoded_exif[tag_name] = decoded_value
    return decoded_exif

# 使用示例
exif = get_exif('your_image.jpg')
if exif:
    for key, val in exif.items():
        print(f"{key}: {val}")

这里关键在 decode_exif_string 函数:它先假设原始数据被错误解码成了Latin-1(这是Python处理未知字节的默认方式),然后转回字节再尝试用UTF-8、GBK等常见编码重新解码。latin-1 编码很特殊,它能把0-255的字节直接映射成Unicode,所以可以无损转回原始字节。

如果这段代码还解决不了,那可能是EXIF数据本身就被写坏了,或者用了非常冷门的编码。你可以用十六进制编辑器直接看图片里EXIF段的原始字节,确认实际编码。

简单说就是编码对不上,得试几种常见的。

回到顶部