# -*- coding: utf-8 -*-
"""
-----------------------------------主程序-------------------------------
按歌手或者专辑名移动MP3.py
将这个主程序和ID3v2.py , MP3.py ,MP3Info.py 三个文件(此三个文件详见前面链接2)放在一起,就可以用了。
Created on Sun Jun 14 22:35:36 2020
用于快速给mp3歌曲按歌手或者专辑进行分类
@author: user
"""
import MP3
import re
import os
import shutil
#原音乐所在文件夹=os.path.split(os.path.realpath(__file__))[0] #若启动此语句,就是默认处理当前py文件所在路径
原音乐所在文件夹=r'C:\音乐归集'
归集方式='专辑'#可选择参数:歌手 或 专辑
转移目标文件夹路径=os.path.join('C:\音乐归集-专辑')
def thwb(dthwb,nr):
for i in range(len(dthwb)):
if isinstance(dthwb[i],str):#是文本类型直接替换成没有
nr=nr.replace(dthwb[i],'')
elif isinstance(dthwb[i],list):#事列表类型,替换为指定的值
nr=nr.replace(dthwb[i][0],dthwb[i][1])
return nr
xttszf=[['?','?'],[':',':'],['*','*'],['<','<'],['>','>'],[r'/','/'],['\\','\'],['|','|'],['"','"']]#windows文件系统不允许以下字符 < > / \ | : " * ?
def find_file(path, ext, file_list=[]):
dir = os.listdir(path)
for i in dir:
i = os.path.join(path, i)
if os.path.isdir(i):
find_file(i, ext, file_list)
else:
if ext == os.path.splitext(i)[1]:
file_list.append(i)
return file_list
ext = ".mp3"
file_list = find_file(原音乐所在文件夹, ext)
for file in file_list:
a = MP3.MP3(file)
filename = os.path.basename(file)
try:
# 乐曲名称=a.d['TIT2']
if 归集方式=='歌手':
歌手=a.d['TPE1']
歌手=thwb(xttszf,歌手)#此处必须对获取的题目做个处理,避免无法作为正常文件路径
待转移文件夹路径_file=os.path.join(转移目标文件夹路径,歌手)
elif 归集方式=='专辑':
专辑名=a.d['TALB']
专辑名=thwb(xttszf,专辑名)
待转移文件夹路径_file=os.path.join(转移目标文件夹路径,专辑名)
if not os.path.exists(待转移文件夹路径_file):
os.makedirs(待转移文件夹路径_file)
# print(待转移文件夹路径_file)
shutil.move(file,待转移文件夹路径_file)
except Exception as exc:
try:#按第二方案,假设是歌手-歌曲名的命名方式
文件名后缀=os.path.splitext(file)[1]
文件名=filename.replace(文件名后缀,'')
# print(歌手)
# print(乐曲名称)
if 归集方式=='歌手':
word = u'-'
a = [m.start() for m in re.finditer(word, 文件名)]#找到所有-符号所在位置
歌手=文件名[:a[-1]].strip()
歌手=thwb(xttszf,歌手)
# 乐曲名称=文件名[a[-1]+1:].strip()
待转移文件夹路径_file=os.path.join(转移目标文件夹路径,歌手)
if 归集方式=='专辑':
专辑名='未分类专辑'
待转移文件夹路径_file=os.path.join(转移目标文件夹路径,专辑名)
if not os.path.exists(待转移文件夹路径_file):
os.makedirs(待转移文件夹路径_file)
shutil.move(file,待转移文件夹路径_file)
except Exception as exc:
print(exc)
下面是对应库文件代码,留存,怕网页内容丢了
---1/3------------
# ID3v2.py version 1.2
# Module for manipulating ID3 informational tags in MP3 audio files
# 鉴于现在适用与python3的ID3软件包很少,遂自己写了一个。现在网上的mp3一般都有ID3v2标签,
# 本模块功能就是读取mp3文件的ID3v2标签,把标签记录在一个集合里面。
# 特别的,对于最常见的歌手,曲名和专辑名,可以通过一些内部属性直接调用访问。
# Written 2013/4/19 By Kayneo <kayneo@yeah.net>
# This is the first thing I've written in Python.
# constructor:
# ID3(filename)
# then you can use the ID3v2 tag as in the follwing
#
# ID3.d
# It's a set containing all the tag found in ID3v2
#
# ID3.title or ID3.d['TIT2']
# The title of the song
#
# ID3.artist of ID3.d['TPE1']
# The artist
#
# ID3.album or ID3.d['TALB']
# The album
#
# ID3.haspic
# Whether or not has a pic
#
# ID3.tagverison
# The ID3v2 version :v2.3 or v2.4
#
# ID3.tagsize
# The size of the ID3 tag
#
# ID3.d['TYER']
# The year
#
# ID3.d[etc.]
# Other tags.
# Usage :
# import ID3v2
# a=ID3v2.ID3('filename')
# print(a.d)
# print(a.artist, a.title, a.album)
def trip_space(s):
while len(s) > 0 and s[-1] == '\x00':
s = s[:-1]
## while len(s) > 0 and s[:2] == b'\x00\x00':
## s = s[2:]
return s
class NoID3v2Error(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
class ID3:
def __init__(self, file):
self.fname = file
try:
self.file = open(file, 'rb')
except IOError as msg:
print('{0:s} open Error! {1:s}'.format(self.fname,msg))
return
if self.file.read(3) != b'ID3' :
#print('No ID3v2 Tag')
raise NoID3v2Error('No ID3v2 Tag')
self.file.close()
return
self.d = {}
self.tagversion = 0
self.tagsize = 0
self.haspic = False
self.artist = ''
self.title = ''
self.album = ''
HDR = self.file.read(7)
self.tagv = 'v%d.%d'%(2,HDR[0])
self.tagsize = HDR[-1]+HDR[-2]*0x80+HDR[-3]*0x4000+HDR[-4]*0x200000 +10
#print (self.tagsize)
while True:
a = self.file.read(1)
if a == b'\x00' or a == b'\xff': break
self.file.seek(-1,1)
fhdr = self.file.read(10) # ;print (fhdr)
sz = fhdr[-3]+fhdr[-4]*0x100 +fhdr[-5]*0x10000+fhdr[-6]*0x1000000
kind = fhdr[0:4].decode()
if kind != 'APIC':
info = self.file.read(sz) #;print (info)
try:
st = info.rfind(b'\xff\xfe')
if st != -1: # \x01\xff\xfe.....\xff\xfe
self.d[kind] = trip_space(info[st+2:].decode('utf16'))
elif info.startswith(b'\x03'):
self.d[kind] = trip_space(info[1:].decode())
else: #\x00
self.d[kind] = info[1:-1].replace(b'\x00',b'\x20').decode('gbk')
except UnicodeDecodeError as msg:
#print('Decode Error @%s, Content is %s\nMsg:%s'%(kind,info, msg))
pass
else:
self.haspic = True
break
#self.file.seek(sz,1)
#print(self.file.tell())
if 'TPE1' in self.d.keys(): self.artist = self.d['TPE1']
if 'TIT2' in self.d.keys(): self.title = self.d['TIT2']
if 'TALB' in self.d.keys(): self.album = self.d['TALB']
self.file.close()
---2/3-------------
# MP3.py Version 1.0
# This module is to get the ID3v2 and infomation of MP3 file.
#获取MP3的信息包含id3v2信息
# Written 2013/4/19 By Kayneo <kayneo@yeah.net>
# This is the first thing I've written in Python.
# Constrctor:
# MP3(filename)
#then you can use the ID3v2 tag as in the follwing
#
# MP3.title or MP3.d['TIT2']
# The title of the song
#
# MP3.artist of MP3.d['TPE1']
# The artist
#
# MP3.album or MP3.d['TALB']
# The album
#
# MP3.bitrate or ID3.d['Bitrate']
# The bitrate of the song
#
# MP3.trackmod or MP3.d['Trackmod']
# The mode of track. 声道模式
#
# MP3.sample_freq or MP3.d['Sample Frequency']
# The frequency of sample 采样率
#
# MP3.d[...]
# Various properties of MP3
#
# Usage :
# import MP3
# a=MP3.MP3('filename')
# print(a.d)
# print(a.artist, a.title, a.bitrate)
from MP3Info import MP3Info
from ID3v2 import *
class MP3:
def __init__(self, file, name='unknown'):
self.name = file
self.artist = ''
self.title = ''
self.album = ''
self.bitrate = ''
self.trackmod = ''
self.sample_freq = ''
self.d={}
try:
mp3info = MP3Info(file)
self.bitrate = mp3info.bitrate
self.trackmod= mp3info.trackmod
self.sample_freq = mp3info.sample_freq
id3 = ID3(file)
self.artist = id3.artist
self.title = id3.title
self.album = id3.album
self.d = dict(mp3info.d, **id3.d)
except NoID3v2Error as msg:
self.d = mp3info.d
print(msg)
## except :
## print('Some Error!')
##
---3/3------------------------------------------------------
# MP3Info.py Version 1.0
# This module focus on geting the infomation of the MP3 file, such as bitrate, sample frequency.
# 获取MP3的信息,包括比特率,取样率,等等。
# Written 2013/4/19 By Kayneo <kayneo@yeah.net>
# This is the first thing I've written in Python.
# constructor:
# MP3Info(filename)
# then you can use the ID3v2 tag as in the follwing
#
# MP3.d
# It's a set containing all the tag found in MP3
#
# MP3Info.version of MP3Info.d['Version']
# The version of the file
#
# MP3Info.bitrate or MP3Info.d['Bitrate']
# The bitrate of the song
#
# MP3Info.trackmod or MP3Info.d['Trackmod']
# The mode of track. 声道模式
#
# MP3Info.sample_freq or MP3Info.d['Sample Frequency']
# The frequency of sample 采样率
#
# MP3Info.copyright or MP3Info.d['Copyright']
# The copyright of MP3
#
# MP3Info.original or MP3Info.d['Original']
# Whether or not Original 是否原版
#
# MP3Info.frame_mod or MP3Info.d['Frame Mode']
# The mode of frame
# Usage :
# import MP3Info
# a=MP3Info.MP3Info('filename')
# print (a.d)
# print(a.bitrate)
class MP3Info:
MP3Version = {0b00:'MPEG 2.5', 0b01:'UNDEFINED', 0b10:'MPEG 2', 0b11:'MPEG 1'}
MP3Layer = {0b00:'UNDEFINED', 0b01:'Layer 3', 0b10:'Layer 2', 0b11:'Layer 1'}
MP3CRC = {0b0:'校检', 0b1:'非校检'}
MP3Bitrate = {0b0000:'free',
0b0001:32,
0b0010:40,
0b0011:48,
0b0100:56,
0b0101:64,
0b0110:80,
0b0111:96,
0b1000:112,
0b1001:128,
0b1010:160,
0b1011:192,
0b1100:224,
0b1101:256,
0b1110:320,
0b1111:'bad'}
MP3Samp_freq = {0b00:441000, 0b01:48000, 0b10:32000, 0b11:'UNdefined'}
MP3Frame_mod = {0:'无需调整',1:'调整'}
MP3Trackmod ={0b00:'立体声',0b01:'联合立体声',0b10:'双声道',0b11:'单声道'}
MP3Copyright ={0b0:'不合法', 0b1:'合法'}
MP3Original = {0b0:'非原版', 0b1:'原版'}
def __init__(self, file):
self.name = file
try:
self.file = open(file, 'rb')
except IOError as msg:
print('{0:s} open Error! {1:s}'.format(self.fname,msg))
return
if self.file.read(3) == b'ID3':
HDR=self.file.read(7)
tagsz = HDR[-1]+HDR[-2]*0x80+HDR[-3]*0x4000+HDR[-4]*0x200000 +10
self.file.seek(tagsz,0)
else:
self.file.seek(0)
framehdr = self.file.read(4)
vbrinfo = self.file.read(32)
self.file.close()
self.d={}
self.version = self.MP3Version[(framehdr[1]&0b00011000)>>3] +' - ' +self.MP3Layer[(framehdr[1] & 0b00000110)>>1]
self.bitrate = self.MP3Bitrate[framehdr[2]>>4]
self.sample_freq = self.MP3Samp_freq[(framehdr[2]&0b00001100)>>2]
self.padding = (framehdr[2]&0b00000010)>>1
self.frame_mod = self.MP3Frame_mod[self.padding]
self.trackmod = self.MP3Trackmod[framehdr[3]>>6]
self.copyright = self.MP3Copyright[(framehdr[3]&0b00001000)>>3]
self.original = self.MP3Original[(framehdr[3] &0b00000100)>>2]
if self.version : self.d['Version'] = self.version
if self.bitrate : self.d['Bitrate'] = self.bitrate
if self.sample_freq : self.d['Sample Frequency'] = self.sample_freq
if self.frame_mod : self.d['Frame Mode'] = self.frame_mod
if self.trackmod :self.d['Track Mode'] = self.trackmod
if self.copyright: self.d['Copyright'] = self.copyright
if self.original : self.d['Original'] = self.original
------------ single.py -----------------
import MP3,re
file = r'a.mp3'
a = MP3.MP3(file)
print (a.d)
---------------------------------