def ListGenres(): """List programmes based on alphabetical order. Only creates the corresponding directories for each character. """ genres = [] html = OpenURL('http://www.bbc.co.uk/radio/programmes/genres') mains = html.split('<div class="category__box island--vertical">') for main in mains: current_main_match = re.search( r'<a.+?class="gel-double-pica-bold".+?href="(.+?)">(.+?)</a>', main) if current_main_match: genres.append((current_main_match.group(1), current_main_match.group(2), True)) current_sub_match = re.findall( r'<a.+?class="gel-long-primer-bold".+?href="(.+?)">(.+?)</a>', main) for sub_match_url, sub_match_name in current_sub_match: genres.append((sub_match_url, current_main_match.group(2) + ' - ' + sub_match_name, False)) for url, name, group in genres: new_url = 'http://www.bbc.co.uk%s' % url if group: AddMenuEntry("[B]%s[/B]" % name, new_url, 137, '', '', '') else: AddMenuEntry("%s" % name, new_url, 137, '', '', '') #BUG: this should sort by original order but it doesn't (see http://trac.kodi.tv/ticket/10252) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE)
def ListLive(): channel_list = [ ('bbc_one_hd', 'bbc_one', 'BBC One'), ('bbc_two_hd', 'bbc_two', 'BBC Two'), ('bbc_four_hd', 'bbc_four', 'BBC Four'), ('cbbc_hd', 'cbbc', 'CBBC'), ('cbeebies_hd', 'cbeebies', 'CBeebies'), ('bbc_news24', 'bbc_news24', 'BBC News Channel'), ('bbc_parliament', 'bbc_parliament', 'BBC Parliament'), ('bbc_alba', 'bbc_alba', 'Alba'), ('s4cpbs', 's4c', 'S4C'), ('bbc_one_london', 'bbc_one', 'BBC One London'), ('bbc_one_scotland_hd', 'bbc_one_scotland', 'BBC One Scotland'), ('bbc_one_northern_ireland_hd', 'bbc_one_northern_ireland', 'BBC One Northern Ireland'), ('bbc_one_wales_hd', 'bbc_one_wales', 'BBC One Wales'), ('bbc_two_scotland', 'bbc_two', 'BBC Two Scotland'), ('bbc_two_northern_ireland_digital', 'bbc_two', 'BBC Two Northern Ireland'), ('bbc_two_wales_digital', 'bbc_two', 'BBC Two Wales'), ] for id, img, name in channel_list: iconimage = xbmc.translatePath( os.path.join('special://home/addons/plugin.video.iplayerwww/media', img + '.png')) if ADDON.getSetting('streams_autoplay') == 'true': AddMenuEntry(name, id, 203, iconimage, '', '') else: AddMenuEntry(name, id, 123, iconimage, '', '')
def ListRedButton(): channel_list = [ ('sport_stream_01', 'BBC Red Button 1'), ('sport_stream_02', 'BBC Red Button 2'), ('sport_stream_03', 'BBC Red Button 3'), ('sport_stream_04', 'BBC Red Button 4'), ('sport_stream_05', 'BBC Red Button 5'), ('sport_stream_06', 'BBC Red Button 6'), ('sport_stream_07', 'BBC Red Button 7'), ('sport_stream_08', 'BBC Red Button 8'), ('sport_stream_09', 'BBC Red Button 9'), ('sport_stream_10', 'BBC Red Button 10'), ('sport_stream_11', 'BBC Red Button 11'), ('sport_stream_12', 'BBC Red Button 12'), ('sport_stream_13', 'BBC Red Button 13'), ('sport_stream_14', 'BBC Red Button 14'), ('sport_stream_15', 'BBC Red Button 15'), ('sport_stream_16', 'BBC Red Button 16'), ('sport_stream_17', 'BBC Red Button 17'), ('sport_stream_18', 'BBC Red Button 18'), ('sport_stream_19', 'BBC Red Button 19'), ('sport_stream_20', 'BBC Red Button 20'), ('sport_stream_21', 'BBC Red Button 21'), ('sport_stream_22', 'BBC Red Button 22'), ('sport_stream_23', 'BBC Red Button 23'), ('sport_stream_24', 'BBC Red Button 24'), ('sport_stream_01b', 'BBC Red Button 1b'), ('sport_stream_02b', 'BBC Red Button 2b'), ('sport_stream_03b', 'BBC Red Button 3b'), ('sport_stream_04b', 'BBC Red Button 4b'), ('sport_stream_05b', 'BBC Red Button 5b'), ('sport_stream_06b', 'BBC Red Button 6b'), ('sport_stream_07b', 'BBC Red Button 7b'), ('sport_stream_08b', 'BBC Red Button 8b'), ('sport_stream_09b', 'BBC Red Button 9b'), ('sport_stream_10b', 'BBC Red Button 10b'), ('sport_stream_11b', 'BBC Red Button 11b'), ('sport_stream_12b', 'BBC Red Button 12b'), ('sport_stream_13b', 'BBC Red Button 13b'), ('sport_stream_14b', 'BBC Red Button 14b'), ('sport_stream_15b', 'BBC Red Button 15b'), ('sport_stream_16b', 'BBC Red Button 16b'), ('sport_stream_17b', 'BBC Red Button 17b'), ('sport_stream_18b', 'BBC Red Button 18b'), ('sport_stream_19b', 'BBC Red Button 19b'), ('sport_stream_20b', 'BBC Red Button 20b'), ('sport_stream_21b', 'BBC Red Button 21b'), ('sport_stream_22b', 'BBC Red Button 22b'), ('sport_stream_23b', 'BBC Red Button 23b'), ('sport_stream_24b', 'BBC Red Button 24b'), ] iconimage = xbmc.translatePath( 'special://home/addons/plugin.video.iplayerwww/media/red_button.png') for id, name in channel_list: if ADDON.getSetting('streams_autoplay') == 'true': AddMenuEntry(name, id, 203, iconimage, '', '') else: AddMenuEntry(name, id, 123, iconimage, '', '')
def AddAvailableLiveStreamsDirectory(name, channelname, iconimage): """Retrieves the available live streams for a channel Args: name: only used for displaying the channel. iconimage: only used for displaying the channel. channelname: determines which channel is queried. """ streams = ParseLiveStreams(channelname, '') # Add each stream to the Kodi selection menu. for id, bitrate, codecs, resolution, url, provider_name in streams: # For easier selection use colors to indicate high and low bitrate streams if bitrate > 2.1: color = 'ff008000' elif bitrate > 1.0: color = 'ffffff00' elif bitrate > 0.6: color = 'ffffa500' else: color = 'ffff0000' title = name + ' - [I][COLOR %s]%0.1f Mbps[/COLOR] [COLOR fff1f1f1]%s[/COLOR][/I]' % ( color, bitrate, provider_name) # Finally add them to the selection menu. AddMenuEntry(title, url, 201, iconimage, '', '')
def AddAvailableStreamsDirectory(name, stream_id, iconimage, description): """Will create one menu entry for each available stream of a particular stream_id""" # print "Stream ID: %s"%stream_id streams = ParseStreams(stream_id) # print streams if streams[1]: # print "Setting subtitles URL" subtitles_url = streams[1][0] # print subtitles_url else: subtitles_url = '' suppliers = ['', 'Akamai', 'Limelight', 'Level3'] bitrates = [0, 800, 1012, 1500, 1800, 2400, 3116, 5510] for supplier, bitrate, url, resolution in sorted(streams[0], key=itemgetter(1), reverse=True): if bitrate in (5, 7): color = 'ff008000' elif bitrate == 6: color = 'ff0084ff' elif bitrate in (3, 4): color = 'ffffff00' else: color = 'ffffa500' title = name + ' - [I][COLOR %s]%0.1f Mbps[/COLOR] [COLOR ffd3d3d3]%s[/COLOR][/I]' % ( color, bitrates[bitrate] / 1000, suppliers[supplier]) AddMenuEntry(title, url, 201, iconimage, description, subtitles_url, resolution=resolution)
def AddAvailableStreamsDirectory(name, stream_id, iconimage, description): """Will create one menu entry for each available stream of a particular stream_id""" streams = ParseStreams(stream_id) for supplier, bitrate, url, encoding in sorted(streams[0], key=itemgetter(1), reverse=True): bitrate = int(bitrate) if supplier == 1: supplier = 'Akamai' elif supplier == 2: supplier = 'Limelight' if bitrate >= 320: color = 'ff008000' elif bitrate >= 128: color = 'ffffff00' elif bitrate >= 96: color = 'ffffa500' else: color = 'ffff0000' title = name + ' - [I][COLOR %s]%d Kbps %s[/COLOR] [COLOR ffd3d3d3]%s[/COLOR][/I]' % ( color, bitrate, encoding, supplier) AddMenuEntry(title, url, 201, iconimage, description, '', '')
def ListAtoZ(): """List programmes based on alphabetical order. Only creates the corresponding directories for each character. """ characters = [('A', 'a'), ('B', 'b'), ('C', 'c'), ('D', 'd'), ('E', 'e'), ('F', 'f'), ('G', 'g'), ('H', 'h'), ('I', 'i'), ('J', 'j'), ('K', 'k'), ('L', 'l'), ('M', 'm'), ('N', 'n'), ('O', 'o'), ('P', 'p'), ('Q', 'q'), ('R', 'r'), ('S', 's'), ('T', 't'), ('U', 'u'), ('V', 'v'), ('W', 'w'), ('X', 'x'), ('Y', 'y'), ('Z', 'z'), ('0-9', '0-9')] if int(ADDON.getSetting('scrape_atoz')) == 1: pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) page = 1 total_pages = len(characters) for name, url in characters: GetAtoZPage(url) percent = int(100 * page / total_pages) pDialog.update(percent, translation(30319), name) page += 1 pDialog.close() else: for name, url in characters: AddMenuEntry(name, url, 124, '', '', '')
def ListCategoryFilters(url): """Parses the available category filters (if available) and creates directories for selcting them. If there are no filters available, all programmes will be listed using GetFilteredCategory. """ NEW_URL = 'http://www.bbc.co.uk/iplayer/categories/%s/all?sort=atoz' % url # Read selected category's page. html = OpenURL(NEW_URL) # Some categories offer filters, we want to provide these filters as options. match1 = re.findall( '<li class="filter"> <a class="name" href="/iplayer/categories/(.+?)"> (.+?)</a>', html, re.DOTALL) if match1: AddMenuEntry('All', url, 126, '', '', '') for url, name in match1: AddMenuEntry(name, url, 126, '', '', '') else: GetFilteredCategory(url)
def ListFollowing(logged_in): if(CheckLogin(logged_in) == False): CreateBaseDirectory('audio') return """Scrapes all episodes of the favourites page.""" html = OpenURL('https://www.bbc.co.uk/radio/favourites/programmes') programmes = html.split('<div class="favourites follow ') for programme in programmes: if not programme.startswith('media'): continue series_id = '' series_name = '' series_id_match = re.search(r'<a aria-label="(.*?)" class="follows__image-link" href="http://www.bbc.co.uk/programmes/(.*?)">',programme) if series_id_match: series_name = series_id_match.group(1) series_id = series_id_match.group(2) episode_name = '' episode_id = '' episode_id_match = re.search(r'<a aria-label="(.*?)" class="size-e clr-white" href="http://www.bbc.co.uk/programmes/(.*?)#play"',programme) if episode_id_match: episode_name = episode_id_match.group(1) episode_id = episode_id_match.group(2) episode_image = '' series_image = '' series_image_match = re.search(r'<img class="media__image" src="(.*?)"',programme) if series_image_match: series_image = "https:%s" % series_image_match.group(1) episode_image = series_image station = '' station_match = re.search(r'<a href="(.*?)" class="clr-light-grey">\s*(.*?)\s*</a>',programme, flags=(re.DOTALL | re.MULTILINE)) if station_match: station = station_match.group(2).strip() description = '' if series_id: series_title = "%s - %s" % (station, series_name) AddMenuEntry(series_title, series_id, 131, series_image, description, '') if episode_id: if series_name: episode_title = "%s - %s - %s" % (station, series_name, episode_name) else: episode_title = "%s - %s" % (station, episode_name) episode_url = "http://www.bbc.co.uk/programmes/%s" % episode_id # xbmc.log(episode_url) CheckAutoplay(episode_title, episode_url, episode_image, ' ', '') xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED)
def ListCategories(): """Parses the available categories and creates directories for selecting one of them. The category names are scraped from the website. """ html = OpenURL('http://www.bbc.co.uk/iplayer') match = re.compile( '<a href="/iplayer/categories/(.+?)" class="stat">(.+?)</a>').findall( html) for url, name in match: AddMenuEntry(name, url, 125, '', '', '')
def GetAtoZPage(url): """Allows to list programmes based on alphabetical order. Creates the list of programmes for one character. """ link = OpenURL('http://www.bbc.co.uk/iplayer/a-z/%s' % url) match = re.compile( '<a href="/iplayer/brand/(.+?)".+?<span class="title">(.+?)</span>', re.DOTALL).findall(link) for programme_id, name in match: AddMenuEntry(name, programme_id, 121, '', '', '')
def ListCategories(): """Parses the available categories and creates directories for selecting one of them. The category names are scraped from the website. """ html = OpenURL('https://www.bbc.co.uk/iplayer') match = re.compile( '<a href="/iplayer/categories/(.+?)/featured".*?><span class="lnk__label">(.+?)</span>' ).findall(html) for url, name in match: if ((name == "View all") or (name == "A-Z")): continue AddMenuEntry(name, url, 126, '', '', '')
def ListAtoZ(): """List programmes based on alphabetical order. Only creates the corresponding directories for each character. """ characters = [('A', 'a'), ('B', 'b'), ('C', 'c'), ('D', 'd'), ('E', 'e'), ('F', 'f'), ('G', 'g'), ('H', 'h'), ('I', 'i'), ('J', 'j'), ('K', 'k'), ('L', 'l'), ('M', 'm'), ('N', 'n'), ('O', 'o'), ('P', 'p'), ('Q', 'q'), ('R', 'r'), ('S', 's'), ('T', 't'), ('U', 'u'), ('V', 'v'), ('W', 'w'), ('X', 'x'), ('Y', 'y'), ('Z', 'z'), ('0-9', '@')] for name, url in characters: url = 'http://www.bbc.co.uk/programmes/a-z/by/%s/player' % url AddMenuEntry(name, url, 138, '', '', '')
def ListChannelHighlights(): """Creates a list directories linked to the highlights section of each channel.""" channel_list = [ ('bbcone', 'bbc_one', 'BBC One'), ('bbctwo', 'bbc_two', 'BBC Two'), ('tv/bbcthree', 'bbc_three', 'BBC Three'), ('bbcfour', 'bbc_four', 'BBC Four'), ('tv/cbbc', 'cbbc', 'CBBC'), ('tv/cbeebies', 'cbeebies', 'CBeebies'), ('tv/bbcnews', 'bbc_news24', 'BBC News Channel'), ('tv/bbcparliament', 'bbc_parliament', 'BBC Parliament'), ('tv/bbcalba', 'bbc_alba', 'Alba'), ('tv/s4c', 's4c', 'S4C'), ] for id, img, name in channel_list: iconimage = xbmc.translatePath( os.path.join('special://home/addons/plugin.video.iplayerwww/media', img + '.png')) AddMenuEntry(name, id, 106, iconimage, '', '')
def ListFavourites(logged_in): if (CheckLogin(logged_in) == False): CreateBaseDirectory('video') return """Scrapes all episodes of the favourites page.""" html = OpenURL( 'http://www.bbc.co.uk/iplayer/usercomponents/favourites/programmes.json' ) json_data = json.loads(html) # favourites = json_data.get('favourites') programmes = json_data.get('programmes') for programme in programmes: id = programme.get('id') url = "http://www.bbc.co.uk/iplayer/brand/%s" % (id) title = programme.get('title') initial_child = programme.get('initial_children')[0] subtitle = initial_child.get('subtitle') episode_title = title if subtitle: episode_title = title + ' - ' + subtitle image = initial_child.get('images') image_url = ParseImageUrl(image.get('standard')) synopses = initial_child.get('synopses') plot = synopses.get('small') try: aired = FirstShownToAired(initial_child.get('release_date')) except: aired = '' CheckAutoplay(episode_title, url, image_url, plot, aired) more = programme.get('count') if more: episodes_url = "http://www.bbc.co.uk/iplayer/episodes/" + id AddMenuEntry( '[B]%s[/B] - %s %s' % (title, more, translation(30313)), episodes_url, 128, image_url, '', '') xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
def AddAvailableLiveStreamsDirectory(name, channelname, iconimage): """Retrieves the available live streams for a channel Args: name: only used for displaying the channel. iconimage: only used for displaying the channel. channelname: determines which channel is queried. """ providers = [('ak', 'Akamai'), ('llnw', 'Limelight')] location_qualities = { 'uk': ['sbr_vlow', 'sbr_low', 'sbr_med', 'sbr_high'], 'nonuk': ['sbr_vlow', 'sbr_low'] } location_names = {'uk': 'UK', 'nonuk': 'International'} quality_colours = { 'sbr_vlow': 'ffff0000', 'sbr_low': 'ffffa500', 'sbr_med': 'ffffff00', 'sbr_high': 'ff008000' } quality_bitrates = { 'sbr_vlow': '48', 'sbr_low': '96', 'sbr_med': '128', 'sbr_high': '320' } for location in list(location_qualities.keys()): qualities = location_qualities[location] qualities.reverse() for quality in qualities: for provider_url, provider_name in providers: url = 'http://a.files.bbci.co.uk/media/live/manifesto/audio/simulcast/hls/%s/%s/%s/%s.m3u8' % ( location, quality, provider_url, channelname) title = name + ' - [I][COLOR %s]%s Kbps[/COLOR] [COLOR fff1f1f1]%s[/COLOR] [COLOR ffb4b4b4]%s[/COLOR][/I]' % ( quality_colours[quality], quality_bitrates[quality], location_names[location], provider_name) AddMenuEntry(title, url, 201, '', '', '')
def ListChannelAtoZ(): """List programmes for each channel based on alphabetical order. Only creates the corresponding directories for each channel. """ channel_list = [ ('bbcone', 'bbc_one', 'BBC One'), ('bbctwo', 'bbc_two', 'BBC Two'), ('tv/bbcthree', 'bbc_three', 'BBC Three'), ('bbcfour', 'bbc_four', 'BBC Four'), ('tv/cbbc', 'cbbc', 'CBBC'), ('tv/cbeebies', 'cbeebies', 'CBeebies'), ('tv/bbcnews', 'bbc_news24', 'BBC News Channel'), ('tv/bbcparliament', 'bbc_parliament', 'BBC Parliament'), ('tv/bbcalba', 'bbc_alba', 'Alba'), ('tv/s4c', 's4c', 'S4C'), ] for id, img, name in channel_list: iconimage = xbmc.translatePath( os.path.join('special://home/addons/plugin.video.iplayerwww/media', img + '.png')) url = "http://www.bbc.co.uk/%s/a-z" % id AddMenuEntry(name, url, 128, iconimage, '', '')
def ParseJSON(programme_data, current_url): """Parses the JSON data containing programme information of a page. Contains a lot of fallbacks """ added_playables = [] added_directories = [] if programme_data: name = '' if 'header' in programme_data: if 'title' in programme_data['header']: name = programme_data['header']['title'] url_split = current_url.replace('&', '?').split('?') is_paginated = False """ Avoid duplicate entries by checking if we are on page >1 """ for part in url_split: if part.startswith('page'): is_paginated = True if not is_paginated: if 'availableSlices' in programme_data['header']: current_series = programme_data['header']['currentSliceId'] slices = programme_data['header']['availableSlices'] if slices is not None: for series in slices: if series['id'] == current_series: continue base_url = url_split[0] series_url = base_url + '?seriesId=' + series['id'] AddMenuEntry( '[B]%s: %s[/B]' % (name, series['title']), series_url, 128, '', '', '') programmes = None if 'currentLetter' in programme_data: # This must be an A-Z page. current_letter = programme_data['currentLetter'] programmes = programme_data['programmes'][current_letter][ 'entities'] elif 'entities' in programme_data: # This must be a category or most popular. programmes = programme_data['entities'] elif 'items' in programme_data: # This must be Added or Watching. programmes = programme_data['items'] if programmes: for item in programmes: meta = None if 'props' in item: meta = item.get('meta') item = item.get('props') ParseSingleJSON(meta, item, name, added_playables, added_directories) # The next section is for global and channel highlights. They are a bit tricky. groups = None highlights = None bundles = None if 'groups' in programme_data: groups = programme_data.get('groups') for entity in groups: for item in entity['entities']: item = item.get("props") if not item: continue ParseSingleJSON(None, item, None, added_playables, added_directories) title = '' id = '' title = entity.get('title') id = entity.get('id') if (title and id): episodes_url = 'https://www.bbc.co.uk/iplayer/group/%s' % id if not episodes_url in added_directories: AddMenuEntry( '[B]%s: %s[/B]' % (translation(30314), title), episodes_url, 128, '', '', '') if 'highlights' in programme_data: highlights = programme_data.get('highlights') entity = highlights.get("items") if entity: for item in entity: item = item.get("props") if not item: continue ParseSingleJSON(None, item, None, added_playables, added_directories) if 'bundles' in programme_data: bundles = programme_data.get('bundles') for bundle in bundles: entity = '' entity = bundle.get('entities') if entity: for item in entity: ParseSingleJSON(None, item, None, added_playables, added_directories) journey = '' journey = bundle.get('journey') if journey: id = '' id = journey.get('id') type = '' type = journey.get('type') title = '' title = bundle.get('title').get('default') if title: if (id and (type == 'group')): if (id == 'popular'): AddMenuEntry( '[B]%s: %s[/B]' % (translation(30314), title), 'url', 105, '', '', '') else: episodes_url = 'https://www.bbc.co.uk/iplayer/group/%s' % id if not episodes_url in added_directories: AddMenuEntry( '[B]%s: %s[/B]' % (translation(30314), title), episodes_url, 128, '', '', '') if (id and (type == 'category')): AddMenuEntry( '[B]%s: %s[/B]' % (translation(30314), title), id, 126, '', '', '') xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED)
def ListLive(): channel_list = [ ('bbc_one_hd', 'BBC One'), ('bbc_two_hd', 'BBC Two'), ('bbc_four_hd', 'BBC Four'), ('cbbc_hd', 'CBBC'), ('cbeebies_hd', 'CBeebies'), ('bbc_news24', 'BBC News Channel'), ('bbc_parliament', 'BBC Parliament'), ('bbc_alba', 'Alba'), ( 'bbc_scotland_hd', 'BBC Scotland', ), ('s4cpbs', 'S4C'), ('bbc_one_london', 'BBC One London'), ('bbc_one_scotland_hd', 'BBC One Scotland'), ('bbc_one_northern_ireland_hd', 'BBC One Northern Ireland'), ('bbc_one_wales_hd', 'BBC One Wales'), ('bbc_two_scotland', 'BBC Two Scotland'), ('bbc_two_northern_ireland_digital', 'BBC Two Northern Ireland'), ('bbc_two_wales_digital', 'BBC Two Wales'), ( 'bbc_two_england', 'BBC Two England', ), ( 'bbc_one_cambridge', 'BBC One Cambridge', ), ( 'bbc_one_channel_islands', 'BBC One Channel Islands', ), ( 'bbc_one_east', 'BBC One East', ), ( 'bbc_one_east_midlands', 'BBC One East Midlands', ), ( 'bbc_one_east_yorkshire', 'BBC One East Yorkshire', ), ( 'bbc_one_north_east', 'BBC One North East', ), ( 'bbc_one_north_west', 'BBC One North West', ), ( 'bbc_one_oxford', 'BBC One Oxford', ), ( 'bbc_one_south', 'BBC One South', ), ( 'bbc_one_south_east', 'BBC One South East', ), ( 'bbc_one_south_west', 'BBC One South West', ), ( 'bbc_one_west', 'BBC One West', ), ( 'bbc_one_west_midlands', 'BBC One West Midlands', ), ( 'bbc_one_yorks', 'BBC One Yorks', ), ] for id, name in channel_list: iconimage = xbmc.translatePath( os.path.join('special://home/addons/plugin.video.iplayerwww/media', id + '.png')) if ADDON.getSetting('streams_autoplay') == 'true': AddMenuEntry(name, id, 203, iconimage, '', '') else: AddMenuEntry(name, id, 123, iconimage, '', '')
def GetCategoryPage(page_url, just_episodes=False): pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) html = OpenURL(page_url) total_pages = 1 current_page = 1 page_range = list(range(1)) paginate = re.search(r'pgn__list', html) next_page = 1 if paginate: if int(ADDON.getSetting('radio_paginate_episodes')) == 0: current_page_match = re.search(r'page=(\d*)', page_url) if current_page_match: current_page = int(current_page_match.group(1)) main_base_url = re.search(r'(.+?)\?.+?', page_url).group(1) else: main_base_url = page_url page_range = list(range(current_page, current_page + 1)) next_page_match = re.search( r'pgn__page--next.*?href="(.*?page=)(.*?)"', html) if next_page_match: page_base_url = main_base_url + next_page_match.group(1) next_page = int(next_page_match.group(2)) else: next_page = current_page page_range = list(range(current_page, current_page + 1)) else: pages = re.findall(r'<li class="pgn__page.*?</li>', html, flags=(re.DOTALL | re.MULTILINE)) if pages: last = pages[-2] last_page = re.search(r'href=".*?page=(.*?)"', last) page_base_url = page_url + '?page=' total_pages = int(last_page.group(1)) page_range = list(range(1, total_pages + 1)) for page in page_range: if page > current_page: page_url = page_base_url + str(page) html = OpenURL(page_url) list_item_num = 1 programmes = html.split('<div class="programme-item') for programme in programmes: series_id = '' series_id_match = re.search( r'<a class="category-episodes" href="/programmes/(.+?)/episodes"', programme) if series_id_match: series_id = series_id_match.group(1) programme_id = '' programme_id_match = re.search(r'href="/programmes/(.+?)"', programme) if programme_id_match: programme_id = programme_id_match.group(1) name = '' name_match = re.search( r'<span class="programme-item-title.+?>(.+?)</span>', programme) if name_match: name = name_match.group(1) subtitle = '' subtitle_match = re.search( r'<p class="programme-item-subtitle.+?>(.+?)</p>', programme) if subtitle_match: subtitle = subtitle_match.group(1) image = '' image_match = re.search(r'class="media__image" src="(.+?)"', programme) if image_match: image = 'http://' + image_match.group(1) synopsis = '' synopsis_match = re.search( r'<p class="programme-item-synopsis.+?>(.+?)</p>', programme) if synopsis_match: synopsis = synopsis_match.group(1) station = '' station_match = re.search( r'class="programme-item-network.+?>\s*(.+?)\s*</a>', programme) if station_match: station = station_match.group(1).strip() series_title = "[B]%s - %s[/B]" % (station, name) title = "[B]%s[/B] - %s %s" % (station, name, subtitle) if series_id: AddMenuEntry(series_title, series_id, 131, image, synopsis, '') elif programme_id: #TODO maybe they are not always mutually exclusive url = "http://www.bbc.co.uk/radio/play/%s" % programme_id CheckAutoplay(title, url, image, ' ', '') percent = int(100 * (page + list_item_num / len(programmes)) / total_pages) pDialog.update(percent, translation(30319), name) list_item_num += 1 percent = int(100 * page / total_pages) pDialog.update(percent, translation(30319)) if int(ADDON.getSetting('radio_paginate_episodes')) == 0: if current_page < next_page: page_url = page_base_url + str(next_page) AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 137, '', '', '') #BUG: this should sort by original order but it doesn't (see http://trac.kodi.tv/ticket/10252) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) pDialog.close()
def GetAtoZPage(page_url, just_episodes=False): """ Generic Radio page scraper. """ pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) html = OpenURL(page_url) total_pages = 1 current_page = 1 page_range = list(range(1)) paginate = re.search(r'<ol.+?class="pagination.*?</ol>', html) next_page = 1 if paginate: if int(ADDON.getSetting('radio_paginate_episodes')) == 0: current_page_match = re.search(r'page=(\d*)', page_url) if current_page_match: current_page = int(current_page_match.group(1)) page_range = list(range(current_page, current_page + 1)) next_page_match = re.search( r'<li class="pagination__next"><a href="(.*?page=)(.*?)">', paginate.group(0)) if next_page_match: page_base_url = next_page_match.group(1) next_page = int(next_page_match.group(2)) else: next_page = current_page page_range = list(range(current_page, current_page + 1)) else: pages = re.findall(r'<li.+?class="pagination__page.*?</li>', paginate.group(0)) if pages: last = pages[-1] last_page = re.search(r'<a.+?href="(.*?=)(.*?)"', last) page_base_url = last_page.group(1) total_pages = int(last_page.group(2)) page_range = list(range(1, total_pages + 1)) for page in page_range: if page > current_page: page_url = 'http://www.bbc.co.uk' + page_base_url + str(page) html = OpenURL(page_url) masthead_title = '' masthead_title_match = re.search( r'<div.+?id="programmes-main-content".*?<span property="name">(.+?)</span>', html) if masthead_title_match: masthead_title = masthead_title_match.group(1) else: alternative_masthead_title_match = re.search( r'<div class="br-masthead__title">.*?<a href="[^"]+">([^<]+?)</a>', html, re.M | re.S) if alternative_masthead_title_match: masthead_title = alternative_masthead_title_match.group(1) list_item_num = 1 programmes = html.split('<li class="grid one-whole">') for programme in programmes: if not re.search(r'programme--radio', programme): continue series_id = '' series_id_match = re.search( r'data-lazylink-inc="/programmes/(.+?)/episodes/player.inc"', programme) if series_id_match: series_id = series_id_match.group(1) programme_id = '' programme_id_match = re.search(r'data-pid="(.+?)"', programme) if programme_id_match: programme_id = programme_id_match.group(1) name = '' name_match = re.search(r'<span property="name">(.+?)</span>', programme) if name_match: name = name_match.group(1) else: alternative_name_match = re.search( r'<meta property="name" content="([^"]+?)"', programme) if alternative_name_match: name = alternative_name_match.group(1) image = '' image_match = re.search( r'<meta property="image" content="(.+?)" />', programme) if image_match: image = image_match.group(1) synopsis = '' synopsis_match = re.search( r'<span property="description">(.+?)<\/span>', programme) if synopsis_match: synopsis = synopsis_match.group(1) station = '' station_match = re.search( r'<p class="programme__service.+?<strong>(.+?)<\/strong>.*?<\/p>', programme) if station_match: station = station_match.group(1).strip() series_title = "[B]%s - %s[/B]" % (station, name) if just_episodes: title = "[B]%s[/B] - %s" % (masthead_title, name) else: title = "[B]%s[/B] - %s" % (station, name) if series_id: AddMenuEntry(series_title, series_id, 131, image, synopsis, '') elif programme_id: #TODO maybe they are not always mutually exclusive url = "http://www.bbc.co.uk/radio/play/%s" % programme_id CheckAutoplay(title, url, image, ' ', '') percent = int(100 * (page + list_item_num / len(programmes)) / total_pages) pDialog.update(percent, translation(30319), name) list_item_num += 1 percent = int(100 * page / total_pages) pDialog.update(percent, translation(30319)) if int(ADDON.getSetting('radio_paginate_episodes')) == 0: if current_page < next_page: page_url = 'http://www.bbc.co.uk' + page_base_url + str(next_page) AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 138, '', '', '') #BUG: this should sort by original order but it doesn't (see http://trac.kodi.tv/ticket/10252) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) pDialog.close()
def GetPage(page_url, just_episodes=False): """ Generic Radio page scraper. """ pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) html = OpenURL(page_url) total_pages = 1 current_page = 1 page_range = list(range(1)) paginate = re.search(r'<ol.+?class="pagination.*?</ol>', html) next_page = 1 if paginate: if int(ADDON.getSetting('radio_paginate_episodes')) == 0: current_page_match = re.search(r'page=(\d*)', page_url) if current_page_match: current_page = int(current_page_match.group(1)) page_range = list(range(current_page, current_page + 1)) next_page_match = re.search( r'<li class="pagination__next"><a href="(.*?page=)(.*?)">', paginate.group(0)) if next_page_match: page_base_url = next_page_match.group(1) next_page = int(next_page_match.group(2)) else: next_page = current_page page_range = list(range(current_page, current_page + 1)) else: pages = re.findall(r'<li.+?class="pagination__page.*?</li>', paginate.group(0)) if pages: last = pages[-1] last_page = re.search(r'<a.+?href="(.*?=)(.*?)"', last) page_base_url = last_page.group(1) total_pages = int(last_page.group(2)) page_range = list(range(1, total_pages + 1)) for page in page_range: if page > current_page: page_url = 'http://www.bbc.co.uk' + page_base_url + str(page) html = OpenURL(page_url) masthead_title = '' masthead_title_match = re.search( r'<div.+?id="programmes-main-content".*?<span property="name">(.+?)</span>', html) if masthead_title_match: masthead_title = masthead_title_match.group(1) else: alternative_masthead_title_match = re.search( r'<div class="br-masthead__title">.*?<a href="[^"]+">([^<]+?)</a>', html, re.M | re.S) if alternative_masthead_title_match: masthead_title = alternative_masthead_title_match.group(1) list_item_num = 1 data = '' data_match = re.findall( r'<script type="application\/ld\+json">(.*?)<\/script>', html, re.S) if data_match: json_data = json.loads(data_match[0]) for episode in json_data['episode']: programme_id = '' programme_id = episode['identifier'] name = '' name = episode['name'] title = "[B]%s[/B] - %s" % (masthead_title, name) imafe = '' image = episode['image'] synopsis = '' synopsis = episode['description'] url = "http://www.bbc.co.uk/radio/play/%s" % programme_id CheckAutoplay(title, url, image, synopsis, '') percent = int( 100 * (page + list_item_num / len(json_data['episode'])) / total_pages) pDialog.update(percent, translation(30319), name) list_item_num += 1 percent = int(100 * page / total_pages) pDialog.update(percent, translation(30319)) if int(ADDON.getSetting('radio_paginate_episodes')) == 0: if current_page < next_page: page_url = 'http://www.bbc.co.uk' + page_base_url + str(next_page) AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 136, '', '', '') #BUG: this should sort by original order but it doesn't (see http://trac.kodi.tv/ticket/10252) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) pDialog.close()
def ListHighlights(highlights_url): """Creates a list of the programmes in the highlights section. """ html = OpenURL('http://www.bbc.co.uk/%s' % highlights_url) inner_anchors = re.findall(r'<a.*?(?!<a).*?</a>', html, flags=(re.DOTALL | re.MULTILINE)) # First find all groups as we need to store some properties of groups for later reuse. group_properties = [] # NOTE find episode count first episode_count = dict() groups = [ a for a in inner_anchors if re.match( r'<a[^<]*?class="grouped-items__cta.*?data-object-type="group-list-link".*?', a, flags=(re.DOTALL | re.MULTILINE)) ] for group in groups: href = '' href_match = re.match(r'<a[^<]*?href="(.*?)"', group, flags=(re.DOTALL | re.MULTILINE)) if href_match: href = href_match.group(1) count_match = re.search(r'>View all ([0-9]*).*?</a>', group, flags=(re.DOTALL | re.MULTILINE)) if count_match: count = count_match.group(1) episode_count[href] = count groups = [ a for a in inner_anchors if re.match( r'<a[^<]*?class="grouped-items__title.*?data-object-type="group-list-link".*?', a, flags=(re.DOTALL | re.MULTILINE)) ] for group in groups: href = '' href_match = re.match(r'<a[^<]*?href="(.*?)"', group, flags=(re.DOTALL | re.MULTILINE)) if href_match: href = href_match.group(1) name = '' name_match = re.search(r'<strong>(.*?)</strong>', group, flags=(re.DOTALL | re.MULTILINE)) if name_match: name = name_match.group(1) count = '' if href in episode_count: count = episode_count[href] url = 'http://www.bbc.co.uk' + href # Unfortunately, the group type is not inside the links, so we need to search the whole HTML. group_type = '' group_type_match = re.search(r'data-group-name="' + name + '".+?data-group-type="(.+?)"', html, flags=(re.DOTALL | re.MULTILINE)) if group_type_match: group_type = group_type_match.group(1) position = '' position_match = re.search(r'data-object-position="(.+?)-ALL"', group, flags=(re.DOTALL | re.MULTILINE)) if position_match: group_properties.append( [position_match.group(1), name, group_type]) AddMenuEntry( '[B]%s: %s[/B] - %s %s' % (translation(30314), name, count, translation(30315)), url, 128, '', '', '') # Some programmes show up twice in HTML, once inside the groups, once outside. # We need to parse both to avoid duplicates and to make sure we get all of them. episodelist = [] # <a\n href="/iplayer/episode/b06tr74y/eastenders-24122015"\n class="grouped-items__list-link listeds = [ a for a in inner_anchors if re.search(r'class="grouped-items__list-link', a, flags=(re.DOTALL | re.MULTILINE)) ] for listed in listeds: episode_id = '' # <a\n href="/iplayer/episode/b06tr74y/eastenders-24122015" id_match = re.match(r'<a.*?href="/iplayer/episode/(.*?)/', listed, flags=(re.DOTALL | re.MULTILINE)) if id_match: episode_id = id_match.group(1) name = '' # <p class="grouped-items__title grouped-items__title--item typo typo--skylark"> # <strong>EastEnders</strong></p> title_match = re.search( r'<.*?class="grouped-items__title.*?<strong>(.*?)</strong>', listed, flags=(re.DOTALL | re.MULTILINE)) if title_match: name = title_match.group(1) name = re.compile(r'<.*?>', flags=(re.DOTALL | re.MULTILINE)).sub('', name) # <p class="grouped-items__subtitle typo typo--canary">24/12/2015</p> subtitle_match = re.search( r'<.*?class="grouped-items__subtitle.*?>(.*?)<', listed, flags=(re.DOTALL | re.MULTILINE)) if subtitle_match: name = name + ' - ' + subtitle_match.group(1) # Assign correct group based on the position of the episode position = '' position_match = re.search(r'data-object-position="(.+?)"', listed, flags=(re.DOTALL | re.MULTILINE)) if position_match: for n, i in enumerate(group_properties): if re.match(i[0], position_match.group(1), flags=(re.DOTALL | re.MULTILINE)): position = i[1] # For series-catchup groups, we need to modify the title. if i[2] == 'series-catchup': name = i[1] + ': ' + name episodelist.append([ episode_id, name, "%s %s" % (translation(30316), position), 'DefaultVideo.png', '' ]) # < a\nhref="/iplayer/episode/p036gq3z/bbc-music-introducing-from-buddhist-monk-to-rock-star"\n # class="single-item stat" singles = [ a for a in inner_anchors if re.search( r'class="single-item', a, flags=(re.DOTALL | re.MULTILINE)) ] for single in singles: object_type = '' # data-object-type="episode-backfill" data_object_type = re.search(r'data-object-type="(.*?)"', single, flags=(re.DOTALL | re.MULTILINE)) if data_object_type: object_type = data_object_type.group(1) if object_type == "episode-backfill": if (highlights_url not in ['tv/bbcnews', 'tv/bbcparliament', 'tv/s4c']): continue episode_id = '' url = '' # <a\nhref="/iplayer/episode/p036gq3z/bbc-music-introducing-from-buddhist-monk-to-rock-star" if object_type == "editorial-promo": id_match = re.match(r'<a.*?href="(.*?)"', single, flags=(re.DOTALL | re.MULTILINE)) else: id_match = re.match(r'<a.*?href="/iplayer/episode/(.*?)/', single, flags=(re.DOTALL | re.MULTILINE)) if id_match: episode_id = id_match.group(1) url = 'http://www.bbc.co.uk/iplayer/episode/' + episode_id name = '' # <h3 class="single-item__title typo typo--skylark"><strong>BBC Music Introducing</strong></h3> title_match = re.search( r'<.*?class="single-item__title.*?<strong>(.*?)</strong>', single, flags=(re.DOTALL | re.MULTILINE)) if title_match: name = title_match.group(1) name = re.compile(r'<.*?>', flags=(re.DOTALL | re.MULTILINE)).sub('', name) # <p class="single-item__subtitle typo typo--canary">From Buddhist Monk to Rock Star</p> subtitle_match = re.search( r'<.*?class="single-item__subtitle.*?>(.*?)<', single, flags=(re.DOTALL | re.MULTILINE)) if subtitle_match: name = name + ' - ' + subtitle_match.group(1) icon = '' # <div class="r-image" data-ip-type="episode" # data-ip-src="http://ichef.bbci.co.uk/images/ic/406x228/p036gtc5.jpg"> image_match = re.search(r'<.*?class="r-image.*?data-ip-src="(.*?)"', single, flags=(re.DOTALL | re.MULTILINE)) if image_match: icon = image_match.group(1) desc = '' # <p class="single-item__overlay__desc"> # The remarkable rise of Ngawang Lodup - from BBC Introducing to performing at the O2 Arena</p> desc_match = re.search( r'<.*?class="single-item__overlay__desc.*?>(.*?)<', single, flags=(re.DOTALL | re.MULTILINE)) if desc_match: desc = desc_match.group(1) aired = '' # <p class="single-item__overlay__subtitle">First shown: 4 Nov 2015</p> release_match = re.search( r'<.*?class="single-item__overlay__subtitle">First shown: (.*?)<', single, flags=(re.DOTALL | re.MULTILINE)) if release_match: release = release_match.group(1) if release: aired = FirstShownToAired(release) add_entry = True for n, i in enumerate(episodelist): if i[0] == episode_id: episodelist[n][2] = desc episodelist[n][3] = icon episodelist[n][4] = aired add_entry = False if add_entry: if object_type == "editorial-promo": AddMenuEntry('[B]%s[/B]' % (name), episode_id, 128, icon, '', '') else: CheckAutoplay(name, url, icon, desc, aired) # Finally add all programmes which have been identified as part of a group before. for episode in episodelist: episode_url = "http://www.bbc.co.uk/iplayer/episode/%s" % episode[0] if ((ADDON.getSetting('suppress_incomplete') == 'false') or (not episode[4] == '')): CheckAutoplay(episode[1], episode_url, episode[3], episode[2], episode[4]) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED)
def ListListenList(logged_in): if (CheckLogin(logged_in) == False): CreateBaseDirectory('audio') return """Scrapes all episodes of the favourites page.""" html = OpenURL('http://www.bbc.co.uk/radio/favourites') programmes = html.split('<div class="favourites box-link favourite ') for programme in programmes: if not programme.startswith('media'): continue data_available_match = re.search(r'data-is-available="(.*?)"', programme) if ((not data_available_match) or (data_available_match.group(1) == '')): continue series_id = '' series_name = '' series_id_match = re.search( r'<a href="/programmes/(.*?)" class="media__meta-row size-f clr-light-grey text--single-line">\s*(.*?)\s*</a>', programme) if series_id_match: series_name = series_id_match.group(2) series_id = series_id_match.group(1) episode_name = '' episode_id = '' episode_id_match = re.search( r'<a aria-label="(.*?) Duration: (.*?)" class="favourites__brand-link(.*?)" href="/programmes/(.*?)#play">', programme) if episode_id_match: episode_name = episode_id_match.group(1) episode_id = episode_id_match.group(4) episode_image = '' episode_image_match = re.search( r'<img alt="" class="favourites__brand-image media__image " src="(.*?)"', programme) if episode_image_match: episode_image = "http:%s" % episode_image_match.group(1) series_image = '' series_image_match = re.search( r'<img class="media__image avatar-image--small" src="(.*?)">', programme) if series_image_match: series_image = "http:%s" % series_image_match.group(1) series_image = re.sub(r'96x96', '640x360', series_image) station = '' station_match = re.search( r'<span class="favourites__network-name.*?<a href="(.*?)" class="clr-light-grey">\s+?(.*?)\s+?<', programme, flags=(re.DOTALL | re.MULTILINE)) if station_match: station = station_match.group(2).strip() description = '' description_match = re.search( r'<p class="favourites__description media__meta-row size-f clr-white.*?">\s+?(.*?)\s+?</p>', programme, flags=(re.DOTALL | re.MULTILINE)) if description_match: description = description_match.group(1).strip() if series_id: series_title = "[B]%s - %s[/B]" % (station, series_name) AddMenuEntry(series_title, series_id, 131, series_image, description, '') if episode_id: if series_name: episode_title = "[B]%s[/B] - %s - %s" % (station, series_name, episode_name) episode_url = "http://www.bbc.co.uk/programmes/%s" % episode_id else: episode_title = "[B]%s[/B] - %s" % (station, episode_name) episode_url = "http://www.bbc.co.uk/radio/play/%s" % episode_id # xbmc.log(episode_url) CheckAutoplay(episode_title, episode_url, episode_image, ' ', '') xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED)
def ScrapeAtoZEpisodes(page_url): """Creates a list of programmes on one standard HTML page. ScrapeEpisodes contains a number of special treatments, which are only needed for specific pages, e.g. Search, but allows to use a single function for all kinds of pages. """ pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) html = OpenURL(page_url) total_pages = 1 current_page = 1 page_range = list(range(1)) json_data = ScrapeJSON(html) if json_data: last_page = 1 current_page = 1 if 'pagination' in json_data: page_base_url_match = re.search(r'(.+?)page=', page_url) if page_base_url_match: page_base_url = page_base_url_match.group(0) else: page_base_url = page_url + "?page=" current_page = json_data['pagination'].get('currentPage') last_page = json_data['pagination'].get('totalPages') if int(ADDON.getSetting('paginate_episodes')) == 0: current_page_match = re.search(r'page=(\d*)', page_url) if current_page_match: current_page = int(current_page_match.group(1)) page_base_url_match = re.search(r'(.+?)page=', page_url) if page_base_url_match: page_base_url = page_base_url_match.group(0) else: page_base_url = page_url + "?page=" if current_page < last_page: next_page = curent_page + 1 else: next_page = current_page page_range = list(range(current_page, current_page + 1)) else: page_range = list(range(1, last_page + 1)) for page in page_range: if page > current_page: page_url = page_base_url + str(page) html = OpenURL(page_url) json_data = ScrapeJSON(html) if json_data: ParseJSON(json_data, page_url) percent = int(100 * page / last_page) pDialog.update(percent, translation(30319)) if int(ADDON.getSetting('paginate_episodes')) == 0: if current_page < next_page: page_url = page_base_url + str(next_page) AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 134, '', '', '') pDialog.close()
def ScrapeEpisodes(page_url): """Creates a list of programmes on one standard HTML page. ScrapeEpisodes contains a number of special treatments, which are only needed for specific pages, e.g. Search, but allows to use a single function for all kinds of pages. """ pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) html = OpenURL(page_url) total_pages = 1 current_page = 1 page_range = list(range(1)) paginate = re.search(r'<ol class="paginat.*?</ol>', html, re.DOTALL) if not paginate: paginate = re.search(r'<div class="paginate.*?</div>', html, re.DOTALL) next_page = 1 if paginate: if int(ADDON.getSetting('paginate_episodes')) == 0: current_page_match = re.search(r'page=(\d*)', page_url) if current_page_match: current_page = int(current_page_match.group(1)) pages = re.findall(r'<li class="pag.*?</li>', paginate.group(0), re.DOTALL) if pages: last = pages[-1] last_page = re.search(r'page=(\d*)', last) if last_page: total_pages = int(last_page.group(1)) else: total_pages = current_page if current_page < total_pages: split_page_url = page_url.replace('&', '?').split('?') page_base_url = split_page_url[0] for part in split_page_url[1:len(split_page_url)]: if not part.startswith('page'): page_base_url = page_base_url + '?' + part if '?' in page_base_url: page_base_url = page_base_url.replace( 'https://www.bbc.co.uk', '') + '&page=' else: page_base_url = page_base_url.replace( 'https://www.bbc.co.uk', '') + '?page=' next_page = current_page + 1 else: next_page = current_page page_range = list(range(current_page, current_page + 1)) else: pages = re.findall(r'<li class="pag.*?</li>', paginate.group(0), re.DOTALL) if pages: last = pages[-1] last_page = re.search(r'page=(\d*)', last) split_page_url = page_url.replace('&', '?').split('?') page_base_url = split_page_url[0] for part in split_page_url[1:len(split_page_url)]: if not part.startswith('page'): page_base_url = page_base_url + '?' + part if '?' in page_base_url: page_base_url = page_base_url.replace( 'https://www.bbc.co.uk', '') + '&page=' else: page_base_url = page_base_url.replace( 'https://www.bbc.co.uk', '') + '?page=' total_pages = int(last_page.group(1)) page_range = list(range(1, total_pages + 1)) for page in page_range: if page > current_page: page_url = 'https://www.bbc.co.uk' + page_base_url + str(page) html = OpenURL(page_url) json_data = ScrapeJSON(html) if json_data: ParseJSON(json_data, page_url) percent = int(100 * page / total_pages) pDialog.update(percent, translation(30319)) if int(ADDON.getSetting('paginate_episodes')) == 0: if current_page < next_page: page_url = 'https://www.bbc.co.uk' + page_base_url + str(next_page) AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 128, '', '', '') pDialog.close()
def ListLive(): channel_list = [ ('bbc_radio_one', 'BBC Radio 1'), ('bbc_1xtra', 'BBC Radio 1Xtra'), ('bbc_radio_two', 'BBC Radio 2'), ('bbc_radio_three', 'BBC Radio 3'), ('bbc_radio_fourfm', 'BBC Radio 4 FM'), ('bbc_radio_fourlw', 'BBC Radio 4 LW'), ('bbc_radio_four_extra', 'BBC Radio 4 Extra'), ('bbc_radio_five_live', 'BBC Radio 5 live'), ('bbc_radio_five_live_sports_extra', 'BBC Radio 5 live sports extra'), ('bbc_6music', 'BBC Radio 6 Music'), ('bbc_asian_network', 'BBC Asian Network'), ('bbc_radio_scotland_fm', 'BBC Radio Scotland'), ('bbc_radio_nan_gaidheal', 'BBC Radio nan Gàidheal'), ('bbc_radio_ulster', 'BBC Radio Ulster'), ('bbc_radio_foyle', 'BBC Radio Foyle'), ('bbc_radio_wales_fm', 'BBC Radio Wales'), ('bbc_radio_cymru', 'BBC Radio Cymru'), ('bbc_radio_berkshire', 'BBC Radio Berkshire'), ('bbc_radio_bristol', 'BBC Radio Bristol'), ('bbc_radio_cambridge', 'BBC Radio Cambridgeshire'), ('bbc_radio_cornwall', 'BBC Radio Cornwall'), ('bbc_radio_coventry_warwickshire', 'BBC Coventry & Warwickshire'), ('bbc_radio_cumbria', 'BBC Radio Cumbria'), ('bbc_radio_derby', 'BBC Radio Derby'), ('bbc_radio_devon', 'BBC Radio Devon'), ('bbc_radio_essex', 'BBC Essex'), ('bbc_radio_gloucestershire', 'BBC Radio Gloucestershire'), ('bbc_radio_guernsey', 'BBC Radio Guernsey'), ('bbc_radio_hereford_worcester', 'BBC Hereford & Worcester'), ('bbc_radio_humberside', 'BBC Radio Humberside'), ('bbc_radio_jersey', 'BBC Radio Jersey'), ('bbc_radio_kent', 'BBC Radio Kent'), ('bbc_radio_lancashire', 'BBC Radio Lancashire'), ('bbc_radio_leeds', 'BBC Radio Leeds'), ('bbc_radio_leicester', 'BBC Radio Leicester'), ('bbc_radio_lincolnshire', 'BBC Radio Lincolnshire'), ('bbc_london', 'BBC Radio London'), ('bbc_radio_manchester', 'BBC Radio Manchester'), ('bbc_radio_merseyside', 'BBC Radio Merseyside'), ('bbc_radio_newcastle', 'BBC Newcastle'), ('bbc_radio_norfolk', 'BBC Radio Norfolk'), ('bbc_radio_northampton', 'BBC Radio Northampton'), ('bbc_radio_nottingham', 'BBC Radio Nottingham'), ('bbc_radio_oxford', 'BBC Radio Oxford'), ('bbc_radio_sheffield', 'BBC Radio Sheffield'), ('bbc_radio_shropshire', 'BBC Radio Shropshire'), ('bbc_radio_solent', 'BBC Radio Solent'), ('bbc_radio_somerset_sound', 'BBC Somerset'), ('bbc_radio_stoke', 'BBC Radio Stoke'), ('bbc_radio_suffolk', 'BBC Radio Suffolk'), ('bbc_radio_surrey', 'BBC Surrey'), ('bbc_radio_sussex', 'BBC Sussex'), ('bbc_tees', 'BBC Tees'), ('bbc_three_counties_radio', 'BBC Three Counties Radio'), ('bbc_radio_wiltshire', 'BBC Wiltshire'), ('bbc_wm', 'BBC WM 95.6'), ('bbc_radio_york', 'BBC Radio York'), ] for id, name in channel_list: iconimage = xbmc.translatePath( os.path.join('special://home/addons/plugin.video.iplayerwww/media', id + '.png')) if ADDON.getSetting('streams_autoplay') == 'true': AddMenuEntry(name, id, 213, iconimage, '', '') else: AddMenuEntry(name, id, 133, iconimage, '', '')
def ParseSingleJSON(meta, item, name, added_playables, added_directories): main_url = None episodes_url = '' episodes_title = '' num_episodes = None synopsis = '' icon = '' aired = '' title = '' if 'episode' in item: subitem = item['episode'] if 'id' in subitem: main_url = 'https://www.bbc.co.uk/iplayer/episode/' + subitem.get( 'id') if subitem.get('subtitle'): if 'default' in subitem.get('subtitle'): if 'title' in subitem: if 'default' in subitem.get('title'): title = '%s - %s' % (subitem['title'].get( 'default'), subitem['subtitle'].get('default')) else: title = '%s - %s' % (name, subitem['subtitle'].get('default')) elif subitem.get('title'): if 'default' in subitem.get('title'): title = subitem['title'].get('default') else: title = name if subitem.get('synopsis'): if 'small' in subitem.get('synopsis'): synopsis = subitem['synopsis'].get('small') if subitem.get('image'): if 'default' in subitem.get('image'): icon = subitem['image'].get('default').replace( "{recipe}", "832x468") else: if 'href' in item: # Some strings already contain the full URL, need to work around this. url = item['href'].replace('http://www.bbc.co.uk', '') url = url.replace('https://www.bbc.co.uk', '') if url: main_url = 'https://www.bbc.co.uk' + url if 'secondaryHref' in item: # Some strings already contain the full URL, need to work around this. url = item['secondaryHref'].replace('http://www.bbc.co.uk', '') url = url.replace('https://www.bbc.co.uk', '') if url: episodes_url = 'https://www.bbc.co.uk' + url episodes_title = item["title"] elif meta: if 'secondaryHref' in meta: # Some strings already contain the full URL, need to work around this. url = meta['secondaryHref'].replace('http://www.bbc.co.uk', '') url = url.replace('https://www.bbc.co.uk', '') if url: episodes_url = 'https://www.bbc.co.uk' + url episodes_title = item["title"] if 'episodesAvailable' in meta: if meta['episodesAvailable'] > 1: num_episodes = str(meta['episodesAvailable']) if 'subtitle' in item: if 'title' in item: title = "%s - %s" % (item['title'], item['subtitle']) else: title = name elif 'title' in item: title = item['title'] else: title = name if 'synopsis' in item: synopsis = item['synopsis'] if 'imageTemplate' in item: icon = item['imageTemplate'].replace("{recipe}", "832x468") if main_url: if not main_url in added_playables: CheckAutoplay(title, main_url, icon, synopsis, aired) added_playables.append(main_url) if num_episodes: if not main_url in added_directories: title = '[B]' + item[ 'title'] + '[/B] - ' + num_episodes + ' episodes available' AddMenuEntry(title, main_url, 139, icon, synopsis, '') added_directories.append(main_url) if episodes_url: if not main_url in added_directories: AddMenuEntry('[B]%s[/B]' % (episodes_title), episodes_url, 128, icon, synopsis, '') added_directories.append(main_url)
def CheckAutoplay(name, url, iconimage, plot, aired=None): if ADDON.getSetting('streams_autoplay') == 'true': AddMenuEntry(name, url, 212, iconimage, plot, '', aired=aired) else: AddMenuEntry(name, url, 132, iconimage, plot, '', aired=aired)
def ScrapeEpisodes(page_url): """Creates a list of programmes on one standard HTML page. ScrapeEpisodes contains a number of special treatments, which are only needed for specific pages, e.g. Search, but allows to use a single function for all kinds of pages. """ pDialog = xbmcgui.DialogProgressBG() pDialog.create(translation(30319)) html = OpenURL(page_url) total_pages = 1 current_page = 1 page_range = range(1) paginate = re.search(r'<div class="paginate.*?</div>', html, re.DOTALL) next_page = 1 if paginate: if int(ADDON.getSetting('paginate_episodes')) == 0: current_page_match = re.search(r'page=(\d*)', page_url) if current_page_match: current_page = int(current_page_match.group(1)) page_range = range(current_page, current_page + 1) next_page_match = re.search( r'<span class="next txt">.+?href="(.*?page=)(.*?)"', paginate.group(0), re.DOTALL) if next_page_match: page_base_url = next_page_match.group(1) next_page = int(next_page_match.group(2)) else: next_page = current_page page_range = range(current_page, current_page + 1) else: pages = re.findall(r'<li class="page.*?</li>', paginate.group(0), re.DOTALL) if pages: last = pages[-1] last_page = re.search(r'<a href="(.*?page=)(.*?)"', last) page_base_url = last_page.group(1) total_pages = int(last_page.group(2)) page_range = range(1, total_pages + 1) for page in page_range: if page > current_page: page_url = 'http://www.bbc.co.uk' + page_base_url + str(page) html = OpenURL(page_url) # NOTE remove inner li to match outer li # <li data-version-type="hd"> html = re.compile(r'<li data-version-type.*?</li>', flags=(re.DOTALL | re.MULTILINE)).sub('', html) # <li class="list-item programme" data-ip-id="p026f2t4"> list_items = re.findall(r'<li class="list-item.*?</li>', html, flags=(re.DOTALL | re.MULTILINE)) list_item_num = 1 for li in list_items: # <li class="list-item unavailable" data-ip-id="b06sq9xj"> unavailable_match = re.search( '<li class="list-item.*?unavailable.*?"', li, flags=(re.DOTALL | re.MULTILINE)) if unavailable_match: continue # <li class="list-item search-group" data-ip-id="b06rdtx0"> search_group = False search_group_match = re.search( '<li class="list-item.*?search-group.*?"', li, flags=(re.DOTALL | re.MULTILINE)) if search_group_match: search_group = True main_url = None # <a href="/iplayer/episode/p026gmw9/world-of-difference-the-models" # title="World of Difference, The Models" class="list-item-link stat" url_match = re.search(r'<a.*?href="(.*?)".*?list-item-link.*?>', li, flags=(re.DOTALL | re.MULTILINE)) if url_match: url = url_match.group(1) if url: main_url = 'http://www.bbc.co.uk' + url name = '' title = '' #<div class="title top-title">World of Difference</div> title_match = re.search( r'<div class="title top-title">\s*(.*?)\s*</div>', li, flags=(re.DOTALL | re.MULTILINE)) if title_match: title = title_match.group(1) name = title subtitle = None #<div class="subtitle">The Models</div> subtitle_match = re.search( r'<div class="subtitle">\s*(.*?)\s*</div>', li, flags=(re.DOTALL | re.MULTILINE)) if subtitle_match: subtitle = subtitle_match.group(1) if subtitle: name = name + " - " + subtitle icon = '' type = None # <div class="r-image" data-ip-type="episode" # data-ip-src="http://ichef.bbci.co.uk/images/ic/336x189/p026vl1q.jpg"> # <div class="r-image" data-ip-type="group" # data-ip-src="http://ichef.bbci.co.uk/images/ic/336x189/p037ty9z.jpg"> image_match = re.search( r'<div class="r-image".+?data-ip-type="(.*?)".+?data-ip-src="http://ichef.bbci.co.uk/images/ic/336x189/(.*?)\.jpg"', li, flags=(re.DOTALL | re.MULTILINE)) if image_match: type = image_match.group(1) image = image_match.group(2) if image: icon = "http://ichef.bbci.co.uk/images/ic/832x468/" + image + ".jpg" synopsis = '' # <p class="synopsis">What was it like to be a top fashion model 30 years ago? (1978)</p> synopsis_match = re.search(r'<p class="synopsis">\s*(.*?)\s*</p>', li, flags=(re.DOTALL | re.MULTILINE)) if synopsis_match: synopsis = synopsis_match.group(1) aired = '' # <span class="release">\nFirst shown: 8 Jun 1967\n</span> release_match = re.search( r'<span class="release">.*?First shown:\s*(.*?)\n.*?</span>', li, flags=(re.DOTALL | re.MULTILINE)) if release_match: release = release_match.group(1) if release: aired = FirstShownToAired(release) episodes = None # <a class="view-more-container avail stat" href="/iplayer/episodes/p00db1jf" data-progress-state=""> # <a class="view-more-container sibling stat" # href="/iplayer/search?q=doctor&search_group_id=urn:bbc:programmes:b06qbs4n"> episodes_match = re.search( r'<a class="view-more-container.+?stat".+?href="(.*?)"', li, flags=(re.DOTALL | re.MULTILINE)) if episodes_match: episodes = episodes_match.group(1) more = None # <em class="view-more-heading">27</em> more_match = re.search(r'<em class="view-more-heading">(.*?)</em>', li, flags=(re.DOTALL | re.MULTILINE)) if more_match: more = more_match.group(1) if episodes: episodes_url = 'http://www.bbc.co.uk' + episodes if search_group: AddMenuEntry( '[B]%s[/B] - %s' % (title, translation(30318)), episodes_url, 128, icon, '', '') else: AddMenuEntry( '[B]%s[/B] - %s %s' % (title, more, translation(30313)), episodes_url, 128, icon, '', '') elif more: AddMenuEntry( '[B]%s[/B] - %s %s' % (title, more, translation(30313)), main_url, 128, icon, '', '') if type != "group": CheckAutoplay(name, main_url, icon, synopsis, aired) percent = int(100 * (page + list_item_num / len(list_items)) / total_pages) pDialog.update(percent, translation(30319), name) list_item_num += 1 percent = int(100 * page / total_pages) pDialog.update(percent, translation(30319)) if int(ADDON.getSetting('paginate_episodes')) == 0: if current_page < next_page: page_url = 'http://www.bbc.co.uk' + page_base_url + str(next_page) AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 128, '', '', '') xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE) xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED) pDialog.close()