首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python 解析 MP3 ID3v1 標籤資訊完整教學

     編輯:更多程式設計知識

MP3 檔案的 ID3v1 標籤位於檔案末尾 128 位元組,包含標題、藝術家、專輯、年份、註釋、流派等資訊。本文實作一個純 Python 2.x 腳本,遞迴掃描目錄解析所有 MP3 標籤並輸出。

ID3v1 標籤結構

欄位位移長度
TAG 標識0-23 bytes
標題3-3230 bytes
藝術家33-6230 bytes
專輯63-9230 bytes
年份93-964 bytes
註釋97-12630 bytes
流派1271 byte

核心類別設計


import os, sys
from UserDict import UserDict

def stripnulls(data):
    return data.replace("\x00", "").strip()

class FileInfo(UserDict):
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename

class MP3FileInfo(FileInfo):
    tagDataMap = {
        "title":   (3, 33, stripnulls),
        "artist":  (33, 63, stripnulls),
        "album":   (63, 93, stripnulls),
        "year":    (93, 97, stripnulls),
        "comment": (97, 126, stripnulls),
        "genre":   (127, 128, ord)
    }

    def __parse(self, filename):
        self.clear()
        try:
            fsock = open(filename, "rb", 0)
            try:
                fsock.seek(-128, 2)  # 從檔案末尾倒數 128 位元組
                tagdata = fsock.read(128)
            finally:
                fsock.close()
            if tagdata[:3] == "TAG":
                for tag, (start, end, parseFunc) in self.tagDataMap.items():
                    self[tag] = parseFunc(tagdata[start:end])
        except IOError:
            pass

    def __setitem__(self, key, item):
        if key == "name" and item:
            self.__parse(item)
        FileInfo.__setitem__(self, key, item)

目錄掃描與工廠模式


def listDirectory(directory, fileExtList):
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]
    fileList = [os.path.join(directory, f) for f in fileList
                if os.path.splitext(f)[1] in fileExtList]
    return [getFileInfoClass(f)(f) for f in fileList]

def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
    subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
    return hasattr(module, subclass) and getattr(module, subclass) or FileInfo

主程式執行


if __name__ == "__main__":
    for info in listDirectory("E:\\Music", [".mp3"]):
        print "\n".join(["%s=%s" % (k, v) for k, v in info.items()])
        print

輸出範例


album=What Are Words - Single
comment=pythontab
name=E:\Music\chris medina - what_are_words.mp3
title=What Are Words
artist=Chris Medina
year=2011
genre=13

album=After the Wedding
comment=pythontab
name=E:\Music\two fathers.mp3
title=Two Fathers
artist=pythontab
year=2010
genre=255

關鍵技術點

  • seek(-128, 2):從檔案末尾(whence=2)定位
  • UserDict:字典繼承基類,支援 __setitem__ 覆寫
  • 工廠函數 getFileInfoClass:根據副檔名動態選擇解析類別
  • stripnulls 清除空字元與首尾空白
  • 流派碼對應標準 ID3v1 流派表(0-255)

擴充建議

  • 支援 ID3v2.x 標籤(檔案開頭,長度可變、支援 Unicode、封面圖片)
  • 使用 mutagen、eyed3 等成熟庫處理複雜格式
  • 加入檔案編碼自動偵測(GBK/UTF-8)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved