Pypodd
I’ve been working on and off since around Summer last year, making a simplistic command line podcast catching app. I had a go with lots of other podcatchers: upodder , greg , podcatcher and others that I can’t remember, but I found them to be just a bit overblown, and many had difficulty when RSS feeds were constructed with certain types of formatting. So while I was on trying to learn Python I set myself the task of writing a little app.
In the end, it only took 120 lines of code, which I think is quite good, though it doesn’t do anything fancy like let you store databases of played episodes, it just lists podcasts through a heirarchical menu system and lets you download them one at a time.
#!/usr/local/opt/python/libexec/bin/python
# Modules
import feedparser
import urllib
import os
import csv
from progress.bar import Bar
# Define system location variables
destDir = os.environ['HOME'] + os.sep + "Downloads" + os.sep # Note trailing `os.sep`
subsLoc = "subscriptions.txt"
# e.g. subsLoc = os.environ['HOME'] + os.sep + "subscriptions.txt"
# Define progress bar class for urllib.urlretrieve()
class dlProg:
def get(self, url, to):
self.p = None
def update(blocks, bs, size):
if not self.p:
self.p = Bar(to, max=size)
else:
if size < 0:
self.p.update()
else:
self.p.goto(blocks * bs)
urllib.urlretrieve(url, to, update)
self.p.finish()
# Import subscriptions list from csv containing [url, name]
with open(subsLoc) as f:
subs = csv.reader(f)
subs = list(subs)
# Split subs into URLs and titles
urlList = [x[0] for x in subs]
subList = [x[1] for x in subs]
# Select a podcast to download, from list of subscriptions
count_subs = 1
input_exit = 1
while input_exit != 2: # Terminate program if input_exit == 2
for i in subList:
print(str(count_subs) + ") " + i) # Print list of podcasts - could convert to parsed feeds later
count_subs += 1
input_subs = input("\nChoose a podcast [1-n]: ") # Take input
input_subs = int(input_subs) # Convert input to integer
index_subs = input_subs - 1 # For 0-base indexing
# Parse chosen feed
feedChooseList = [] # Create empty list
feedChooseList.append(urlList[index_subs]) # Fill list with URL of chosen podcast
feedList = [] # Create empty list
for i in feedChooseList:
feedList.append(feedparser.parse(i)) # Fill list parsed data from URL
# Extract episode names from parsed feed
nameList = [] # Create empty list
for i in feedList[0]['entries']: # Fill list with names of episodes
nameList.append(i['title'])
# Extract episode links from parsed feed
linkList = [] # Create empty list
for i in feedList[0]['entries']: # Fill list with episode URLs
linkList.append(i['enclosures'][0]['href'])
# Select episode to download - most recent or other - menu 1
count_epi_1 = 1
optList = ['Most recent episode', 'Another episode'] # Create a list of options
print("\nMost recent episode: " + nameList[0] + "\n") # Print name of most recent episode
for i in optList: # Choose between most recent or other episode
print(str(count_epi_1) + ") " + i)
count_epi_1 += 1
input_epi_1 = input("\nChoose an episode to download: ") # Take user input
input_epi_1 = int(input_epi_1)
# Select an episode to download - menu 2
count_epi_2 = 1
count_epi_3 = 1
len_nameList = len(nameList)
if input_epi_1 == 1: # Outer if statement, if user inputs 1 or 2, do stuff, otherwise, return to beginning
print ("\nDownloading most recent episode")
dlExt = ".mp3"
dlName = nameList[0]
dlFile = destDir + dlName + dlExt
dlURL = linkList[0]
dlProg().get(dlURL, dlFile)
optList = ['Download more', 'Exit'] # Create a list of options
for i in optList: # Give option to download more podcasts (return to main menu or exit
print(str(count_epi_2) + ") " + i)
count_epi_2 += 1
input_exit = input("\nFinished Downloading. Get more?")
input_exit = int(input_exit)
elif input_epi_1 == 2:
for i in nameList:
print(str(count_epi_2) + ") " + i)
count_epi_2 +=1
input_epi_2 = input("\nChoose an episode to download: ")
input_epi_2 = int(input_epi_2) - 1
if input_epi_2 <= len_nameList: # Inner if statement, If user inputs a valid episode number, do stuff, otherwise, try again
dlExt = ".mp3"
dlName = nameList[input_epi_2]
dlFile = destDir + dlName + dlExt
dlURL = linkList[input_epi_2]
dlProg().get(dlURL, dlFile)
optList = ['Download more', 'Exit'] # Create a list of options
for i in optList:
print(str(count_epi_3) + ") " + i)
count_epi_3 += 1
input_exit = input("\nFinished Downloading. Get more?")
input_exit = int(input_exit)
else:
raw_input("Invalid choice, press Enter to try again...")
else:
raw_input("Invalid choice, press Enter to try again...")
So basically, it’s just a set of if statements linked to the value of user input variables, all wrapped in a big while loop so it continues to return to the first level menu unless you tell it to exit.
The structure goes like this, where each number refers to a menu requiring user input:
1. Choose a podcast to download
│
└─2. Choose an episode to download, most recent or another
│
├─Most Recent
│ │
│ └─Downloading most recent episode
└─Another
│
└─3. Choose a specific episode to download
│
└─Download the specific episode