毛豆工作室有xml 可以下載,先用 xml.dom.minidom 分析取出 fileName + title + description ,之後用 eyeD3 (python 模組) 將mp3 加tag。
總共有一千多個mp3,很難確保第一次就寫程式就OK,保險點是第一步驟的結果先暫存在 txt 檔,之後再讀 txt檔用 eyeD3。或是先對一兩個mp3試驗,之後再擴展之。再者,從xml中抽取出的description裡面有時夾雜不想要的廣告文字或html控制碼,先暫存輸出到txt檔,各別修改之。這樣子做至少比在程式一開始寫時就全盤考慮來得簡單、有效率的多了。現在的text editor的 find/replace都很強大,有regular expression功能,做起來不比用python程式遜色。
這個xml 結構是有兩百多個item,每個item描述每個mp3,每個mp3有 title、description、link等 nodes。
dom1 = xml.dom.minidom.parse('8minsreading_2010.xml') items = dom1.getElementsByTagName('item') for item in items: title = item.getElementsByTagName('title')[0].\ firstChild.nodeValue link = item.getElementsByTagName('link')[0].\ firstChild.nodeValue fileName = link.split('/')[-1].split('.')[0] description = item.getElementsByTagName('description')\ [0].firstChild.nodeValue
Unicode 簡体中文的問題:第一個問題是python在print到 stdio的時候,簡中會變成亂碼(文字化け),就算用了
sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)偶爾某些印出還是亂碼,所以不要太在意console output,還是先印出到暫存的 utf-8 text 檔。
第二個問題是 iTunes 用的IDv3 是 eyeD3.ID3_V2_3 ,是UCS-2 little endian,也就是前綴要加上
tag.encoding='\x01'不保險的話,要對tag的每個frame.encoding都設好
for frame in tag.frames: frame.encoding='\x01'
為了要讓下載到iPhone的mp3,在聆聽時點一下螢幕會出現歌詞。這個mp3必須要加一個tag 叫「UNSYNCED LYRICS」。從foobar2000上看到tag名是 UNSYNCED LYRICS,但其實對eyeD3只要一個簡單的addLyrics即可:
tag.addLyrics(description)
以下python code全文,是邊做邊改邊試的,只是為了一次性工作而做的。你可以取出copy paste對你有幫助的code片段,比如 xml 的讀取,eyeD3 tag的寫入。
#!/usr/bin/env python # -*- coding: utf-8 -*- import os, sys, codecs, glob, re import xml.dom.minidom from xml.dom.minidom import parse import eyeD3 sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) def read_xml(): xmlFileName = '8minsreading_2010.xml' dom1 = parse(xmlFileName) txtFileName = xmlFileName.split('.')[0] + '.txt' fout = codecs.open(txtFileName, mode='w', \ encoding='utf-8') items = dom1.getElementsByTagName('item') for item in items: title = item.getElementsByTagName('title')[0].\ firstChild.nodeValue link = item.getElementsByTagName('link')[0].\ firstChild.nodeValue fileName = link.split('/')[-1].split('.')[0] description = item.getElementsByTagName(\ 'description')[0].firstChild.nodeValue description = description.split(' ')[0] description = description.strip() fout.write(fileName + '\t' + title + '\t' + \ description + '\n') fout.close() def sum_all(): pat = re.compile(r'\d\d\d\d\d\d\t') table = {} txtFiles = ['8minsreading_2011.txt', '8minsreading_2010.txt', '8minsreading_2009.txt', '8minsreading_2008.txt', '8minsreading_2007.txt'] for txtFile in txtFiles: fin = codecs.open(txtFile, mode='r', encoding='utf-8') for line in fin: line = line.strip() if not line: continue if pat.match(line): comps = line.split('\t') fileTitle = comps[0] title = comps[1] description = ''.join(comps[2:]) table[fileTitle] = (fileTitle, title, description) else: (fileTitle, title, description) = \ table[fileTitle] description += line table[fileTitle] = (fileTitle, title, description) fin.close() fout = codecs.open('all.txt', mode='w', encoding='utf-8') keys = table.keys() keys.sort() for k in keys: fileTitle, title, description = table[k] fout.write( fileTitle+'\t'+ title +'\t'+ description +'\n' ) fout.close() table = {} fin = codecs.open('all.txt', mode='r', encoding='utf-8') for line in fin: comps = line.split('\t') fileTitle, title = comps[0], comps[1] description = ''.join(comps[2:]) table[fileTitle] = (title, description) fin.close() mp3Files = glob.glob('*.mp3') for mp3File in mp3Files: fileTitle = mp3File.split('.')[0] title, description = table[fileTitle] tag = eyeD3.Tag() tag.link(mp3File) tag.setVersion(eyeD3.ID3_V2_3) tag.encoding='\x01' tag.setTitle(fileTitle+title ) tag.setAlbum(u'開卷八分鐘') tag.setArtist(u'梁文道') tag.addLyrics(description) for frame in tag.frames: frame.encoding='\x01' tag.update()
No comments:
Post a Comment