What programme was on BBC1 at…?

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?

Tags: , , , , ,

One Response to “What programme was on BBC1 at…?”

  1. [...] dale lane fan of all things mobile, father of small girls, IBM code monkey, youth charity trustee… « What programme was on BBC1 at…? [...]