Posted by benj1 on Mon 2nd Nov 22:36 (modification of post by view diff)
View followups from benj1 | download | new post
- #! /usr/bin/env python
- #
- # Author: Ben Holroyd <holroyd.ben@gmail.com>
- # License: GPL 3.0+
- #
- # Usage:
- # Put an entry in ~/.config/openbox/menu.xml:
- # <menu id="Listing" label="listing" execute="~/.config/openbox/scripts/tvlisting" />
- #called without args just checks that listings are up to date for that day
- #-t prints in plain text to stdout
- #-p is for use in pipe menus
- from HTMLParser import HTMLParser
- from urllib import FancyURLopener
- from threading import Thread
- import datetime,os
- from optparse import OptionParser
- #dict of channels with channel codes, need to get from radio times website
- channellistdict = {'BBC1':'92','BBC2':'105','ITV':'26','Channel4':'132','Five':'134'}
- #need a separate list, as dict gets out of order
- channellist=['BBC1','BBC2','ITV','Channel4','Five']
- #where temporary files are kept
- tmpfile = "/tmp"
- #dont touch
- tmpfile=os.path.join(tmpfile,"%%s-%s" % datetime.date.today())
- address="http://www.radiotimes.com/ListingsServlet?event=4&jspGridLocation=%%2Fjsp%%2Ftv_listings_grid.jsp&jspListLocation=%%2Fjsp%%2Ftv_listings_single.jsp&jspError=%%2Fjsp%%2Ferror.jsp&listingsFormat=L&channels=%s"
- class parser(HTMLParser):
- def __init__(self, data, channel):
- """parse downloaded pages, and save by channel in tmp"""
- HTMLParser.__init__(self)
- self.bltime = False
- self.bltitle = False
- self.time = ''
- #hack-- htmlparser doesnt like original form, even though its in comments
- data = data.replace("</scr'+'ipt>","</script>")
- self.file = open(tmpfile % channel, 'w')
- self.feed(data)
- def handle_starttag(self, tag, attrs):
- if tag == 'p' and attrs:
- if attrs[0][1] == 'startTime':
- self.bltime = True
- if attrs[0][1] == 'progTitle':
- self.bltitle = True
- def handle_data(self,data):
- if self.bltime == True:
- self.time = data
- self.bltime = False
- if self.bltitle == True:
- self.file.write('%s%%%s\n' % (data, self.time))
- #print "Title: ",data, 'time: ', self.time
- self.bltitle = False
- class downloader(Thread):
- """threaded downloader for webpages"""
- def __init__ (self, url, channelcode, channel):
- Thread.__init__(self)
- self.channel = channel
- self.channelcode = channelcode
- self.url = url
- def run(self):
- try:
- data = FancyURLopener().open(self.url % self.channelcode).read()
- except IOError:
- pass
- parser(data, self.channel)
- class printer():
- """print parsed files"""
- def __init__(self, channel):
- self.now = datetime.datetime.now()
- self.channel = channel
- #check we have listings for the correct day
- if not os.path.exists(tmpfile % self.channel):
- downloader(address,channellistdict[self.channel],self.channel).start()
- file = open(tmpfile % self.channel, 'r').read()
- data = [line.split('%') for line in file.split('\n') if len(line) > 0]
- #find most recent program, then trim 'data' to fit.
- for index, [programme, time] in enumerate(data):
- if self.comparetime(time):
- if index == 0: index = 1 #just in case a programme starts just before midnight
- self.data = data[index-1:]
- break
- def comparetime (self,cmp_time):
- """returns true if time supplied is bigger than current time"""
- hour, minute = self.now.hour, self.now.minute
- #converts 'hh:mm a/pm' to int, pam strips pm and am from string
- cmp_hour,cmp_minute = map(int, cmp_time.rstrip('pam').split(':'))
- #convert to 24hr time, & sort 12am, 12pm
- if cmp_time.endswith('pm') and cmp_hour != 12: cmp_hour += 12
- if cmp_time.endswith('am') and cmp_hour == 12: cmp_hour -= 12
- return (cmp_hour, cmp_minute) > (hour, minute)
- def showxmlmenu(self):
- print " <menu id=\"%s\" label=\"%s\">" % (self.channel,self.channel)
- print " <item label=\"Now: %s %s\"/>" % (self.data[0][0],self.data[0][1])
- print " <item label=\"Next: %s %s\"/>" % (self.data[1][0],self.data[1][1])
- print " <menu id=\"Then%s\" label=\"Then\">" % (self.channel)
- for programme, time in self.data[2:]:
- print " <item label=\"%s (%s)\"/>" % (programme,time)
- print " </menu>"
- print " </menu>"
- def showplaintext(self):
- for programme, time in self.data:
- print programme, ' Starts: ', time
- parser = OptionParser(
- version=" %prog V0.1 Ben Holroyd",
- description = "%prog - print tv listings, if called without options will check\nthat the listings are upto date and redownload if needed",
- usage = "%prog [-tp] [--text] [--pipe] [--help]")
- parser.add_option("-t", "--text", action="store_true", dest="text", default=False, help="print tvlistings in plain text")
- parser.add_option("-p", "--pipe", action="store_true", dest="pipe", default=False, help="print listings in xml suitable for obmenu")
- (options, args) = parser.parse_args()
- for entry in channellist: #check files are up to date
- if not os.path.exists(tmpfile % entry):
- downloader(address,channellistdict[entry],entry).start()
- if options.text:
- for entry in channellist:
- print "\n\033[01;04m%s\033[00;00m" % entry #print bold & underlined
- printer(entry).showplaintext()
- elif options.pipe :
- print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
- print "<openbox_pipe_menu>"
- for entry in channellist: printer(entry).showxmlmenu()
- print "</openbox_pipe_menu>"
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.