ポッドキャストをダウンロードする
ポッドキャストを聞く場合、PCを使っている時はiTunesを使うのですが、車中で聞く場合は、USBメモリをチューナーに差して聞いています。
このUSBメモリにPC上のmp3のファイルを手作業でコピーするのが少々面倒なので、スクリプトでやってみることにしました。
やることは、ポッドキャストのデータから過去n時間以内に公開されたのmp3ファイルをダウンロードする、です。幾つかのファイルが揃ったらそれをDropbox側に移動させます。(Dropbox側へのファイルコピーはdropbox-apiを使ってみるを使うことにします。)
ポッドキャストのデータからmp3ファイルをダウンロードする方法ですが、スクリプトを書いてみました(download_podcast_mp3.py)。ネットで似たようなスクリプトを見つけたのですが、公開時期でファイルを選択させる機能がほしかったので書いた次第です。
import urllib2 from xml.dom.minidom import parse from time import strptime from datetime import datetime from datetime import timedelta import time import re import os import sys # The following url is feed format and can not be accepted. # url = "http://www.bbc.co.uk/worldservice/learningenglish/general/sixminute/index.xml" # The following url is rss format and can be accepted. # url = "http://downloads.bbc.co.uk/podcasts/worldservice/how2/rss.xml" def getPodcastXmlDom(url): response = urllib2.urlopen(url) #msg = response.read() dom1 = parse(response) return dom1 def getItemList(dom): items = dom.getElementsByTagName('item') if len(items) > 0: return parseItemsAsRSS(items) else: raise Exception("no item element found") def parseItemsAsRSS(items): results = [] for item in items: idict = dict() enc = item.getElementsByTagName('enclosure') if len(enc) == 1: idict["url"] = enc[0].getAttribute("url") idate = item.getElementsByTagName('pubDate') if len(idate) == 1: idict["date"] = getGMTDatetime(idate[0].firstChild.wholeText) ititle = item.getElementsByTagName('title') if len(ititle) == 1: idict["title"] = ititle[0].firstChild.wholeText if idict["url"] is not None and idict["date"] is not None and idict["title"] is not None: results.append(idict) return results def getGMTDatetime(idateStr): tlag = 0 if re.search("[\+\-][0-9]{4}",idateStr): tlag = int( re.findall("[\+\-][0-9]{4}", idateStr)[0] ) / 100 idateStr = re.sub("[\+\-][0-9]{4}", "GMT", idateStr) for s, v in { "ADT":-3, "AST":-4, "EDT":-4, "EST":-5, "PDT":-7, "PST":-8, "JST":9 }.iteritems(): if re.search(s, idateStr): tlag = v idateStr = re.sub(s, "GMT", idateStr) idateValue = strptime(idateStr, "%a, %d %b %Y %H:%M:%S %Z") idate = datetime(idateValue.tm_year,idateValue.tm_mon, idateValue.tm_mday, idateValue.tm_hour, idateValue.tm_min, idateValue.tm_sec) idate = idate - timedelta(hours = tlag) return idate def getFilename4mp3(idict): ret = re.sub("[ :]", "_", idict["title"]) ret = ret + "_" ret = ret + idict["date"].strftime("%Y_%m_%d_%H_%M") ret = ret + ".mp3" return ret def downloadFile(url, filename): print "download " + url + " as " + filename response = urllib2.urlopen(url) tofile = open(filename,"w") tofile.write(response.read()) response.close() tofile.close() def changeAccessTime(filename, pubdate): t = int(time.mktime(pubdate.timetuple())) os.utime(filename, (t,t)) def getLatestItem(items, nhoursago): tdy = datetime.today() # make t as GMT t = datetime(tdy.year, tdy.month, tdy.day, tdy.hour, tdy.minute) # assume this environment is in JST (+0900) t = t - timedelta(seconds = 9 * 3600) ndaysago = nhoursago % 24 nsecsago = (nhoursago - 24 * ndaysago) * 3600 results = filter(lambda i:i["date"] > t - timedelta(days = ndaysago, seconds = nsecsago) ,items) return results def main(): if len(sys.argv) < 2: print "Usage:" + sys.argv[0] + " url_of_podcast_rss [options]" print """Options: --since n : gets mp3s newer than n hours ago. default is 148 (24hours * 7days) --title TITLE : uses TITLE as filename """ sys.exit() url = sys.argv[1] nhoursago = 7 * 24 alttitle = None for i in range(2, len(sys.argv)): if sys.argv[i] == "--since" and i + 1 < len(sys.argv): nhoursago = int(sys.argv[i + 1]) if sys.argv[i] == "--title" and i + 1 < len(sys.argv): alttitle = sys.argv[i + 1] # items = getItemList(getPodcastXmlDom(url)) items = getLatestItem(getItemList(getPodcastXmlDom(url)),nhoursago) for item in items: if alttitle: item["title"] = alttitle downloadFile(item["url"], getFilename4mp3(item)) changeAccessTime(getFilename4mp3(item), item["date"]) def testGetGMTDatetime(): print getGMTDatetime("Sun, 22 Jan 2012 13:00:01 +0000") print getGMTDatetime("Thu, 27 Jan 2012 22:48:45 PDT") print getGMTDatetime("Thu, 26 Jan 2012 08:44:15 -0800") print getGMTDatetime("Fri, 27 Jan 2012 03:30:33 EST") if __name__ == '__main__': # testGetGMTDatetime() main()
以下使い方です。
$ python download_podcast_mp3.py ポッドキャストのURL [--since n] [--title TITLE]
対象となるmp3ファイルがあれば、カレントディレクトリにそのファイルが保存されます。ファイル名は「title_2012_01_27_01_23_45.mp3」のようにポッドキャストXML内のtitle要素 + pubDate要素を使います。
「–since n」は今からn時間前以降に公開されたファイルを対象とすることを指定します。デフォルトは148(一週間前)になります。
「–title TITLE」はファイル名にtitle要素以外の文字列を指定する場合に使用します。これはtitleに日本語が含まれる場合にうまく保存できないのを避けるための用意しています。
タイムゾーンの扱いは、きっちりやっていません。PDT、EDT、JST以外のタイムゾーンを扱う場合は、該当するタイムゾーン文字列とGMTとの時間差をdictで書いている部分がありますので、そこを変更してみてください。
追記:20120328
タイムゾーンを追加しました。