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…? […]