PyPodcastPlayer

Podcastを読み込み、再生するPythonスクリプト
ファイル再生にpygame使用。
ソースファイル

  • -

PyPodcastPlayer.py

import os
import sys
import string
import urllib2
import xml.dom.minidom
import pygame.mixer

class PodcastPlayer :
 podcast_data = ""
 now_playing = ""

 def __init__(self, podcast_data) :
  self.podcast_data = podcast_data
  self.managePlayer()

 def managePlayer(self) :
  self.setTrack()
  while(True) :
   self.displayPlayer()
   self.selectFile()

 def setTrack(self) :
  for i, v in enumerate(self.podcast_data) :
   for j, data in enumerate(v) :
    self.podcast_data[i][j]["track"] = str(i + 1) + "-" + str(j + 1)

 def displayPlayer(self) :
  print "q    : Quit"
  print "0    : All Play"
  for i, v in enumerate(self.podcast_data) :
   for j, data in enumerate(v) :
    print '%-5s: [%s]\n     %s\t%s\n     %s' %\
      (data["track"], data["title"], \
      data["pubDate"], data["category"], \
      data["link"])

 def selectFile(self) :
  track = raw_input("Select track number(N-N) & Press Enter key: ")
  if (track == "q") :
   sys.exit()
  elif (track == "0") :
   for i, v in enumerate(self.podcast_data) :
    for j, data in enumerate(v) :
     self.now_playing = self.podcast_data[i][j]
     self.playFile()
  else :
   try :
    num =string.split(track, "-")
    r = int(num[0]) - 1
    s = int(num[1]) - 1
    self.now_playing = self.podcast_data[r][s]
    self.playFile()
   except :
    print "Unexpected error:", sys.exc_info()[0]

 def playFile(self) :
  pygame.mixer.init()
  pygame.mixer.music.load(self.now_playing["path"])
  print "Now playing... track["+ self.now_playing["track"] + "]"
  pygame.mixer.music.play()
  self.controlPlayer()

 def controlPlayer(self) :
  while(True) :
   key = raw_input("Press key & Enter key(z:stop, x: pause): ")
   if(key == "z") :
    pygame.mixer.music.stop()
    break
   elif(key == "x") :
    pygame.mixer.music.pause()
    key = raw_input("Press key & Enter key(z:stop, c: play): ")
    if(key == "z") :
     pygame.mixer.music.stop()
     break
    elif(key == "c") :
     pygame.mixer.music.unpause()
    else :
     pygame.mixer.music.stop()
     break
   else :
    pygame.mixer.music.stop()
    break

class PodcastManager :
 def getFile(self, data) :
  urlpath = string.replace(data["enclosure"], "http://", "")
  urlsp = string.split(urlpath, "/")
  file_name = urlsp[len(urlsp) - 1]
  del urlsp[len(urlsp) - 1]
  dir_name ="archive"+ os.sep + string.join(urlsp, os.sep)
  if not os.path.exists(dir_name) :
   os.makedirs(dir_name)
  file_path = dir_name + os.sep + file_name
  if not os.path.exists(file_path) :
   file = open(file_path, "wb")
   file.write(urllib2.urlopen(data["enclosure"]).read())
   file.close()
  data["path"] = file_path
  return data

 def getXmldata(self, xml_data) :
  dom = xml.dom.minidom.parseString(xml_data)
  dom_data = dom.getElementsByTagName("item")
  data_list = []
  i = 0
  while i < dom_data.length :
   data_map = {}
   item = dom_data.item(i)
   enclosure_elm = item.getElementsByTagName("enclosure").item(0)
   if enclosure_elm != None :
    enclosure = enclosure_elm.getAttribute("url")
    data_map["enclosure"] = enclosure
    title_elm = item.getElementsByTagName("title").item(0)
    title = title_elm.firstChild.data
    data_map["title"] = title
    try :
     link_elm = item.getElementsByTagName("link").item(0)
     link = link_elm.firstChild.data
     data_map["link"] = link
    except:
     data_map["link"] = "no link"
    try :
     category_elm = item.getElementsByTagName("category").item(0)
     category = category_elm.firstChild.data
     data_map["category"] = category
    except :
     data_map["category"] = "no category"
    try :
     pubDate_elm = item.getElementsByTagName("pubDate").item(0)
     pubDate = pubDate_elm.firstChild.data
     data_map["pubDate"] = pubDate
    except :
     data_map["pubDate"] = "no date"
    data_list.append(data_map)
   i = i + 1
  return data_list

 def getPodcastdata(self, list) :
  pdata = []
  for i, v in enumerate(list) :
   if(len(v) != 0) :
    print "Now Loading " + v + " ...",
    xmldata = urllib2.urlopen(v).read()
    pdata.append(self.getXmldata(xmldata))
    print "OK"
  for j, v in enumerate(pdata) :
   for k, w in enumerate(pdata[j]) :
    print "Now Downloading "+ w["enclosure"] + " ...",
    pdata[j][k] = self.getFile(w)
    print "OK"
  return pdata

 def readPodcastlist(self) :
  print "Now Loading podcast_list.txt ...",
  listf = open("podcast_list.txt")
  line = listf.readline()
  list = []
  while line :
   list.append(line.strip())
   line = listf.readline()
  listf.close()
  print "OK"
  return list

