{"id":818,"date":"2009-07-27T22:32:29","date_gmt":"2009-07-27T22:32:29","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=818"},"modified":"2009-07-27T22:45:04","modified_gmt":"2009-07-27T22:45:04","slug":"what-programme-was-on-bbc1-at","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=818","title":{"rendered":"What programme was on BBC1 at&#8230;?"},"content":{"rendered":"<p>After <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=815\">my absence<\/a>, I thought I&#8217;d come back with something quick and fun &#8211; the result of half an hour&#8217;s playing with a new (<em>to me<\/em>) API. <\/p>\n<p>The problem that I wanted to look into was: What programme was on TV on a given channel at a given time?<\/p>\n<p>And how can I find this out programmatically?<\/p>\n<p>The first thing that I came across was the <a href=\"http:\/\/www0.rdthdo.bbc.co.uk\/services\/api\/bbc.schedule.getProgrammes.html\" target=\"_blank\">getProgrammes<\/a> service in the beta <a target=\"_blank\" href=\"http:\/\/www0.rdthdo.bbc.co.uk\/services\/api\/\">BBC Web API<\/a>. <\/p>\n<p>As I expect from the forward-thinking BBC, it&#8217;s pretty awesome: a simple API that gives you an XML document containing the programmes schedule for the specified time window. <\/p>\n<p>The documentation on the BBC site is pretty self-explanatory. It gives all the information you need to start playing with the API &#8211; either using the <a href=\"http:\/\/www0.rdthdo.bbc.co.uk\/services\/api\/bbc.schedule.getProgrammes.html\" target=\"_blank\">form on the BBC page<\/a>, or by sending it a few requests using <a href=\"http:\/\/www.gnu.org\/software\/wget\/\" target=\"_blank\">wget<\/a>. <\/p>\n<p><!--more--><\/p>\n<pre style=\"overflow: scroll; font-size: 1.1em; border: thin solid silver; background-color: #eeeeee; padding: 0.8em\">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\" \r\n\r\n&lt;rsp stat=\"ok\"&gt; \r\n        &lt;schedule&gt; \r\n                &lt;programme programme_id=\"crid:\/\/bbc.co.uk\/272940021\" title=\"Torchwood: Children of Earth\"&gt; \r\n                        &lt;synopsis&gt;Day Five: Gwen stands alone as the final sanction begins, and the world descends into anarchy. Contains adult themes. Also in HD. [AD,S]&lt;\/synopsis&gt; \r\n                        &lt;channel_id&gt;BBCOne&lt;\/channel_id&gt; \r\n                        &lt;start&gt;2009-07-10T20:00:00Z&lt;\/start&gt; \r\n                        &lt;duration&gt;01:00:00&lt;\/duration&gt; \r\n                &lt;\/programme&gt; \r\n                &lt;programme programme_id=\"crid:\/\/bbc.co.uk\/272934185\" title=\"BBC News at Ten\"&gt; \r\n                        &lt;synopsis&gt;The latest national and international news, with reports from BBC correspondents worldwide. [S]&lt;\/synopsis&gt; \r\n                        &lt;channel_id&gt;BBCOne&lt;\/channel_id&gt; \r\n                        &lt;start&gt;2009-07-10T21:00:00Z&lt;\/start&gt; \r\n                        &lt;duration&gt;00:25:00&lt;\/duration&gt; \r\n                &lt;\/programme&gt; \r\n                &lt;programme programme_id=\"crid:\/\/bbc.co.uk\/272937816\" title=\"BBC London News\"&gt; \r\n                        &lt;synopsis&gt;The latest stories from the BBC London newsroom. Followed by Weather. [S]&lt;\/synopsis&gt; \r\n                        &lt;channel_id&gt;BBCOne&lt;\/channel_id&gt; \r\n                        &lt;start&gt;2009-07-10T21:25:00Z&lt;\/start&gt; \r\n                        &lt;duration&gt;00:10:00&lt;\/duration&gt; \r\n                &lt;\/programme&gt; \r\n                &lt;programme programme_id=\"crid:\/\/bbc.co.uk\/272937814\" title=\"Friday Night with Jonathan Ross\"&gt; \r\n                        &lt;synopsis&gt;23\/25. Jonathan Ross is joined by fashion designer Dame Vivienne Westwood, Top Gear&apos;s James May and American singer\/songwriter Rufus Wainwright. With music from Paolo Nutini. Also in HD. [S]&lt;\/synopsis&gt; \r\n                        &lt;channel_id&gt;BBCOne&lt;\/channel_id&gt; \r\n                        &lt;start&gt;2009-07-10T21:35:00Z&lt;\/start&gt; \r\n                        &lt;duration&gt;01:00:00&lt;\/duration&gt; \r\n                &lt;\/programme&gt; \r\n        &lt;\/schedule&gt; \r\n&lt;\/rsp&gt; <\/pre>\n<p>The next step was to knock up a quick bit of Java to try it:<\/p>\n<pre style=\"overflow: scroll; font-size: 1em; border: thin solid silver; background-color: #eeeeee; padding: 0.8em\">import java.io.IOException;\r\nimport java.net.HttpURLConnection;\r\nimport java.net.MalformedURLException;\r\nimport java.net.ProtocolException;\r\nimport java.net.URL;\r\nimport java.text.DateFormat;\r\nimport java.text.ParseException;\r\nimport java.text.SimpleDateFormat;\r\nimport java.util.Date;\r\nimport java.util.GregorianCalendar;\r\nimport java.util.TimeZone;\r\n\r\nimport javax.xml.parsers.DocumentBuilder;\r\nimport javax.xml.parsers.DocumentBuilderFactory;\r\nimport javax.xml.parsers.ParserConfigurationException;\r\nimport javax.xml.xpath.XPath;\r\nimport javax.xml.xpath.XPathConstants;\r\nimport javax.xml.xpath.XPathExpression;\r\nimport javax.xml.xpath.XPathExpressionException;\r\nimport javax.xml.xpath.XPathFactory;\r\n\r\nimport org.w3c.dom.Document;\r\nimport org.w3c.dom.NodeList;\r\nimport org.xml.sax.SAXException;\r\n\r\npublic class BBCSchedule {\r\n\r\n    public static void main(String[] args) {\r\n\r\n        \/\/ what TV channel?\r\n        String channel = \"BBCOne\";\r\n\r\n        \/\/ what time did the TV go on?\r\n        GregorianCalendar startTime = new GregorianCalendar(TimeZone.getTimeZone(\"GMT\"));\r\n        startTime.set(2009, GregorianCalendar.JULY, 10, 19, 0, 0);\r\n        \r\n        \/\/ what time did the TV go off?\r\n        GregorianCalendar finishTime = new GregorianCalendar(TimeZone.getTimeZone(\"GMT\"));\r\n        finishTime.set(2009, GregorianCalendar.JULY, 10, 20, 30, 0);\r\n\r\n        \/\/ query BBC API for what programmes were on at this time\r\n        try {\r\n            \/\/ ISO datetime format used by BBC\r\n            DateFormat df = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss\");\r\n            \r\n            \/\/ BBC API works in GMT - so need to convert all data to and from this \r\n            df.setTimeZone(TimeZone.getTimeZone(\"GMT\"));\r\n            String start = df.format(startTime.getTime());\r\n            String end = df.format(finishTime.getTime());\r\n\r\n            \/\/ web services API \r\n            \/\/  documented at http:\/\/www0.rdthdo.bbc.co.uk\/services\/api\/bbc.schedule.getProgrammes.html\r\n            URL url = new URL(\r\n                    \"http:\/\/www0.rdthdo.bbc.co.uk\/cgi-perl\/api\/query.pl?method=bbc.schedule.getProgrammes&channel_id=\" + channel\r\n                            + \"&format=simple&detail=schedule&start=\"\r\n                            + start + \"&end=\" + end);\r\n            \r\n            \/\/ send request\r\n            HttpURLConnection connection = (HttpURLConnection) url.openConnection();\r\n            connection.setDoInput(true);\r\n            connection.setRequestMethod(\"GET\");\r\n\r\n            \/\/ create an XML object from the response\r\n            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();\r\n            domFactory.setNamespaceAware(true);\r\n            DocumentBuilder builder = domFactory.newDocumentBuilder();\r\n            Document doc = builder.parse(connection.getInputStream());\r\n\r\n            \/\/ parse the XML response using XPath\r\n            XPathFactory factory = XPathFactory.newInstance();\r\n            XPath xpath = factory.newXPath();\r\n            XPathExpression expr = xpath.compile(\"\/rsp\/schedule\/programme\");\r\n\r\n            \/\/ for each node in the tree, pick out a few fields\r\n            NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);\r\n            for (int i = 0; i &lt; nodes.getLength(); i++) {\r\n            \t\/\/ TODO: using a whole new XPath query to pick out attributes\r\n            \t\/\/    is a quick-and-dirty hack - would be more efficient to \r\n            \t\/\/    use a single, smarter query\r\n            \t\/\/    This will do for proof-of-concept, though\r\n            \t\r\n                expr = xpath.compile(\"\/rsp\/schedule\/programme[\" + (i + 1) + \"]\/@title\");\r\n                String progTitle = (String) expr.evaluate(doc, XPathConstants.STRING);\r\n\r\n                expr = xpath.compile(\"\/rsp\/schedule\/programme[\" + (i + 1) + \"]\/start\");\r\n                String progStart = (String) expr.evaluate(doc, XPathConstants.STRING);\r\n                Date progStartDate = df.parse(progStart);\r\n\r\n                expr = xpath.compile(\"\/rsp\/schedule\/programme[\" + (i + 1) + \"]\/duration\");\r\n                String progDuration = (String) expr.evaluate(doc, XPathConstants.STRING);\r\n\r\n                \/\/ TEST - display the start time, duration and title of the programme\r\n                System.out.println(progStartDate.toString() + \" :: \" + progDuration + \"  ==&gt; \" + progTitle);\r\n            }\r\n\r\n        } catch (MalformedURLException e) {\r\n            e.printStackTrace();\r\n        } catch (ProtocolException e) {\r\n            e.printStackTrace();\r\n        } catch (IOException e) {\r\n            e.printStackTrace();\r\n        } catch (SAXException e) {\r\n            e.printStackTrace();\r\n        } catch (ParserConfigurationException e) {\r\n            e.printStackTrace();\r\n        } catch (XPathExpressionException e) {\r\n            e.printStackTrace();\r\n        } catch (ParseException e) {\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}<\/pre>\n<p>Running this outputs:<\/p>\n<pre style=\"overflow: scroll; font-size: 1em; border: thin solid silver; background-color: #eeeeee; padding: 0.8em\">Fri Jul 10 19:30:00 BST 2009 :: 00:30:00  ==&gt; Air Medics\r\nFri Jul 10 20:00:00 BST 2009 :: 00:30:00  ==&gt; EastEnders\r\nFri Jul 10 20:30:00 BST 2009 :: 00:30:00  ==&gt; Celebrity MasterChef\r\nFri Jul 10 21:00:00 BST 2009 :: 01:00:00  ==&gt; Torchwood: Children of Earth<\/pre>\n<p>(<em>Yup &#8211; Torchwood was great, wasn&#8217;t it?<\/em>)<\/p>\n<p>It&#8217;s impressive how simple this was to do. (Although it does mean I&#8217;m a little less impressed with the (very slick) <a href=\"http:\/\/jimblackler.net\/blog\/?p=72\" target=\"_blank\">BBC Listings app<\/a> on my Android phone \ud83d\ude09 )<\/p>\n<p>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?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After my absence, I thought I&#8217;d come back with something quick and fun &#8211; the result of half an hour&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[51,50,306,398,399,572],"class_list":["post-818","post","type-post","status-publish","format-standard","hentry","category-code","tag-backstage","tag-bbc","tag-television","tag-tv","tag-tv-guide","tag-web"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/818","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=818"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/818\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=818"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=818"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=818"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}