get_podcasts.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #!/usr/bin/env python3
  2. #############################
  3. ###### USER VARIABLES #######
  4. #############################
  5. # set download root dir
  6. download_root_dir = '/home/bryan/Downloads/Podcasts'
  7. # set handheld directory
  8. handheld_root_dir = '/run/media/bryan/SANSA CLIPZ/Podcasts'
  9. # feeds (python list)
  10. feedurls = ['http://linuxactionnews.com/rss', \
  11. 'http://wakingup.libsyn.com/rss', \
  12. 'http://feeds.soundcloud.com/users/soundcloud:users:146429914/sounds.rss', \
  13. 'http://billburr.libsyn.com/rss', \
  14. #'http://feeds.99percentinvisible.org/99percentinvisible', \
  15. 'http://files.libertyfund.org/econtalk/EconTalk.xml', \
  16. 'http://jamesandthegiantpodcast.libsyn.com/rss', \
  17. 'http://rss.art19.com/tim-ferriss-show']
  18. #'http://feed.thisamericanlife.org/talpodcast']
  19. #'https://www.npr.org/rss/podcast.php?id=510019']
  20. # number of old episodes to keep
  21. old_episodes_keep = 2
  22. # include episode name in filename (1 = on, 0 = off)
  23. episode_name_in_filename = 0
  24. # enable debug output (1 = on, 0 = off)
  25. debug = 0
  26. #################################
  27. ###### END USER VARIABLES #######
  28. #################################
  29. import podcastparser
  30. import urllib.request
  31. import os
  32. import time
  33. import datetime
  34. import glob
  35. import shutil
  36. # spoof headers for certain rss feeds
  37. opener=urllib.request.build_opener()
  38. opener.addheaders=[('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36')]
  39. opener.addheaders=[('Content-Type', 'application/json')]
  40. urllib.request.install_opener(opener)
  41. #################################
  42. ######### GET EPISODES ##########
  43. #################################
  44. # parse feeds
  45. for feed in feedurls:
  46. # parsed is a dict
  47. parsed = podcastparser.parse(feed, urllib.request.urlopen(feed), old_episodes_keep)
  48. # debug
  49. if debug == 1:
  50. import pprint
  51. pprint.pprint(parsed)
  52. # get podcast title
  53. podcast_title = parsed['title']
  54. print('Checking ' + podcast_title + ' for new episdoes...')
  55. # check if download dir exists and if not, make it
  56. podcast_download_dir = os.path.join(download_root_dir, podcast_title)
  57. if not os.path.exists(podcast_download_dir):
  58. os.mkdir(podcast_download_dir)
  59. # parse episodes
  60. for episode in parsed['episodes']:
  61. # format release time to date format
  62. release_time = int(episode['published'])
  63. episode_date = datetime.datetime.fromtimestamp(release_time)
  64. episode_date = episode_date.strftime("%y-%m-%d")
  65. # debug
  66. if debug == 1:
  67. print(release_time)
  68. print(episode_date)
  69. # create filename based on episode date and/or episode title
  70. if episode_name_in_filename == 0:
  71. episode_title = episode_date
  72. else:
  73. episode_title = episode_date + " " + episode['title']
  74. full_episode_path = os.path.splitext(os.path.join(podcast_download_dir, episode_title))[0]
  75. for enclosures in episode['enclosures']:
  76. # get download url
  77. url = enclosures['url']
  78. if debug == 1:
  79. print(url)
  80. if enclosures['mime_type'] == 'audio/mpeg':
  81. full_episode_path += '.mp3'
  82. # download file and save to episode title
  83. if not os.path.exists(full_episode_path):
  84. try:
  85. print('Downloading ' + episode['title'])
  86. urllib.request.urlretrieve(url, full_episode_path)
  87. except urllib.error.HTTPError as e:
  88. print('HTTPError' + ': Could not download ' + podcast_title + '\n' + 'Reason: ' + e.reason + '\n' + 'URL: ' + url)
  89. except urllib.error.URLError:
  90. print('URLError')
  91. except urllib.error.ContentTooShortError:
  92. print('Download failed, file corrupt!')
  93. # remove old episodes
  94. old_files = glob.glob(os.path.join(podcast_download_dir, '*'))
  95. old_files.sort()
  96. for file in old_files[:-old_episodes_keep]:
  97. os.unlink(file)
  98. #################################
  99. ######## MANAGE HANDHELD ########
  100. #################################
  101. if os.path.exists(handheld_root_dir):
  102. # define copy to handheld function
  103. def copy_files(src_file, dest_dir):
  104. if not os.path.isdir(dest_dir):
  105. os.mkdir(dest_dir)
  106. filename = os.path.basename(src_file)
  107. dest_file = os.path.join(dest_dir, filename)
  108. if not os.path.exists(dest_file):
  109. print('Copying ' + src_file + ' to ' + dest_file)
  110. shutil.copyfile(src_file, dest_file)
  111. # copy to handheld
  112. podcast_dirs = glob.glob(os.path.join(download_root_dir, '*'))
  113. for podcast_dir in podcast_dirs:
  114. podcast_name = os.path.basename(podcast_dir)
  115. handheld_target_dir = os.path.join(handheld_root_dir, podcast_name)
  116. files_to_copy = glob.glob(os.path.join(podcast_dir, '*'))
  117. for file in files_to_copy:
  118. if debug == 1:
  119. print(file + ' ' + handheld_target_dir)
  120. copy_files(file, handheld_target_dir)
  121. # remove old files from handheld
  122. podcast_dirs = glob.glob(os.path.join(handheld_root_dir, '*'))
  123. for podcast_dir in podcast_dirs:
  124. old_files = glob.glob(os.path.join(podcast_dir, '*'))
  125. old_files.sort()
  126. for file in old_files[:-old_episodes_keep]:
  127. os.unlink(file)
  128. else:
  129. print('Handheld not detected, skipping...')