if __name__=='__main__' :
 pm = PodcastManager()
 podcast_list = pm.readPodcastlist()
 podcast_data = pm.getPodcastdata(podcast_list)
 pp = PodcastPlayer(podcast_data)

podcast_list.txt(例)

http://podfeedsp.podcastjuice.jp/app/rss_convert.cgi?url=http%3A%2F%2Ftbs954%2Ecocolog%2Dnifty%2Ecom%2Fbujio%2F
http://ajaxian.podbus.com/
http://feeds.feedburner.com/cinecast
http://pod.abc1008.com/1008podcast.xml
http://podcast.1242.com/fukuda/index.xml
http://podcast.rubyonrails.org/podcast.xml
http://www.awaretek.com/python/index.xml
http://www.j-wave.co.jp/blog/estation/task/index.xml
http://www.joqr.net/blog/shounen/index.xml
http://www.oreillynet.com/pub/feed/37?format=rss2
http://www.perlcast.com/rss/current.xml

実行例

> python PyPodcastPlayer.py
Now Loading podcast_list.txt ... OK
Now Loading http://podfeedsp.podcastjuice.jp/app/rss_convert.cgi?url=http%3A%2F%2Ftbs954%2Ecocolog%2Dnifty%2Ecom%2Fbujio%2F ... OK
〜(略)
Now Downloading http://tbs954.cocolog-nifty.com/bujio/files/b1010.mp3 ... OK
Now Downloading http://tbs954.cocolog-nifty.com/bujio/files/b1007.mp3 ... OK
〜(略)
q    : Quit
0    : All Play
1-1  : [10/10ブジオ!]
     MON, 10 Oct 2005 20:58:27 +0900     月曜日
     http://tbs954.cocolog-nifty.com/bujio/2005/10/1010_10b4.html
1-2  : [10/7無事?!終了です☆]
     Fri, 7 Oct 2005 21:36:52 +0900      金曜日
     http://tbs954.cocolog-nifty.com/bujio/2005/10/post_34e8.html
〜(略)
Select track number(N-N) & Press Enter key:

操作例

Select track number(N-N) & Press Enter key: 1-1  #(track num入力)
Now playing... track[1-1]
Press Key & Enter key(z:stop, x:pause): x        #(一時停止)
Press Key & Enter key(z:stop, c:play): c         #(再生)
Press Key & Enter key(z:stop, x:pause): z        #(停止)
q    : Quit
0    : All Play
1-1  : [10/10ブジオ!]
     MON, 10 Oct 2005 20:58:27 +0900     月曜日
     http://tbs954.cocolog-nifty.com/bujio/2005/10/1010_10b4.html
1-2  : [10/7無事?!終了です☆]
     Fri, 7 Oct 2005 21:36:52 +0900      金曜日
     http://tbs954.cocolog-nifty.com/bujio/2005/10/post_34e8.html
〜(略)
Select track number(N-N) & Press Enter key:q     #(終了)
>

ダウンロードしたファイルは「archive」フォルダにURLで分類して保存する。
1度ダウンロードしたファイルは再ダウンロードしない。レジューム機能無し。
全ての例外を処理していないので注意。
ファイルが多く、画面が小さいと、一覧表示の際にナンバの小さいトラックが見えなくなるのが問題。