The getEps function in this module returns a text string containing the original air date for the last aired and next upcoming episodes of a TV series title. It also provides the plot for the next upcoming episode, if available. The information returned is limited to what is available at IMDb, and so it may not be up to date. IMDbPY (http://imdbpy.sourceforge.net/) is used. See code for usage information and examples.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | # TV-Series Current Episode Info 1.02
# Date: 2008/05/08
# License: As-is; public domain
# Prerequisites: Python 2.5.2, IMDbPY 3.5
# Description: The getEps function in this module returns a text string containing the original air date for the last aired and next upcoming episodes of a TV series title. It also provides the plot for the next upcoming episode, if available. The information returned is limited to what is available at IMDb, and so it may not be up to date. IMDbPY (http://imdbpy.sourceforge.net/) is used. It is designed especially for use by an IRC or other text bot.
# Usage:
# from getEps import getEps
# getEps('title of a TV series')
# Usage examples:
# getEps('terminator')
# The episode that aired last for "Terminator: The Sarah Connor Chronicles" (2008) is "The Demon Hand" (S01E07). It aired 4 days ago, i.e. on Mon, 25 Feb 08. The next upcoming episode is "Vick's Chip" (S01E08). It airs in 3 days, i.e. on Mon, 3 Mar 08. Its plot is unavailable.
# getEps('smallville')
# The episode that aired last for "Smallville" (2001) is "Fracture" (S07E12). It aired 15 days ago, i.e. on Thu, 14 Feb 08. The next upcoming episode is "Hero" (S07E13). It airs in 13 days, i.e. on Thu, 13 Mar 08. Its plot is: Pete Ross returns to Smallville and finds a number of surprising changes since his departure four years earlier. Besides resolving his feelings toward Clark since he learned of his friend's secret, Pete has to deal with the acquisition of a superpower of his own.
# getEps('stargate atlantis /noplot')
# The episode that aired last for "Stargate: Atlantis" (2004) is "The Kindred: Part 1" (S04E18). It aired 7 days ago, i.e. on Fri, 22 Feb 08. The next upcoming episode is "The Kindred: Part 2" (S04E19). It airs today, i.e. on Fri, 29 Feb 08.
# Keywords:
# tv, television, tv show, tv series, tv episodes, episodes,
# last episode, previous episode, next episode, upcoming episode, future episode,
# episode date, episode air date, episode schedule, original air date,
# imdb, imdbpy,
# tv bot, tv show bot, tv episode bot
# Import needed modules and methods
from imdb import IMDb
from imdb.helpers import sortedEpisodes
from itertools import dropwhile, ifilter, islice, takewhile
from datetime import date
from time import sleep, strptime
import locale
# Set locale
locale.setlocale(locale.LC_ALL,'') # This is used for formatting numbers
def getEps(title,max_len=990,debug=False): # 1024-32-2 = 990
"""Returns a text string containing schedule info for the last aired and the next upcoming episodes for the given TV series title"""
# Validate title
assert isinstance(title,str), 'A string input was not provided.'
# Preprocess title
title=title.strip()
# Determine if the next upcoming episode's plot should be included if available (Default is True)
if title.lower().endswith('/noplot'):
title=title[:-len('/noplot')].rstrip()
include_plot=False
else:
include_plot=True
try:
# Validate title further
if len(title)==0: return 'A title was not provided.'
# Create IMDb object
i=IMDb()
# Get search results
max_attempts=3 # Set to anything greater than 1
for attempt in range(1,max_attempts+1):
try:
search_results=i.search_movie(title)
break
except:
if attempt<max_attempts:
if debug: print 'An error occurred while attempting to retrieve search results for "%s". %s attempts were made.'%(title,attempt)+'\n'
sleep(attempt*2)
else:
return 'An error occurred while attempting to retrieve search results for "%s". %s attempts were made.'%(title,attempt)
del attempt,max_attempts
# Get first search result that is a TV series
search_results=ifilter(lambda s:s['kind']=='tv series',search_results)
search_results=list(islice(search_results,0,1))
if len(search_results)==0: return 'No TV series matches were found for "%s".'%title
s=search_results[0]
del search_results
# Get episodes
i.update(s,'episodes')
s_title=s['long imdb title']
if (not s.has_key('episodes')) or len(s['episodes'])==0: return 'Episode info is unavailable for %s.'%s_title
s=sortedEpisodes(s)
if len(s)==0: return 'Episode info is unavailable for %s.'%s_title
# Sort episodes in approximately the desired order
s.reverse() # This results in episodes that are sorted in the desired order. If, however, the episodes are not listed in proper order at the source, such as for "Showtime Championship Boxing" (1987) as of 2/29/08, the error will be copied here.
s=list(dropwhile(lambda e:e['season']=='unknown',s))+list(takewhile(lambda e:e['season']=='unknown',s)) # While this may not always produce the most accurate results, it prevents episodes belonging to an unknown season from being thought of as most recent.
# Process date related info for episodes
date_today=date.today()
for ep_ind in xrange(len(s)):
if s[ep_ind].has_key('original air date'):
try:
s[ep_ind]['date']=strptime(s[ep_ind]['original air date'],'%d %B %Y')
except: pass
if s[ep_ind].has_key('date'):
s[ep_ind]['date']=date(*s[ep_ind]['date'][0:3])
s[ep_ind]['age']=(s[ep_ind]['date']-date_today).days # Age is date delta in days
if s[ep_ind]['age']<0:
s[ep_ind]['has aired']=True
else:
s[ep_ind]['has aired']=False
else:
s[ep_ind]['has aired']=False
del date_today,ep_ind
# Print last 10 listed episodes (if debugging)
if debug:
print 'Last 10 listed episodes:\nS# Epi# Age Episode Title'
for e in s[:10]: print '%s %s %s %s'%(str(e['season']).zfill(2)[:2],str(e['episode']).zfill(4),e.has_key('age') and str(e['age']).zfill(5) or ' '*5,e['title'].encode('latin-1'))
print
# Declare convenient functions for use in generating output string
def getSE(e):
if not isinstance(e['season'],int): return ''
Sstr='S'+str(e['season']).zfill(2)
Estr='E'+str(e['episode']).zfill(2)
return ' ('+Sstr+Estr+')'
def getAge(e): return locale.format('%i',abs(e['age']),grouping=True)
def getDate(e): return 'i.e. on '+e['date'].strftime('%a, ')+str(e['date'].day)+e['date'].strftime(' %b %y')
# Determine last aired episode
# (An episode that airs today is considered to be not yet aired)
e=ifilter(lambda e:e['has aired'],s)
e=list(islice(e,0,1))
if len(e)>0:
e=e[0]
e_schedule= e['age']!=-1 and ('%s days ago'%getAge(e)) or 'yesterday'
# Generate output string when last aired episode is available
e_out='The episode that aired last for '+s_title+' is "'+e['title']+'"'+getSE(e)+'. It aired '+e_schedule+', '+getDate(e)+'. '
del e_schedule
else:
# Generate output string when last aired episode is unavailable
e_out=''
# Determine next upcoming episode
# (An episode that airs today is considered to be an upcoming episode)
e=list(takewhile(lambda e:e['has aired']==False,s)) # Memory inefficient
if len(e)>0:
e=e[-1]
# Generate output string when next upcoming episode is available
e_out=e_out+'The next upcoming episode '+(e_out=='' and ('for '+s_title+' ') or '')+'is "'+e['title']+'"'+getSE(e)+'.'
if e.has_key('age'):
e_schedule= e['age']>1 and ('in %s days'%getAge(e)) or e['age']==1 and 'tomorrow' or e['age']==0 and 'today'
e_out=e_out+' It airs '+e_schedule+', '+getDate(e)+'.'
del e_schedule
else:
e_out=e_out+' Its air date is unavailable.'
if include_plot:
if e.has_key('plot') and e['plot']!='Related Links':
e_out=e_out+' Its plot is: '+e['plot']
elif e_out.endswith('Its air date is unavailable.'):
e_out=e_out.replace('Its air date is unavailable.','Its air date and plot are unavailable.')
else:
e_out=e_out+' Its plot is unavailable.'
else:
if e_out!='': # Last: available; Next: unavailable
e_out=e_out+'No upcoming episode is scheduled.'
else: # Last: unavailable; Next: unavailable
e_out='Episode info is unavailable for %s.'%s_title
# Conditionally trim output string
if (max_len not in [-1,0,None]) and len(e_out)>max_len-3: e_out=e_out[:max_len-3]+'...'
# Return output string
return e_out
except: return 'An error occurred while attempting to retrieve episode info for "%s".'%title
def getEps_test(add_noplot=False):
"""Run a set of tests"""
# Make a tuple of sample titles in alphabetical order
titles=('24', # As of 2/21/08, this item has inconsistent schedule info
'arrested development',
'avatar',
'big brother',
'dexter',
'future weapons', # As of 2/21/08, this item has inconsistent schedule info
'heroes',
'kid nation',
'kyle xy',
'las vegas',
'lost',
'my name is earl',
'nip tuck',
'numbers', # This item is a misspelled name of a TV series and it has an unaired pilot
'prison break',
'scrubs',
'showtime championship boxing', # The episodes for this item are not correctly sorted by date
'smallville',
'south park',
'stargate atlantis',
'stargate sg1', # This item doesn't have an upcoming episode
'supernatural',
'terminator', # This item is a partial name of a TV series
'the daily show', # All episodes for this item belong to an unknown season
'the oc',
'the office',
'the universe',
'the wire',
'twilight zone',
'ufo hunters',
'weeds',
'zzkjsdfglkjfsdg') # This item does not correspond to any TV series
#titles=('',) # For testing a single or limited number of TV-series
for title in titles:
print title+':\n'
print getEps(title,debug=True)+'\n'+'_'*72+'\n'
if add_noplot:
print title+': '+getEps(title+' /noplot',debug=True)++'\n''_'*72+'\n'
# Run tests
if __name__=='__main__': getEps_test()
|
While TV.com may provide more accurate schedule information, IMDb was chosen here as the data source because a library for accessing it, namely IMDbPY, is available.