00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 __title__ ="bbciplayer_api - Simple-to-use Python interface to the BBC iPlayer RSS feeds (http://www.bbc.co.uk)"
00015 __author__="R.D. Vaughan"
00016 __purpose__='''
00017 This python script is intended to perform a variety of utility functions to search and access text
00018 meta data, video and image URLs from the BBC iPlayer Web site. These routines process RSS feeds
00019 provided by BBC (http://www.bbc.co.uk). The specific BBC iPlayer RSS feeds that are processed are controled through a user XML preference file usually found at
00020 "~/.mythtv/MythNetvision/userGrabberPrefs/bbciplayer.xml"
00021 '''
00022
00023 __version__="v0.1.3"
00024
00025
00026
00027
00028
00029
00030
00031
00032 import os, struct, sys, re, time, datetime, shutil, urllib, re
00033 import logging
00034 from socket import gethostname, gethostbyname
00035 from threading import Thread
00036 from copy import deepcopy
00037 from operator import itemgetter, attrgetter
00038 from MythTV import MythXML
00039 from bbciplayer_exceptions import (BBCUrlError, BBCHttpError, BBCRssError, BBCVideoNotFound, BBCConfigFileError, BBCUrlDownloadError)
00040
00041 class OutStreamEncoder(object):
00042 """Wraps a stream with an encoder"""
00043 def __init__(self, outstream, encoding=None):
00044 self.out = outstream
00045 if not encoding:
00046 self.encoding = sys.getfilesystemencoding()
00047 else:
00048 self.encoding = encoding
00049
00050 def write(self, obj):
00051 """Wraps the output stream, encoding Unicode strings with the specified encoding"""
00052 if isinstance(obj, unicode):
00053 try:
00054 self.out.write(obj.encode(self.encoding))
00055 except IOError:
00056 pass
00057 else:
00058 try:
00059 self.out.write(obj)
00060 except IOError:
00061 pass
00062
00063 def __getattr__(self, attr):
00064 """Delegate everything but write to the stream"""
00065 return getattr(self.out, attr)
00066 sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
00067 sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')
00068
00069
00070 try:
00071 from StringIO import StringIO
00072 from lxml import etree
00073 except Exception, e:
00074 sys.stderr.write(u'\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e)
00075 sys.exit(1)
00076
00077
00078
00079
00080
00081 version = ''
00082 for digit in etree.LIBXML_VERSION:
00083 version+=str(digit)+'.'
00084 version = version[:-1]
00085 if version < '2.7.2':
00086 sys.stderr.write(u'''
00087 ! Error - The installed version of the "lxml" python library "libxml" version is too old.
00088 At least "libxml" version 2.7.2 must be installed. Your version is (%s).
00089 ''' % version)
00090 sys.exit(1)
00091
00092
00093 class Videos(object):
00094 """Main interface to http://www.bbciplayer.com/
00095 This is done to support a common naming framework for all python Netvision plugins no matter their site
00096 target.
00097
00098 Supports search methods
00099 The apikey is a not required to access http://www.bbciplayer.com/
00100 """
00101 def __init__(self,
00102 apikey,
00103 mythtv = True,
00104 interactive = False,
00105 select_first = False,
00106 debug = False,
00107 custom_ui = None,
00108 language = None,
00109 search_all_languages = False,
00110 ):
00111 """apikey (str/unicode):
00112 Specify the target site API key. Applications need their own key in some cases
00113
00114 mythtv (True/False):
00115 When True, the returned meta data is being returned has the key and values massaged to match MythTV
00116 When False, the returned meta data is being returned matches what target site returned
00117
00118 interactive (True/False): (This option is not supported by all target site apis)
00119 When True, uses built-in console UI is used to select the correct show.
00120 When False, the first search result is used.
00121
00122 select_first (True/False): (This option is not supported currently implemented in any grabbers)
00123 Automatically selects the first series search result (rather
00124 than showing the user a list of more than one series).
00125 Is overridden by interactive = False, or specifying a custom_ui
00126
00127 debug (True/False):
00128 shows verbose debugging information
00129
00130 custom_ui (xx_ui.BaseUI subclass): (This option is not supported currently implemented in any grabbers)
00131 A callable subclass of interactive class (overrides interactive option)
00132
00133 language (2 character language abbreviation): (This option is not supported by all target site apis)
00134 The language of the returned data. Is also the language search
00135 uses. Default is "en" (English). For full list, run..
00136
00137 search_all_languages (True/False): (This option is not supported by all target site apis)
00138 By default, a Netvision grabber will only search in the language specified using
00139 the language option. When this is True, it will search for the
00140 show in any language
00141
00142 """
00143 self.config = {}
00144 self.mythxml = MythXML()
00145
00146 if apikey is not None:
00147 self.config['apikey'] = apikey
00148 else:
00149 pass
00150
00151 self.config['debug_enabled'] = debug
00152 self.common = common
00153 self.common.debug = debug
00154
00155 self.log_name = u'BBCiPlayer_Grabber'
00156 self.common.logger = self.common.initLogger(path=sys.stderr, log_name=self.log_name)
00157 self.logger = self.common.logger
00158
00159 self.config['custom_ui'] = custom_ui
00160
00161 self.config['interactive'] = interactive
00162
00163 self.config['select_first'] = select_first
00164
00165 self.config['search_all_languages'] = search_all_languages
00166
00167 self.error_messages = {'BBCUrlError': u"! Error: The URL (%s) cause the exception error (%s)\n", 'BBCHttpError': u"! Error: An HTTP communications error with the BBC was raised (%s)\n", 'BBCRssError': u"! Error: Invalid RSS meta data\nwas received from the BBC error (%s). Skipping item.\n", 'BBCVideoNotFound': u"! Error: Video search with the BBC did not return any results (%s)\n", 'BBCConfigFileError': u"! Error: bbc_config.xml file missing\nit should be located in and named as (%s).\n", 'BBCUrlDownloadError': u"! Error: Downloading a RSS feed or Web page (%s).\n", }
00168
00169
00170 self.channel = {'channel_title': u'BBC iPlayer', 'channel_link': u'http://www.bbc.co.uk', 'channel_description': u"BBC iPlayer is our service that lets you catch up with radio and television programmes from the past week.", 'channel_numresults': 0, 'channel_returned': 1, u'channel_startindex': 0}
00171
00172
00173 self.countryCodeParsers = [
00174 etree.XPath('.//a[@class="episode-title title-link cta-video"]', namespaces=self.common.namespaces),
00175 etree.XPath('.//div[@class="feature video"]', namespaces=self.common.namespaces),
00176 etree.XPath('.//atm:category[@term="TV"]', namespaces=self.common.namespaces),
00177 ]
00178
00179
00180 self.s_e_Patterns = [
00181
00182 re.compile(u'''^.+?Series\\ (?P<seasno>[0-9]+).*.+?Episode\\ (?P<epno>[0-9]+).*$''', re.UNICODE),
00183
00184 re.compile(u'''^.+?Series\\ (?P<seasno>[0-9]+)\\ \\-\\ (?P<epno>[0-9]+).*$''', re.UNICODE),
00185
00186 re.compile(u'''^.+?Series\\ (?P<seasno>[0-9]+).*.+?Part\\ (?P<epno>[0-9]+).*$''', re.UNICODE),
00187
00188 re.compile(u'''^.+?Series\\ (?P<seasno>[0-9]+)\\:\\ Programme\\ (?P<epno>[0-9]+).*$''', re.UNICODE),
00189
00190 re.compile(u'''^.+?Series\\ (?P<seasno>[0-9]+).*$''', re.UNICODE),
00191
00192 re.compile(u'''^.+?Episode\\ (?P<seasno>[0-9]+).*$''', re.UNICODE),
00193 ]
00194
00195 self.channel_icon = u'%SHAREDIR%/mythnetvision/icons/bbciplayer.jpg'
00196
00197 self.config[u'image_extentions'] = ["png", "jpg", "bmp"]
00198
00199
00200
00201
00202
00203
00204
00205
00206 def getBBCConfig(self):
00207 ''' Read the MNV BBC iPlayer grabber "bbc_config.xml" configuration file
00208 return nothing
00209 '''
00210
00211 url = u'file://%s/nv_python_libs/configs/XML/bbc_config.xml' % (baseProcessingDir, )
00212 if not os.path.isfile(url[7:]):
00213 raise BBCConfigFileError(self.error_messages['BBCConfigFileError'] % (url[7:], ))
00214
00215 if self.config['debug_enabled']:
00216 print url
00217 print
00218 try:
00219 self.bbciplayer_config = etree.parse(url)
00220 except Exception, e:
00221 raise BBCUrlError(self.error_messages['BBCUrlError'] % (url, errormsg))
00222 return
00223
00224
00225
00226 def getUserPreferences(self):
00227 '''Read the bbciplayer_config.xml and user preference bbciplayer.xml file.
00228 If the bbciplayer.xml file does not exist then copy the default.
00229 return nothing
00230 '''
00231
00232 self.getBBCConfig()
00233
00234
00235 userPreferenceFile = self.bbciplayer_config.find('userPreferenceFile').text
00236 if userPreferenceFile[0] == '~':
00237 self.bbciplayer_config.find('userPreferenceFile').text = u"%s%s" % (os.path.expanduser(u"~"), userPreferenceFile[1:])
00238
00239
00240 if not os.path.isfile(self.bbciplayer_config.find('userPreferenceFile').text):
00241
00242 prefDir = self.bbciplayer_config.find('userPreferenceFile').text.replace(u'/bbciplayer.xml', u'')
00243 if not os.path.isdir(prefDir):
00244 os.makedirs(prefDir)
00245 defaultConfig = u'%s/nv_python_libs/configs/XML/defaultUserPrefs/bbciplayer.xml' % (baseProcessingDir, )
00246 shutil.copy2(defaultConfig, self.bbciplayer_config.find('userPreferenceFile').text)
00247
00248
00249 url = u'file://%s' % (self.bbciplayer_config.find('userPreferenceFile').text, )
00250 if self.config['debug_enabled']:
00251 print url
00252 print
00253 try:
00254 self.userPrefs = etree.parse(url)
00255 except Exception, e:
00256 raise BBCUrlError(self.error_messages['BBCUrlError'] % (url, errormsg))
00257 return
00258
00259
00260 def setCountry(self, item):
00261 '''Parse the item information (HTML or RSS/XML) to identify if the content is a video or
00262 audio file. Set the contry code if a video is detected as it can only be played in the "UK"
00263 return "uk" if a video type was detected.
00264 return None if a video type was NOT detected.
00265 '''
00266 countryCode = None
00267 for xpathP in self.countryCodeParsers:
00268 if len(xpathP(item)):
00269 countryCode = u'uk'
00270 break
00271 return countryCode
00272
00273
00274
00275 def getSeasonEpisode(self, title):
00276 ''' Check is there is any season or episode number information in an item's title
00277 return array of season and/or episode numbers
00278 return array with None values
00279 '''
00280 s_e = [None, None]
00281 for index in range(len(self.s_e_Patterns)):
00282 match = self.s_e_Patterns[index].match(title)
00283 if not match:
00284 continue
00285 if index < 4:
00286 s_e[0], s_e[1] = match.groups()
00287 break
00288 elif index == 4:
00289 s_e[0] = match.groups()[0]
00290 break
00291 elif index == 5:
00292 s_e[1] = match.groups()[0]
00293 break
00294 return s_e
00295
00296
00297
00298
00299
00300
00301
00302
00303 def processVideoUrl(self, url):
00304 playerUrl = self.mythxml.getInternetContentUrl("nv_python_libs/configs/HTML/bbciplayer.html", \
00305 url)
00306 return playerUrl
00307
00308 def searchTitle(self, title, pagenumber, pagelen):
00309 '''Key word video search of the BBC iPlayer web site
00310 return an array of matching item elements
00311 return
00312 '''
00313
00314 orgUrl = self.bbciplayer_config.find('searchURLS').xpath(".//href")[0].text
00315
00316 try:
00317 searchVar = u'/?q=%s&page=%s' % (urllib.quote(title.encode("utf-8")), pagenumber)
00318 except UnicodeDecodeError:
00319 searchVar = u'/?q=%s&page=%s' % (urllib.quote(title), pagenumber)
00320
00321 url = self.bbciplayer_config.find('searchURLS').xpath(".//href")[0].text+searchVar
00322
00323 if self.config['debug_enabled']:
00324 print url
00325 print
00326
00327 self.bbciplayer_config.find('searchURLS').xpath(".//href")[0].text = url
00328
00329
00330 try:
00331 resultTree = self.common.getUrlData(self.bbciplayer_config.find('searchURLS'), pageFilter=self.bbciplayer_config.find('searchURLS').xpath(".//pageFilter")[0].text)
00332 except Exception, errormsg:
00333
00334 self.bbciplayer_config.find('searchURLS').xpath(".//href")[0].text = orgUrl
00335 raise BBCUrlDownloadError(self.error_messages['BBCUrlDownloadError'] % (errormsg))
00336
00337
00338 self.bbciplayer_config.find('searchURLS').xpath(".//href")[0].text = orgUrl
00339
00340 if resultTree is None:
00341 raise BBCVideoNotFound(u"No BBC Video matches found for search value (%s)" % title)
00342
00343 searchResults = resultTree.xpath('//result//li')
00344 if not len(searchResults):
00345 raise BBCVideoNotFound(u"No BBC Video matches found for search value (%s)" % title)
00346
00347
00348
00349 pubDate = datetime.datetime.now().strftime(self.common.pubDateFormat)
00350
00351
00352 if self.userPrefs.find('displayURL') != None:
00353 urlType = self.userPrefs.find('displayURL').text
00354 else:
00355 urlType = u'fullscreen'
00356
00357
00358 audioFilter = etree.XPath('contains(./@class,"audio") or contains(./../../@class,"audio")')
00359 linkFilter = etree.XPath(u".//div[@class='episode-info ']//a")
00360 titleFilter = etree.XPath(u".//div[@class='episode-info ']//a")
00361 descFilter = etree.XPath(u".//div[@class='episode-info ']//p[@class='episode-synopsis']")
00362 thumbnailFilter = etree.XPath(u".//span[@class='episode-image cta-play']//img")
00363 itemDict = {}
00364 for result in searchResults:
00365 tmpLink = linkFilter(result)
00366 if not len(tmpLink):
00367 continue
00368 bbciplayerItem = etree.XML(self.common.mnvItem)
00369
00370 audioTF = audioFilter(result)
00371
00372 link = tmpLink[0].attrib['href']
00373 if urlType == 'bigscreen':
00374 link = u'http://www.bbc.co.uk/iplayer/bigscreen%s' % link.replace(u'/iplayer',u'')
00375 elif urlType == 'bbcweb':
00376 link = u'http://www.bbc.co.uk'+ link
00377 else:
00378 if not audioTF:
00379 link = link.replace(u'/iplayer/episode/', u'')
00380 index = link.find(u'/')
00381 link = link[:index]
00382 link = self.processVideoUrl(link);
00383 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}customhtml").text = 'true'
00384 else:
00385 link = u'http://www.bbc.co.uk'+ link
00386 link = self.common.ampReplace(link)
00387
00388 title = self.common.massageText(titleFilter(result)[0].attrib['title'].strip())
00389 description = self.common.massageText(etree.tostring(descFilter(result)[0], method="text", encoding=unicode).strip())
00390
00391
00392 bbciplayerItem.find('title').text = title
00393 bbciplayerItem.find('author').text = u'BBC'
00394 bbciplayerItem.find('pubDate').text = pubDate
00395 bbciplayerItem.find('description').text = description
00396 bbciplayerItem.find('link').text = link
00397 bbciplayerItem.xpath('.//media:thumbnail', namespaces=self.common.namespaces)[0].attrib['url'] = self.common.ampReplace(thumbnailFilter(result)[0].attrib['src'])
00398 bbciplayerItem.xpath('.//media:content', namespaces=self.common.namespaces)[0].attrib['url'] = link
00399
00400 if audioTF:
00401 countCode = None
00402 else:
00403 countCode = u'uk'
00404 if countCode:
00405 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}country").text = countCode
00406 s_e = self.getSeasonEpisode(title)
00407 if s_e[0]:
00408 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}season").text = s_e[0]
00409 if s_e[1]:
00410 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}episode").text = s_e[1]
00411 itemDict[title.lower()] = bbciplayerItem
00412
00413 if not len(itemDict.keys()):
00414 raise BBCVideoNotFound(u"No BBC Video matches found for search value (%s)" % title)
00415
00416
00417 self.channel['channel_numresults'] = len(itemDict)
00418
00419 return [itemDict, resultTree.xpath('//pageInfo')[0].text]
00420
00421
00422
00423 def searchForVideos(self, title, pagenumber):
00424 """Common name for a video search. Used to interface with MythTV plugin NetVision
00425 """
00426
00427 try:
00428 self.getUserPreferences()
00429 except Exception, e:
00430 sys.stderr.write(u'%s' % e)
00431 sys.exit(1)
00432
00433 if self.config['debug_enabled']:
00434 print "self.userPrefs:"
00435 sys.stdout.write(etree.tostring(self.userPrefs, encoding='UTF-8', pretty_print=True))
00436 print
00437
00438
00439
00440
00441
00442
00443
00444 try:
00445 data = self.searchTitle(title, pagenumber, self.page_limit)
00446 except BBCVideoNotFound, msg:
00447 sys.stderr.write(u"%s\n" % msg)
00448 sys.exit(0)
00449 except BBCUrlError, msg:
00450 sys.stderr.write(u'%s\n' % msg)
00451 sys.exit(1)
00452 except BBCHttpError, msg:
00453 sys.stderr.write(self.error_messages['BBCHttpError'] % msg)
00454 sys.exit(1)
00455 except BBCRssError, msg:
00456 sys.stderr.write(self.error_messages['BBCRssError'] % msg)
00457 sys.exit(1)
00458 except Exception, e:
00459 sys.stderr.write(u"! Error: Unknown error during a Video search (%s)\nError(%s)\n" % (title, e))
00460 sys.exit(1)
00461
00462
00463 rssTree = etree.XML(self.common.mnvRSS+u'</rss>')
00464
00465
00466 itemCount = len(data[0].keys())
00467 if data[1] == 'true':
00468 self.channel['channel_returned'] = itemCount
00469 self.channel['channel_startindex'] = itemCount
00470 self.channel['channel_numresults'] = itemCount+(self.page_limit*(int(pagenumber)-1)+1)
00471 else:
00472 self.channel['channel_returned'] = itemCount+(self.page_limit*(int(pagenumber)-1))
00473 self.channel['channel_startindex'] = self.channel['channel_returned']
00474 self.channel['channel_numresults'] = self.channel['channel_returned']
00475
00476
00477 channelTree = self.common.mnvChannelElement(self.channel)
00478 rssTree.append(channelTree)
00479
00480 lastKey = None
00481 for key in sorted(data[0].keys()):
00482 if lastKey != key:
00483 channelTree.append(data[0][key])
00484 lastKey = key
00485
00486
00487 sys.stdout.write(u'<?xml version="1.0" encoding="UTF-8"?>\n')
00488 sys.stdout.write(etree.tostring(rssTree, encoding='UTF-8', pretty_print=True))
00489 sys.exit(0)
00490
00491
00492 def displayTreeView(self):
00493 '''Gather the BBC iPlayer feeds then get a max page of videos meta data in each of them
00494 Display the results and exit
00495 '''
00496
00497 try:
00498 self.getUserPreferences()
00499 except Exception, e:
00500 sys.stderr.write(u'%s' % e)
00501 sys.exit(1)
00502
00503 if self.config['debug_enabled']:
00504 print "self.userPrefs:"
00505 sys.stdout.write(etree.tostring(self.userPrefs, encoding='UTF-8', pretty_print=True))
00506 print
00507
00508
00509 self.channel_icon = self.common.ampReplace(self.channel_icon)
00510
00511
00512 rssTree = etree.XML(self.common.mnvRSS+u'</rss>')
00513
00514
00515 channelTree = self.common.mnvChannelElement(self.channel)
00516 rssTree.append(channelTree)
00517
00518
00519 searchResultTree = []
00520 searchFilter = etree.XPath(u"//item")
00521 userSearchStrings = u'userSearchStrings'
00522 if self.userPrefs.find(userSearchStrings) != None:
00523 userSearch = self.userPrefs.find(userSearchStrings).xpath('./userSearch')
00524 if len(userSearch):
00525 for searchDetails in userSearch:
00526 try:
00527 data = self.searchTitle(searchDetails.find('searchTerm').text, 1, self.page_limit)
00528 except BBCVideoNotFound, msg:
00529 sys.stderr.write(u"%s\n" % msg)
00530 continue
00531 except BBCUrlError, msg:
00532 sys.stderr.write(u'%s\n' % msg)
00533 continue
00534 except BBCHttpError, msg:
00535 sys.stderr.write(self.error_messages['BBCHttpError'] % msg)
00536 continue
00537 except BBCRssError, msg:
00538 sys.stderr.write(self.error_messages['BBCRssError'] % msg)
00539 continue
00540 except Exception, e:
00541 sys.stderr.write(u"! Error: Unknown error during a Video search (%s)\nError(%s)\n" % (title, e))
00542 continue
00543 dirElement = etree.XML(u'<directory></directory>')
00544 dirElement.attrib['name'] = self.common.massageText(searchDetails.find('dirName').text)
00545 dirElement.attrib['thumbnail'] = self.channel_icon
00546 lastKey = None
00547 for key in sorted(data[0].keys()):
00548 if lastKey != key:
00549 dirElement.append(data[0][key])
00550 lastKey = key
00551 channelTree.append(dirElement)
00552 continue
00553
00554
00555 rssData = etree.XML(u'<xml></xml>')
00556 for feedType in [u'treeviewURLS', u'userFeeds']:
00557 if self.userPrefs.find(feedType) == None:
00558 continue
00559 if not len(self.userPrefs.find(feedType).xpath('./url')):
00560 continue
00561 for rssFeed in self.userPrefs.find(feedType).xpath('./url'):
00562 urlEnabled = rssFeed.attrib.get('enabled')
00563 if urlEnabled == 'false':
00564 continue
00565 urlName = rssFeed.attrib.get('name')
00566 if urlName:
00567 uniqueName = u'%s;%s' % (urlName, rssFeed.text)
00568 else:
00569 uniqueName = u'RSS;%s' % (rssFeed.text)
00570 url = etree.XML(u'<url></url>')
00571 etree.SubElement(url, "name").text = uniqueName
00572 etree.SubElement(url, "href").text = rssFeed.text
00573 etree.SubElement(url, "filter").text = u"atm:title"
00574 etree.SubElement(url, "filter").text = u"//atm:entry"
00575 etree.SubElement(url, "parserType").text = u'xml'
00576 rssData.append(url)
00577
00578 if self.config['debug_enabled']:
00579 print "rssData:"
00580 sys.stdout.write(etree.tostring(rssData, encoding='UTF-8', pretty_print=True))
00581 print
00582
00583
00584 if rssData.find('url') != None:
00585 try:
00586 resultTree = self.common.getUrlData(rssData)
00587 except Exception, errormsg:
00588 raise BBCUrlDownloadError(self.error_messages['BBCUrlDownloadError'] % (errormsg))
00589 if self.config['debug_enabled']:
00590 print "resultTree:"
00591 sys.stdout.write(etree.tostring(resultTree, encoding='UTF-8', pretty_print=True))
00592 print
00593
00594
00595 if self.userPrefs.find('displayURL') != None:
00596 urlType = self.userPrefs.find('displayURL').text
00597 else:
00598 urlType = u'fullscreen'
00599
00600
00601 feedFilter = etree.XPath('//url[text()=$url]')
00602 itemFilter = etree.XPath('.//atm:entry', namespaces=self.common.namespaces)
00603 titleFilter = etree.XPath('.//atm:title', namespaces=self.common.namespaces)
00604 mediaFilter = etree.XPath('.//atm:category[@term="TV"]', namespaces=self.common.namespaces)
00605 linkFilter = etree.XPath('.//atm:link', namespaces=self.common.namespaces)
00606 descFilter1 = etree.XPath('.//atm:content', namespaces=self.common.namespaces)
00607 descFilter2 = etree.XPath('.//p')
00608 itemThumbNail = etree.XPath('.//media:thumbnail', namespaces=self.common.namespaces)
00609 creationDate = etree.XPath('.//atm:updated', namespaces=self.common.namespaces)
00610 itemDwnLink = etree.XPath('.//media:content', namespaces=self.common.namespaces)
00611 itemLanguage = etree.XPath('.//media:content', namespaces=self.common.namespaces)
00612 rssName = etree.XPath('atm:title', namespaces=self.common.namespaces)
00613 categoryDir = None
00614 categoryElement = None
00615 itemAuthor = u'BBC'
00616 for result in resultTree.findall('results'):
00617 names = result.find('name').text.split(u';')
00618 names[0] = self.common.massageText(names[0])
00619 if names[0] == 'RSS':
00620 names[0] = self.common.massageText(rssName(result.find('result'))[0].text.replace(u'BBC iPlayer - ', u''))
00621 count = 0
00622 urlMax = None
00623 url = feedFilter(self.userPrefs, url=names[1])
00624 if len(url):
00625 if url[0].attrib.get('max'):
00626 try:
00627 urlMax = int(url[0].attrib.get('max'))
00628 except:
00629 pass
00630 elif url[0].getparent().attrib.get('globalmax'):
00631 try:
00632 urlMax = int(url[0].getparent().attrib.get('globalmax'))
00633 except:
00634 pass
00635 if urlMax == 0:
00636 urlMax = None
00637 channelThumbnail = self.channel_icon
00638 channelLanguage = u'en'
00639
00640 if names[0] != categoryDir:
00641 if categoryDir != None:
00642 channelTree.append(categoryElement)
00643 categoryElement = etree.XML(u'<directory></directory>')
00644 categoryElement.attrib['name'] = names[0]
00645 categoryElement.attrib['thumbnail'] = self.channel_icon
00646 categoryDir = names[0]
00647
00648 if self.config['debug_enabled']:
00649 print "Results: #Items(%s) for (%s)" % (len(itemFilter(result)), names)
00650 print
00651
00652
00653
00654 itemDict = [(pd.text, pd.getparent()) for pd in creationDate(result)]
00655 itemList = sorted(itemDict, key=itemgetter(0), reverse=True)
00656
00657 for tupleDate in itemList:
00658 itemData = tupleDate[1]
00659 bbciplayerItem = etree.XML(self.common.mnvItem)
00660 tmpLink = linkFilter(itemData)
00661 if len(tmpLink):
00662 link = tmpLink[0].attrib['href']
00663 if urlType == 'bigscreen':
00664 link = link.replace(u'/iplayer/', u'/iplayer/bigscreen/')
00665 elif urlType == 'bbcweb':
00666 pass
00667 else:
00668 if len(mediaFilter(itemData)):
00669 link = link.replace(u'http://www.bbc.co.uk/iplayer/episode/', u'')
00670 index = link.find(u'/')
00671 link = link[:index]
00672 link = self.processVideoUrl(link);
00673 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}customhtml").text = 'true'
00674 else:
00675 pass
00676 else:
00677 continue
00678
00679 pubdate = creationDate(itemData)
00680 if len(pubdate):
00681 pubdate = pubdate[0].text
00682 pubdate = time.strptime(pubdate, '%Y-%m-%dT%H:%M:%SZ')
00683 pubdate = time.strftime(self.common.pubDateFormat, pubdate)
00684 else:
00685 pubdate = datetime.datetime.now().strftime(self.common.pubDateFormat)
00686
00687
00688 bbciplayerItem.find('title').text = self.common.massageText(titleFilter(itemData)[0].text.strip())
00689 bbciplayerItem.find('author').text = itemAuthor
00690 bbciplayerItem.find('pubDate').text = pubdate
00691 description = etree.HTML(etree.tostring(descFilter1(itemData)[0], method="text", encoding=unicode).strip())
00692 description = etree.tostring(descFilter2(description)[1], method="text", encoding=unicode).strip()
00693 bbciplayerItem.find('description').text = self.common.massageText(description)
00694 bbciplayerItem.find('link').text = link
00695 itemDwnLink(bbciplayerItem)[0].attrib['url'] = link
00696 try:
00697 itemThumbNail(bbciplayerItem)[0].attrib['url'] = self.common.ampReplace(itemThumbNail(itemData)[0].attrib['url'])
00698 except IndexError:
00699 pass
00700 itemLanguage(bbciplayerItem)[0].attrib['lang'] = channelLanguage
00701
00702 countCode = self.setCountry(itemData)
00703 if countCode:
00704 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}country").text = countCode
00705 s_e = self.getSeasonEpisode(bbciplayerItem.find('title').text)
00706 if s_e[0]:
00707 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}season").text = s_e[0]
00708 if s_e[1]:
00709 etree.SubElement(bbciplayerItem, "{http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format}episode").text = s_e[1]
00710 categoryElement.append(bbciplayerItem)
00711 if urlMax:
00712 count+=1
00713 if count > urlMax:
00714 break
00715
00716
00717 if categoryElement != None:
00718 if categoryElement.xpath('.//item') != None:
00719 channelTree.append(categoryElement)
00720
00721
00722 if len(rssTree.xpath('//item')):
00723
00724 sys.stdout.write(u'<?xml version="1.0" encoding="UTF-8"?>\n')
00725 sys.stdout.write(etree.tostring(rssTree, encoding='UTF-8', pretty_print=True))
00726
00727 sys.exit(0)
00728
00729