乐趣区

关于python:Python实现mp3-ID3v23信息提取

实现代码

援用所需模块 import re # 正则表达式

mp3 信息和门路提取 def mp3Info(input_file_url):

# 读取 mp3 文件
input_file_url = input_file_url
with open(input_file_url, "rb") as input_file:
    mp3_data = input_file.read().hex()
# 判断 mp3 文件类型是否是 ID3v2.3 格局
if mp3_data[:6] == "494433" and mp3_data[6:8] == "03":
    print("歌曲是 ID3v2.3 版本, 正在提取信息...")
    # 获取歌曲名称
    if re.search(r"\\", input_file_url):
        input_file_name = re.search("(.*).mp3", input_file_url.split("\\")[-1]).group(1)
    else:
        input_file_name = re.search("(.*).mp3", input_file_url).group(1)
    # 获取歌曲门路
    if re.search("(.*)" + input_file_name + ".mp3", input_file_url):
        input_file_path = re.search("(.*)" + input_file_name + ".mp3", input_file_url).group(1)
    else:
        input_file_path = ""
    return mp3_data, input_file_path, input_file_name  # 返回 mp3 16 进制数据, 输出文件门路, 输出文件文件名
else:
    return ""

提取标签内容函数 def tagInfo(tag_name, mp3_data):

# 标签名称,mp3 残缺数据
tag_name, mp3_data = tag_name, mp3_data
# 标签列表
tag_name_list = {"TIT2": "54495432", "TPE1": "54504531", "TALB": "54414c42"}
if tag_name in tag_name_list:
    tag_hex = tag_name_list[tag_name]  # 标签的 16 进制数据
    # 标签长度
    tag_len = int(re.search(tag_hex + "(.{8})", mp3_data).group(1), 16)
    # print("%s 标签的长度是 %s 个字节" % (tag_name,tag_len))
    # 判断标签类型
    tag_index = mp3_data.find(tag_hex)
    tag_data_type = mp3_data[(tag_index + 2 * (4 + 4 + 2)):(tag_index + 2 * (4 + 4 + 2 + 1))]
    # 判断内容编码方式
    if tag_data_type == "00":
        encoding_type = 'iso8859-1'
        # print("采纳 ISO-8859-1 编码")
    if tag_data_type == "01":
        encoding_type = 'utf-16-le'
        # print("采纳 UTF-16LE 编码")
    elif tag_data_type == "02":
        encoding_type = 'utf-16-be'
        # print("采纳 UTF-16BE 编码")
    # elif tag_data_type == "03":    #(仅 ID3V2.4 才反对)#     encoding_type = 'utf-8'
    #     print("采纳 UTF-8 编码")
    # 提取标签内容
    tag_data_hex = mp3_data[(tag_index + 2 * (4 + 4 + 2 + 1)):(tag_index + 2 * (4 + 4 + 2 + 1) + tag_len * 2 - 2)]  # 取标签内容 (16 进制)
    tag_data_bytes = bytes.fromhex(tag_data_hex)  # 将字符串转换为字节流数据
    tag_info = tag_data_bytes.decode(encoding_type, 'ignore')  # 依据编码类型解码
    return tag_info  # 返回标签的内容
else:
    return ""

提取所需标签信息 def tagsInfo():

# 标签类型 TIT2: 题目,TPE1: 艺术家,TALB: 专辑
tags = {"TIT2": "歌名", "TPE1": "歌手", "TALB": "专辑"}
# 标签内容提取
tags_info = {}
for i in tags:
    tag_name = i
    tag_info = tagInfo(tag_name, mp3_data)  # 标签数据
    tags_info[tags[i]] = tag_info.encode('utf-8').decode('utf-8-sig')  # 应用 utf-8-sig 编码,否则呈现 '\ufeff' BOM 数据
return tags_info  # 返回所有标签的内容 

获取歌曲时长函数 def mp3Duration(mp3_data):

music_index = mp3_data.find("496e666f0000000f")  # 定位歌曲理论的起始地位
music_size = len(mp3_data[music_index:]) / 2  # 歌曲字节长度
duration = music_size * 8 / (128 * 1000)  # 获取歌曲时长,单位 s
duration_show = str(int(duration / 60)) + ":" + str(int(duration % 60))  # 格式化歌曲时长
return duration_show  # 返回格式化的歌曲时长 

提取图片函数 def imgTag(mp3_data, input_file_path, input_file_name):

# 歌曲数据, 输出文件的门路, 输出文件的文件名
mp3_data, input_file_path, input_file_name = mp3_data, input_file_path, input_file_name
# 图片数据的提取
img_data_hex = re.search(r"ffd8.+?496e666f0000000f", mp3_data)[0]  # 图片的 16 进制数据
if img_data_hex:
    img_data_bytes = bytes.fromhex(img_data_hex)  # 将字符串转换为字节流数据
    out_file_name = input_file_path + input_file_name + '.jpg'
    with open(out_file_name, "wb") as out_file:
        out_file.write(img_data_bytes)
    return "%s%s.jpg" % (input_file_path, input_file_name)
else:
    return ""

if name == ‘__main__’:

try:
    # 提示信息
    print("##### 本程序为提取 mp3 ID3v2.3 格局的歌曲信息 #####")
    # mp3 门路
    input_file_url = input("请输出须要提取的文件门路:")
    # 获取歌曲信息
    mp3_info = mp3Info(input_file_url)
    if mp3_info:
        # 获取文件门路, 文件名
        mp3_data, input_file_path, input_file_name = mp3_info  # 返回 mp3 16 进制数据, 输出文件门路跟单网 www.gendan5.com/, 输出文件文件名
        # 获取标签数据
        tags_info = tagsInfo()
        # 获取歌曲时长信息
        mp3_duration = mp3Duration(mp3_data)
        tags_info["时长"] = mp3_duration  # 增加时长字段
        # 获取图片数据
        imgInfo = imgTag(mp3_data, input_file_path, input_file_name)
        tags_info["图片门路"] = imgInfo  # 增加图片字段
        print(tags_info)
        # 日志信息
        log = "歌曲门路:" + input_file_path + input_file_name + ".mp3 \n" + "歌曲信息:" + str(tags_info) + "\n\n"
    else:
        # 日志信息
        log = "暂不反对此文件的提取, 本程序仅反对 ID3v2.3 格局的 mp3 文件 \n\n"
        print("暂不反对此文件的提取, 本程序仅反对 ID3v2.3 格局的 mp3 文件")
except:
    # 日志信息
    log = "意外谬误 \n\n"
    print("意外谬误")
finally:
    # 保留日志
    with open(r"log.txt", "a") as out_file:
        out_file.write(log)
退出移动版