After my absence, I thought I’d come back with something quick and fun – the result of half an hour’s playing with a new (to me) API.
The problem that I wanted to look into was: What programme was on TV on a given channel at a given time?
And how can I find this out programmatically?
The first thing that I came across was the getProgrammes service in the beta BBC Web API.
As I expect from the forward-thinking BBC, it’s pretty awesome: a simple API that gives you an XML document containing the programmes schedule for the specified time window.
The documentation on the BBC site is pretty self-explanatory. It gives all the information you need to start playing with the API – either using the form on the BBC page, or by sending it a few requests using wget.
wget -O - "http://www0.rdthdo.bbc.co.uk/cgi-perl/api/query.pl?method=bbc.schedule.getProgrammes&channel_id=BBCOne&format=simple&detail=schedule&start=2009-07-10T21:00:00Z&end=2009-07-10T22:30:00Z" <rsp stat="ok"> <schedule> <programme programme_id="crid://bbc.co.uk/272940021" title="Torchwood: Children of Earth"> <synopsis>Day Five: Gwen stands alone as the final sanction begins, and the world descends into anarchy. Contains adult themes. Also in HD. [AD,S]</synopsis> <channel_id>BBCOne</channel_id> <start>2009-07-10T20:00:00Z</start> <duration>01:00:00</duration> </programme> <programme programme_id="crid://bbc.co.uk/272934185" title="BBC News at Ten"> <synopsis>The latest national and international news, with reports from BBC correspondents worldwide. [S]</synopsis> <channel_id>BBCOne</channel_id> <start>2009-07-10T21:00:00Z</start> <duration>00:25:00</duration> </programme> <programme programme_id="crid://bbc.co.uk/272937816" title="BBC London News"> <synopsis>The latest stories from the BBC London newsroom. Followed by Weather. [S]</synopsis> <channel_id>BBCOne</channel_id> <start>2009-07-10T21:25:00Z</start> <duration>00:10:00</duration> </programme> <programme programme_id="crid://bbc.co.uk/272937814" title="Friday Night with Jonathan Ross"> <synopsis>23/25. Jonathan Ross is joined by fashion designer Dame Vivienne Westwood, Top Gear's James May and American singer/songwriter Rufus Wainwright. With music from Paolo Nutini. Also in HD. [S]</synopsis> <channel_id>BBCOne</channel_id> <start>2009-07-10T21:35:00Z</start> <duration>01:00:00</duration> </programme> </schedule> </rsp>
The next step was to knock up a quick bit of Java to try it:
import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URL; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class BBCSchedule { public static void main(String[] args) { // what TV channel? String channel = "BBCOne"; // what time did the TV go on? GregorianCalendar startTime = new GregorianCalendar(TimeZone.getTimeZone("GMT")); startTime.set(2009, GregorianCalendar.JULY, 10, 19, 0, 0); // what time did the TV go off? GregorianCalendar finishTime = new GregorianCalendar(TimeZone.getTimeZone("GMT")); finishTime.set(2009, GregorianCalendar.JULY, 10, 20, 30, 0); // query BBC API for what programmes were on at this time try { // ISO datetime format used by BBC DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // BBC API works in GMT - so need to convert all data to and from this df.setTimeZone(TimeZone.getTimeZone("GMT")); String start = df.format(startTime.getTime()); String end = df.format(finishTime.getTime()); // web services API // documented at http://www0.rdthdo.bbc.co.uk/services/api/bbc.schedule.getProgrammes.html URL url = new URL( "http://www0.rdthdo.bbc.co.uk/cgi-perl/api/query.pl?method=bbc.schedule.getProgrammes&channel_id=" + channel + "&format=simple&detail=schedule&start=" + start + "&end=" + end); // send request HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setRequestMethod("GET"); // create an XML object from the response DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse(connection.getInputStream()); // parse the XML response using XPath XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("/rsp/schedule/programme"); // for each node in the tree, pick out a few fields NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) { // TODO: using a whole new XPath query to pick out attributes // is a quick-and-dirty hack - would be more efficient to // use a single, smarter query // This will do for proof-of-concept, though expr = xpath.compile("/rsp/schedule/programme[" + (i + 1) + "]/@title"); String progTitle = (String) expr.evaluate(doc, XPathConstants.STRING); expr = xpath.compile("/rsp/schedule/programme[" + (i + 1) + "]/start"); String progStart = (String) expr.evaluate(doc, XPathConstants.STRING); Date progStartDate = df.parse(progStart); expr = xpath.compile("/rsp/schedule/programme[" + (i + 1) + "]/duration"); String progDuration = (String) expr.evaluate(doc, XPathConstants.STRING); // TEST - display the start time, duration and title of the programme System.out.println(progStartDate.toString() + " :: " + progDuration + " ==> " + progTitle); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (XPathExpressionException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } }
Running this outputs:
Fri Jul 10 19:30:00 BST 2009 :: 00:30:00 ==> Air Medics Fri Jul 10 20:00:00 BST 2009 :: 00:30:00 ==> EastEnders Fri Jul 10 20:30:00 BST 2009 :: 00:30:00 ==> Celebrity MasterChef Fri Jul 10 21:00:00 BST 2009 :: 01:00:00 ==> Torchwood: Children of Earth
(Yup – Torchwood was great, wasn’t it?)
It’s impressive how simple this was to do. (Although it does mean I’m a little less impressed with the (very slick) BBC Listings app on my Android phone 😉 )
The only problem is that the BBC only provide an API for their own channels. What if I want to know what was on ITV last night?
[…] dale lane fan of all things mobile, father of small girls, IBM code monkey, youth charity trustee… « What programme was on BBC1 at…? […]