def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== if self.channelCode == "ketnet": self.noImage = "ketnetimage.jpg" self.mainListUri = "https://www.ketnet.be/kijken" self.baseUrl = "https://www.ketnet.be" self.mediaUrlRegex = r'playerConfig\W*=\W*(\{[\w\W]{0,2000}?);(?:.vamp|playerConfig)' elif self.channelCode == "cobra": self.noImage = "cobraimage.png" self.mainListUri = "http://www.cobra.be/cm/cobra/cobra-mediaplayer" self.baseUrl = "http://www.cobra.be" self.swfUrl = "%s/html/flash/common/player.swf" % (self.baseUrl, ) episode_regex = r'<a[^>]+href="(?<url>/kijken[^"]+)"[^>]*>\W*<img[^>]+src="' \ r'(?<thumburl>[^"]+)"[^>]+alt="(?<title>[^"]+)"' episode_regex = Regexer.from_expresso(episode_regex) self._add_data_parser(self.mainListUri, match_type=ParserData.MatchExact, parser=episode_regex, creator=self.create_episode_item) self._add_data_parser("*", preprocessor=self.select_video_section) video_regex = Regexer.from_expresso( r'<a title="(?<title>[^"]+)" href="(?<url>[^"]+)"[^>]*>' r'\W+<img src="(?<thumburl>[^"]+)"[^<]+<span[^<]+[^<]+' r'[^>]+></span>\W+(?<description>[^<]+)') self._add_data_parser("*", parser=video_regex, creator=self.create_video_item, updater=self.update_video_item) folder_regex = Regexer.from_expresso( r'<span class="more-of-program" rel="/(?<url>[^"]+)">') self._add_data_parser("*", parser=folder_regex, creator=self.create_folder_item) #=============================================================================================================== # non standard items #=============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.noImage = "eenimage.png" # setup the urls self.mainListUri = "https://www.een.be/programmas" self.baseUrl = "http://www.een.be" # setup the main parsing data self._add_data_parser(self.mainListUri, preprocessor=self.extract_json, json=True, parser=["data", ], creator=self.create_show_item) video_parser = r'<a class="card-teaser"[^>][^>]*href="(?<url>[^"]+)"[^>]*>\W+<div[^>]+' \ r'style="background-image: url\(\'(?<thumburl>[^\']+/(?<year>\d{4})/' \ r'(?<month>\d{2})/(?<day>\d{2})/[^\']+)\'[^>]*>\W+<div[^>]+_play[\w\W+]' \ r'{0,2000}?<div[^>]*>(?<_title>[^>]*)</div>\W*<h3[^>]*>(?<title>[^<]+)' \ r'</h3>\W+<div[^>]*>\W+(?:<span[^>]*>[^<]*</span>)?(?<description>[^<]+)' video_parser = Regexer.from_expresso(video_parser) self._add_data_parser("*", name="Links to teasers of videos (Card teaser)", parser=video_parser, creator=self.create_video_item, updater=self.update_video_item) video_parser = r'<a[^>]*class="[^"]+-teaser"[^>]*background-image: url\(\'(?<thumburl>' \ r'[^\']+/(?<year>\d{4})/(?<month>\d{2})/(?<day>\d{2})/[^\']+)\'[^>]*href="' \ r'(?<url>[^"]+)"[^>]*>\W+<div[^>]+_play[\w\W+]{0,2000}?<div[^>]*>' \ r'(?<_title>[^>]*)</div>\W*<h3[^>]*>(?<title>[^<]+)</h3>\W+<div[^>]*>\W+' \ r'(?:<span[^>]*>[^<]*</span>)?(?<description>[^<]+)' video_parser = Regexer.from_expresso(video_parser) self._add_data_parser("*", name="Links to teasers of videos (Image Teaser)", parser=video_parser, creator=self.create_video_item, updater=self.update_video_item) single_video_parser = r'>(?<title>[^<]+)</h1>[\w\W]{0,2000}?(?:<h2>?<description>[^<]+)?' \ r'[\w\W]{0,1000}?data-video="(?<url>[^"]+)"[\w\W]{0,500}data-analytics' \ r'=\'{"date":"(?<year>\d+)-(?<month>\d+)-(?<day>\d+)' single_video_parser = Regexer.from_expresso(single_video_parser) self._add_data_parser("*", name="Pages that contain only a single video", parser=single_video_parser, creator=self.create_video_item) #=============================================================================================================== # non standard items #=============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.noImage = "vtmimage.jpg" # setup the urls self.mainListUri = "http://nieuws.vtm.be/herbekijk" self.baseUrl = "http://nieuws.vtm.be" # setup the main parsing data self.episodeItemRegex = '<li><a[^>]+href="/([^"]+)" class="level-1[^>]+>([^<]+)</a>' self._add_data_parser(self.mainListUri, creator=self.create_episode_item, parser=self.episodeItemRegex) video_item_regex = r'<article[^<]+has-video"[^>]*>\W*<a href="(?<Url>[^<"]+)"[^>]*>\W+' \ r'<div[^<]+<img[^>]+src="(?<Thumb>[^"]+)"[^>]*>[\w\W]{0,500}?<h3[^>]*>' \ r'(?:\W+<span[^>]*>[^>]*>)?(?<Title>[^<]+)</h3>\W+<div[^<]+<time[^>]+' \ r'datetime="(?<DateTime>[^"]+)"[^<]+</time>\W*</div>\W*<p[^>]+>*' \ r'(?<Description>[^<]+)' video_item_regex = Regexer.from_expresso(video_item_regex) self._add_data_parser("*", creator=self.create_video_item, parser=video_item_regex, updater=self.update_video_item) stadion_regex = r'<article[^>]*>\W*<div class="image is-video">\W*<a href="(?<Url>[^"]+)' \ r'[^>]*>\W*<img[^>]+src="(?<Thumb>[^"]+)"[\w\W]{0,1000}?<h3 class=' \ r'"pagemanager-item-title">\W*<span>\W*<a[^>]*>(?<Title>[^<]+)[\w\W]' \ r'{0,1000}?<div class="teaser">\W*<a[^>]+>(?<Description>[^<]+)' stadion_regex = Regexer.from_expresso(stadion_regex) self._add_data_parser("http://nieuws.vtm.be/stadion", parser=stadion_regex, creator=self.create_video_item, updater=self.update_video_item) self.pageNavigationRegex = '' self.pageNavigationRegexIndex = 0 #=============================================================================================================== # non standard items #=============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.noImage = "l1image.png" # setup the urls self.mainListUri = "https://l1.nl/gemist/" self.baseUrl = "https://l1.nl" # setup the main parsing data episode_regex = r'<li>\W*<a[^>]*href="(?<url>/[^"]+)"[^>]*>(?<title>[^<]+)</a>\W*</li>' episode_regex = Regexer.from_expresso(episode_regex) self._add_data_parser(self.mainListUri, preprocessor=self.pre_process_folder_list, parser=episode_regex, creator=self.create_episode_item) # live stuff self._add_data_parsers(["#livetv", "#liveradio"], updater=self.update_live_stream) video_regex = r'<a[^>]*class="mediaItem"[^>]*href="(?<url>[^"]+)"[^>]*title="(?<title>' \ r'[^"]+)"[^>]*>[\w\W]{0,500}?<img[^>]+src="/(?<thumburl>[^"]+)' video_regex = Regexer.from_expresso(video_regex) self._add_data_parser("*", parser=video_regex, creator=self.create_video_item, updater=self.update_video_item) page_regex = r'<a[^>]+href="https?://l1.nl/([^"]+?pagina=)(\d+)"' page_regex = Regexer.from_expresso(page_regex) self.pageNavigationRegexIndex = 1 self._add_data_parser("*", parser=page_regex, creator=self.create_page_item) #=============================================================================================================== # non standard items #=============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.videoType = None self.noImage = "eredivisieimage.jpg" # setup the urls self.baseUrl = "https://www.foxsports.nl" self.mainListUri = "https://www.foxsports.nl/videos/" self.swfUrl = "https://static.eredivisielive.nl/static/swf/edPlayer-1.6.2.plus.swf" # setup the main parsing data # self.episodeItemRegex = '<option[^>]+value="([^"]+)"[^=>]+(?:data-season="([^"]+)")?[^=>]*>([^<]+)</option>' # self.videoItemJson = ("item",) self._add_data_parser( self.mainListUri, parser=Regexer.from_expresso( '<a [hd][^>]*ata-(?<Type>area|sport)="(?<Url>[^"]+)[^>]*>' '(?<Title>[^<]+)</a>'), creator=self.create_folder_item) self._add_data_parser( self.mainListUri, parser=Regexer.from_expresso( r'<a[^>]+href="/video/(?<Type>filter|meest_bekeken)/?' r'(?<Url>[^"]*)">[^<]*</a>\W+<h1[^>]*>(?<Title>[^<;]+)' r'(?:'s){0,1}</h1>'), creator=self.create_folder_item) self._add_data_parser( "https://www.foxsports.nl/video/filter/fragments/", preprocessor=self.add_pages, parser=Regexer.from_expresso( r'<img[^>]+src=\'(?<Thumb>[^\']+)\'[^>]*>\W+</picture>\W+' r'<span class="[^"]+play[\w\W]{0,500}?<h1[^>]*>\W+<a href="' r'(?<Url>[^"]+)"[^>]*>(?<Title>[^<]+)</a>\W+</h1>\W+<span' r'[^>]*>(?<Date>[^>]+)</span>'), creator=self.create_video_item) self._add_data_parser("*", updater=self.update_video_item) # ====================================== Actual channel setup STOPS here ======================================= return
def __update_video_from_brightcove(self, item, data, use_adaptive_with_encryption): """ Updates an existing MediaItem with more data based on an MPD stream. :param str data: Stream info retrieved from BrightCove. :param bool use_adaptive_with_encryption: Do we use the Adaptive InputStream add-on? :param MediaItem item: The original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ part = item.create_new_empty_media_part() # Then try the new BrightCove JSON bright_cove_regex = '<video[^>]+data-video-id="(?<videoId>[^"]+)[^>]+data-account="(?<videoAccount>[^"]+)' bright_cove_data = Regexer.do_regex( Regexer.from_expresso(bright_cove_regex), data) if not bright_cove_data: Logger.warning("Error updating using BrightCove data: %s", item) return item Logger.info("Found new BrightCove JSON data") bright_cove_url = 'https://edge.api.brightcove.com/playback/v1/accounts/' \ '%(videoAccount)s/videos/%(videoId)s' % bright_cove_data[0] headers = { "Accept": "application/json;pk=BCpkADawqM3ve1c3k3HcmzaxBvD8lXCl89K7XEHiKutxZArg2c5RhwJHJANOwPwS_4o7UsC4RhIzXG8Y69mrwKCPlRkIxNgPQVY9qG78SJ1TJop4JoDDcgdsNrg" } bright_cove_data = UriHandler.open(bright_cove_url, additional_headers=headers) bright_cove_json = JsonHelper(bright_cove_data) streams = [ d for d in bright_cove_json.get_value("sources") if d["container"] == "M2TS" ] # Old filter # streams = filter(lambda d: d["container"] == "M2TS", bright_cove_json.get_value("sources")) if not streams: Logger.warning("Error extracting streams from BrightCove data: %s", item) return item # noinspection PyTypeChecker stream_url = streams[0]["src"] # these streams work better with the the InputStreamAddon because it removes the # "range" http header if use_adaptive_with_encryption: Logger.info("Using InputStreamAddon for playback of HLS stream") strm = part.append_media_stream(stream_url, 0) M3u8.set_input_stream_addon_input(strm) item.complete = True return item for s, b in M3u8.get_streams_from_m3u8(stream_url): item.complete = True part.append_media_stream(s, b) return item
def add_search_and_genres(self, data): """ Performs pre-process actions for data processing and adds a search option and genres. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Performing Pre-Processing") items = [] if self.parentItem is not None and "genre" in self.parentItem.metaData: self.__genre = self.parentItem.metaData["genre"] Logger.debug("Parsing a specific genre: %s", self.__genre) return data, items search_item = MediaItem("\a.: Sök :.", "searchSite") search_item.complete = True search_item.thumb = self.noImage search_item.dontGroup = True search_item.fanart = self.fanart # search_item.set_date(2099, 1, 1, text="") # -> No items have dates, so adding this will force a date sort in Retrospect items.append(search_item) genres_item = MediaItem("\a.: Genrer :.", "") genres_item.complete = True genres_item.thumb = self.noImage genres_item.dontGroup = True genres_item.fanart = self.fanart items.append(genres_item) # find the actual genres genre_regex = '<li[^>]+genre[^>]*><button[^>]+data-value="(?<genre>[^"]+)"[^>]*>' \ '(?<title>[^>]+)</button></li>' genre_regex = Regexer.from_expresso(genre_regex) genres = Regexer.do_regex(genre_regex, data) for genre in genres: if genre["genre"] == "all": continue genre_item = MediaItem(genre["title"], self.mainListUri) genre_item.complete = True genre_item.thumb = self.noImage genre_item.fanart = self.fanart genre_item.metaData = {"genre": genre["genre"]} genres_item.items.append(genre_item) Logger.debug("Pre-Processing finished") return data, items
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.noImage = "twitimage.png" # setup the urls self.mainListUri = "https://twit.tv/shows" self.baseUrl = "https://twit.tv" # setup the main parsing data self.episodeItemRegex = r'<img[^>]+src="(?<thumburl>[^"]+)"[^>]*></a>\W+<div[^>]+>\W+' \ r'<h2[^>]*><a[^>]+href="/(?<url>shows/[^"]+)"[^>]*>(?<title>[^<]+)' \ r'</a></h2>\W+<div[^>]*>(?<description>[^<]+)' self.episodeItemRegex = Regexer.from_expresso(self.episodeItemRegex) self._add_data_parser(self.mainListUri, preprocessor=self.add_live_stream, match_type=ParserData.MatchExact, parser=self.episodeItemRegex, creator=self.create_episode_item) self.videoItemRegex = r'<div[^>]+class="episode item"[^>]*>\W+<a[^>]+href="(?<url>[^"]+)" ' \ r'title="(?<title>[^"]+)">[\w\W]{0,500}?<img[^>]+src="' \ r'(?<thumburl>[^"]+)"[^>]+>[\w\W]{0,500}?<span[^>]+class="date"' \ r'[^>]*>(?<month>\w+) (?<day>\d+)\w+ (?<year>\d+)' self.videoItemRegex = Regexer.from_expresso(self.videoItemRegex) self._add_data_parser("*", parser=self.videoItemRegex, creator=self.create_video_item, updater=self.update_video_item) self.mediaUrlRegex = r'<a href="([^"]+_(\d+).mp4)"[^>]+download>' # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== # setup the urls self.baseUrl = "https://www.kijkbijons.nl" self.mainListUri = "https://www.kijkbijons.nl/programmas" # Setup textures self.noImage = "onsimage.png" # Define parsers episode_regex = r'<a class="clipItem"[^>]*href="(?<url>[^"]+)[^>]*>\s*<span class="clipItemImage">\s*<img[^>]*src="(?<thumburl>[^"]+)"[^>]+alt="(?<title>[^"]+)"[^>]*>' self._add_data_parser(self.mainListUri, name="Main Programlist", parser=Regexer.from_expresso(episode_regex), creator=self.create_episode_item) video_regex = r'<a class="clipItem"\s+href="(?<url>[^"]+item\?(?<id>[^"]+))"[^>]+>\s+<[^>]+>\s*<img src="(?<thumb>[^"]+)[^>]*>\s*(?:[^>]+>\s*){4}(?<title>[^\n\r<]+)' self._add_data_parser("*", name="Main Video parsers", parser=Regexer.from_expresso(video_regex), creator=self.create_video_item, updater=self.update_video_item) #=============================================================================================================== # non standard items return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # configure login stuff # setup the urls self.noImage = "flevoimage.png" self.mainListUri = "https://www.omroepflevoland.nl/block/missed/list?category=Gemist&page=1" self.baseUrl = "https://www.omroepflevoland.nl" self.channelBitrate = 780 video_item_regex = r'<a[^>]+href="(?<url>[^"]+)"(?:[^>]+>\W*){2}<picture[^>]+>\s*' \ r'<source[^>]+srcset="(?<thumburl>[^"]+)"[^>]*>\s*(?:[^>]+>){9}\s*<h5>' \ r'(?<title>[^<]+)<[^>]*>\s*(?<date>\d+-\d+-\d+\s+\d+:\d+)(?:[^>]+>)' \ r'{11}\W*(?<description>[^<]+)</p>' video_item_regex = Regexer.from_expresso(video_item_regex) self._add_data_parser(self.mainListUri, preprocessor=self.add_live_streams, parser=video_item_regex, creator=self.create_video_item) self._add_data_parser("https://[^/]*.cloudfront.net/live/", updater=self.update_live_urls, match_type=ParserData.MatchRegex) self._add_data_parser("*", preprocessor=self.add_live_streams, parser=video_item_regex, creator=self.create_video_item, updater=self.update_video_item) #=============================================================================================================== # non standard items #=============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # setup the main parsing data if self.channelCode == "vijfbe": self.noImage = "vijfimage.png" self.mainListUri = "https://www.vijf.be/" self.baseUrl = "https://www.vijf.be" elif self.channelCode == "zesbe": self.noImage = "zesimage.png" self.mainListUri = "https://www.zestv.be/" self.baseUrl = "https://www.zestv.be" else: self.noImage = "vierimage.png" self.mainListUri = "https://www.vier.be/" self.baseUrl = "https://www.vier.be" episode_regex = '<a class="program-overview__link" href="(?<url>[^"]+)">\s+<span class="program-overview__title">\s+(?<title>[^<]+)</span>.*?</a>' episode_regex = Regexer.from_expresso(episode_regex) self._add_data_parser(self.mainListUri, match_type=ParserData.MatchExact, parser=episode_regex, creator=self.create_episode_item) self._add_data_parser("*", match_type=ParserData.MatchExact, name="Json video items", json=True, preprocessor=self.extract_hero_data, parser=["data", "playlists", 0, "episodes"], creator=self.create_video_item_api) video_regex = r'<a(?:[^>]+data-background-image="(?<thumburl>[^"]+)")?[^>]+href="' \ r'(?<url>/video/[^"]+)"[^>]*>(?:\s+<div[^>]+>\s+<div [^>]+' \ r'data-background-image="(?<thumburl2>[^"]+)")?[\w\W]{0,1000}?' \ r'<h3[^>]*>(?:<span>)?(?<title>[^<]+)(?:</span>)?</h3>(?:\s+' \ r'(?:<div[^>]*>\s+)?<div[^>]*>[^<]+</div>\s+<div[^>]+data-timestamp=' \ r'"(?<timestamp>\d+)")?' video_regex = Regexer.from_expresso(video_regex) self._add_data_parser("*", match_type=ParserData.MatchExact, name="Normal video items", parser=video_regex, creator=self.create_video_item) # Generic updater with login self._add_data_parser("https://api.viervijfzes.be/content/", updater=self.update_video_item_with_id) self._add_data_parser("*", updater=self.update_video_item) # ========================================================================================== # Channel specific stuff self.__idToken = None self.__meta_playlist = "current_playlist" self.__no_clips = False # ========================================================================================== # Test cases: # Documentaire: pages (has http://www.canvas.be/tag/.... url) # Not-Geo locked: Kroost # ====================================== Actual channel setup STOPS here =================== return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== self.noImage = "vrtnuimage.png" self.mainListUri = "https://www.vrt.be/vrtnu/a-z/" self.baseUrl = "https://www.vrt.be" # first regex is a bit tighter than the second one. episode_regex = r'<nui-tile href="(?<url>/vrtnu[^"]+)"[^>]*>\s*<h3[^>]*>\s*<a[^>]+>' \ r'(?<title>[^<]+)</a>\s*</h3>\s*<div[^>]+>(?:\s*<p>)?(?<description>' \ r'[\w\W]{0,2000}?)(?:</p>)?\W*</div>\s*(?:<p[^>]*' \ r'data-brand="(?<channel>[^"]+)"[^>]*>[^<]+</p>)?\s*(?:<img[\w\W]{0,100}?' \ r'data-responsive-image="(?<thumburl>//[^" ]+)")?' episode_regex = Regexer.from_expresso(episode_regex) self._add_data_parser(self.mainListUri, name="Main A-Z listing", preprocessor=self.add_categories, match_type=ParserData.MatchExact, parser=episode_regex, creator=self.create_episode_item) self._add_data_parser("#channels", name="Main channel name listing", preprocessor=self.list_channels) self._add_data_parser("https://search.vrt.be/suggest?facets[categories]", name="JSON Show Parser", json=True, parser=[], creator=self.create_show_item) self._add_data_parser("https://services.vrt.be/videoplayer/r/live.json", json=True, name="Live streams parser", parser=[], creator=self.create_live_stream) self._add_data_parsers(["http://live.stream.vrt.be/", "https://live-vrt.akamaized.net"], name="Live streams updater", updater=self.update_live_video) self._add_data_parser(r"https://live-[^/]+\.vrtcdn\.be", match_type=ParserData.MatchRegex, name="Live streams updater", updater=self.update_live_video) self._add_data_parser("https://www.vrt.be/vrtnu/categorieen.model.json", name="Category parser", json=True, match_type=ParserData.MatchExact, parser=[":items", "par", ":items", "categories", "items"], creator=self.create_category) folder_regex = r'<li class="vrt-labelnav--item "[^>]*>\s*(?:<h2[^<]*>\s*)?<a[^>]*href="(?<url>[^"]+)"[^>]*>(?:\W*<nui[^>]*>\W*)?(?<title>[^<]+)</' folder_regex = Regexer.from_expresso(folder_regex) self._add_data_parser("*", name="Folder/Season parser", parser=folder_regex, creator=self.create_folder_item) video_regex = r'<a[^>]+href="(?<url>/vrtnu/(?:[^/]+/){2}[^/]*?(?<year2>\d*)/[^"]+)"[^>]*>' \ r'\W*(?<title>[^<]+)(?:<br\s*/>\s*)?</a>\s*</h3>\s*<p[^>]*>\W*(?<channel>[^<]+)' \ r'</p>\s*(?:<p[^<]+</p>\s*)?<div[^>]*class="meta[^>]*>\s*(?:<time[^>]+datetime=' \ r'"(?<year>\d+)-(?<month>\d+)-(?<day>\d+))?[\w\W]{0,1000}?ata-responsive-image=' \ r'"(?<thumburl>[^"]+)' # No need for a subtitle for now as it only includes the textual date video_regex = Regexer.from_expresso(video_regex) self._add_data_parser("*", name="Video item parser", parser=video_regex, creator=self.create_video_item) # needs to be after the standard video item regex single_video_regex = r'<script type="application/ld\+json">\W+({[\w\W]+?})\s*</script' single_video_regex = Regexer.from_expresso(single_video_regex) self._add_data_parser("*", name="Single video item parser", parser=single_video_regex, creator=self.create_single_video_item) self._add_data_parser("*", updater=self.update_video_item, requires_logon=True) # =============================================================================================================== # non standard items self.__hasAlreadyVideoItems = False self.__currentChannel = None # The key is the channel live stream key self.__channelData = { "vualto_mnm": { "title": "MNM", "metaCode": "mnm", "fanart": TextureHandler.instance().get_texture_uri(self, "mnmfanart.jpg"), "thumb": TextureHandler.instance().get_texture_uri(self, "mnmimage.jpg"), "icon": TextureHandler.instance().get_texture_uri(self, "mnmicon.png") }, "vualto_stubru": { "title": "Studio Brussel", "metaCode": "stubru", "fanart": TextureHandler.instance().get_texture_uri(self, "stubrufanart.jpg"), "thumb": TextureHandler.instance().get_texture_uri(self, "stubruimage.jpg"), "icon": TextureHandler.instance().get_texture_uri(self, "stubruicon.png") }, "vualto_een_geo": { "title": "Eén", "metaCode": "een", "fanart": TextureHandler.instance().get_texture_uri(self, "eenfanart.jpg"), "thumb": TextureHandler.instance().get_texture_uri(self, "eenimage.png"), "icon": TextureHandler.instance().get_texture_uri(self, "eenlarge.png"), # "url": "https://live-vrt.akamaized.net/groupc/live/8edf3bdf-7db3-41c3-a318-72cb7f82de66/live_aes.isml/.m3u8" }, "vualto_canvas_geo": { "title": "Canvas", "metaCode": "canvas", "fanart": TextureHandler.instance().get_texture_uri(self, "canvasfanart.png"), "thumb": TextureHandler.instance().get_texture_uri(self, "canvasimage.png"), "icon": TextureHandler.instance().get_texture_uri(self, "canvaslarge.png"), # "url": "https://live-vrt.akamaized.net/groupc/live/14a2c0f6-3043-4850-88a5-7fb062fe7f05/live_aes.isml/.m3u8" }, "vualto_ketnet_geo": { "title": "KetNet", "metaCode": "ketnet", "fanart": TextureHandler.instance().get_texture_uri(self, "ketnetfanart.jpg"), "thumb": TextureHandler.instance().get_texture_uri(self, "ketnetimage.jpg"), "icon": TextureHandler.instance().get_texture_uri(self, "ketnetlarge.png"), # "url": "https://live-vrt.akamaized.net/groupc/live/f132f1b8-d04d-404e-90e0-6da1abb4f4fc/live_aes.isml/.m3u8" }, "vualto_sporza_geo": { # not in the channel filter maps, so no metaCode "title": "Sporza", "fanart": TextureHandler.instance().get_texture_uri(self, "sporzafanart.jpg"), "thumb": TextureHandler.instance().get_texture_uri(self, "sporzaimage.jpg"), "icon": TextureHandler.instance().get_texture_uri(self, "sporzalarge.png"), # "url": "https://live-vrt.akamaized.net/groupa/live/7d5f0e4a-3429-4861-91d4-aa3229d7ad7b/live_aes.isml/.m3u8" }, "ketnet-jr": { # Not in the live channels "title": "KetNet Junior", "metaCode": "ketnet-jr", "fanart": TextureHandler.instance().get_texture_uri(self, "ketnetfanart.jpg"), "thumb": TextureHandler.instance().get_texture_uri(self, "ketnetimage.jpg"), "icon": TextureHandler.instance().get_texture_uri(self, "ketnetlarge.png") } } # To get the tokens: # POST # Content-Type:application/json # https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v1/tokens # =============================================================================================================== # Test cases: # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== # setup the main parsing data if self.channelCode == 'nickelodeon': self.noImage = "nickelodeonimage.png" self.mainListUri = "http://www.nickelodeon.nl/shows" self.baseUrl = "http://www.nickelodeon.nl" elif self.channelCode == "nickno": self.noImage = "nickelodeonimage.png" self.mainListUri = "http://www.nickelodeon.no/program/" self.baseUrl = "http://www.nickelodeon.no" else: raise NotImplementedError("Unknown channel code") episode_item_regex = r"""<a[^>]+href="(?<url>/[^"]+)"[^>]*>\W*<img[^>]+src='(?<thumburl>[^']+)'[^>]*>\W*<div class='info'>\W+<h2 class='title'>(?<title>[^<]+)</h2>\W+<p class='sub_title'>(?<description>[^<]+)</p>""" episode_item_regex = Regexer.from_expresso(episode_item_regex) self._add_data_parser(self.mainListUri, match_type=ParserData.MatchExact, preprocessor=self.no_nick_jr, parser=episode_item_regex, creator=self.create_episode_item) # <h2 class='row-title'>Nick Jr video_item_regex = r"""<li[^>]+data-item-id='\d+'>\W+<a href='(?<url>[^']+)'>\W+<img[^>]+src="(?<thumburl>[^"]+)"[^>]*>\W+<p class='title'>(?<title>[^<]+)</p>\W+<p[^>]+class='subtitle'[^>]*>(?<subtitle>[^>]+)</p>""" video_item_regex = Regexer.from_expresso(video_item_regex) self._add_data_parser("*", preprocessor=self.pre_process_folder_list, parser=video_item_regex, creator=self.create_video_item, updater=self.update_video_item) self.pageNavigationRegex = r'href="(/video[^?"]+\?page_\d*=)(\d+)"' self.pageNavigationRegexIndex = 1 self._add_data_parser("*", parser=self.pageNavigationRegex, creator=self.create_page_item) self.mediaUrlRegex = '<param name="src" value="([^"]+)" />' # used for the update_video_item self.swfUrl = "http://origin-player.mtvnn.com/g2/g2player_2.1.7.swf" #=============================================================================================================== # Test cases: # NO: Avator -> Other items # SE: Hotel 13 -> Other items # NL: Sam & Cat -> Other items # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== if self.channelCode == "sporza": self.noImage = "sporzaimage.jpg" self.mainListUri = "http://sporza.be/cm/sporza/videozone" self.baseUrl = "http://sporza.be" else: raise IndexError("Invalid Channel Code") # elif self.channelCode == "ketnet": # self.noImage = "ketnetimage.png" # self.mainListUri = "http://video.ketnet.be/cm/ketnet/ketnet-mediaplayer" # self.baseUrl = "http://video.ketnet.be" # # elif self.channelCode == "cobra": # self.noImage = "cobraimage.png" # self.mainListUri = "http://www.cobra.be/cm/cobra/cobra-mediaplayer" # self.baseUrl = "http://www.cobra.be" # setup the urls self.swfUrl = "%s/html/flash/common/player.5.10.swf" % (self.baseUrl,) # setup the main parsing data episode_regex = r'<li[^>]*>\W*<a href="(/cm/[^"]+/videozone/programmas/[^"]+)" ' \ r'title="([^"]+)"\W*>' self._add_data_parser(self.mainListUri, match_type=ParserData.MatchExact, preprocessor=self.add_live_channel, parser=episode_regex, creator=self.create_episode_item) # extract the right section, although it is hard to determine the actual one self._add_data_parser("*", preprocessor=self.extract_video_section) # the main video of the page regex = Regexer.from_expresso( r'<img[^>]+src="(?<thumburl>[^"]+)"[^>]*>[\w\W]{0,700}<p>(?<description>[^<]+)</p>' r'[\w\W]{0,500}?<a href="(?<url>/cm/[^/]+/videozone/[^?"]+)" >(?<title>[^<]+)</a>') self._add_data_parser("*", name="Main video of the page", parser=regex, creator=self.create_video_item) # other videos in the side bar regex = Regexer.from_expresso( r'<a[^>]*href="(?<url>[^"]+)"[^>]*class="videolink"[^>]*>\W*<span[^>]*>(?<title>[^"]+)' r'</span>\W*(?:<span[^>]*>(?<desciption>[^"]+)</span>\W*)?<span[^>]*>\W*<img[^>]*' r'src="(?<thumburl>[^"]+)"') self._add_data_parser("*", name="Other videos in the sidebar", parser=regex, creator=self.create_video_item, updater=self.update_video_item) # live streams live_regex = r'data-video-title="([^"]+)"\W+data-video-iphone-server="([^"]+)"\W+' \ r'[\w\W]{0,1000}data-video-sitestat-pubdate="(\d+)"[\w\W]{0,2000}' \ r'data-video-geoblocking="(\w+)"[^>]+>\W*<img[^>]*src="([^"]+)"' self._add_data_parser("http://sporza.be/cm/sporza/matchcenter/mc_livestream", creator=self.create_live_channel, parser=live_regex) self._add_data_parser("http://live.stream.vrt.be", updater=self.update_live_item) self.mediaUrlRegex = r'data-video-((?:src|rtmp|iphone|mobile)[^=]*)="([^"]+)"\W+' \ r'(?:data-video-[^"]+path="([^"]+)){0,1}' # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ==== Actual channel setup STARTS here and should be overwritten from derived classes ==== self.noImage = "urplayimage.png" # setup the urls self.mainListUri = "https://urplay.se/api/bff/v1/search?product_type=series&rows=10000&start=0" self.baseUrl = "https://urplay.se" self.swfUrl = "https://urplay.se/assets/jwplayer-6.12-17973009ab259c1dea1258b04bde6e53.swf" # Match the "series" API -> shows TV Shows self._add_data_parser(self.mainListUri, json=True, name="Show parser with categories", match_type=ParserData.MatchExact, preprocessor=self.add_categories_and_search, parser=["results"], creator=self.create_episode_json_item) # Match Videos (programs) self._add_data_parser( "https://urplay.se/api/bff/v1/search?product_type=program", name="Most viewed", json=True, parser=["results"], creator=self.create_video_item_json) self._add_data_parser("*", json=True, name="Json based video parser", preprocessor=self.extract_json_data, parser=["currentProduct", "series", "programs"], creator=self.create_video_item_json) self._add_data_parser("*", updater=self.update_video_item) # Categories cat_reg = r'<a[^>]+href="(?<url>/blad[^"]+/(?<slug>[^"]+))"[^>]*>(?<title>[^<]+)<' cat_reg = Regexer.from_expresso(cat_reg) self._add_data_parser("https://urplay.se/", name="Category parser", match_type=ParserData.MatchExact, parser=cat_reg, creator=self.create_category_item) self._add_data_parsers([ "https://urplay.se/api/bff/v1/search?play_category", "https://urplay.se/api/bff/v1/search?response_type=category" ], name="Category content", json=True, parser=["results"], creator=self.create_json_item) # Searching self._add_data_parser("https://urplay.se/search/json", json=True, parser=["programs"], creator=self.create_search_result_program) self._add_data_parser("https://urplay.se/search/json", json=True, parser=["series"], creator=self.create_search_result_serie) self.mediaUrlRegex = r"urPlayer.init\(([^<]+)\);" #=========================================================================================== # non standard items self.__videoItemFound = False self.__cateogory_slugs = { "dokumentarfilmer": "dokument%C3%A4rfilmer", "forelasningar": "f%C3%B6rel%C3%A4sningar", "kultur-och-historia": "kultur%20och%20historia", "reality-och-livsstil": "reality%20och%20livsstil", "samhalle": "samh%C3%A4lle" } self.__cateogory_urls = { "radio": "https://urplay.se/api/bff/v1/search?response_type=category" "&singles_and_series=true" "&rows=1000&start=0" "&type=programradio&view=title", "syntolkat": "https://urplay.se/api/bff/v1/search?response_type=category" "&singles_and_series=true" "&rows=1000&start=0" "&view=title" "&with_audio_description=true", "teckensprak": "https://urplay.se/api/bff/v1/search?response_type=category" "&language=sgn-SWE" "&rows=1000&start=0" "&view=title" "&singles_and_series=true&view=title" } self.__timezone = pytz.timezone("Europe/Amsterdam") self.__episode_text = LanguageHelper.get_localized_string( LanguageHelper.EpisodeId) #=========================================================================================== # Test cases: # Anaconda Auf Deutch : RTMP, Subtitles # ====================================== Actual channel setup STOPS here =================== return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) self.liveUrl = None # : the live url if present self.jsonParsing = False if self.channelCode == "omroepzeeland": self.noImage = "omroepzeelandimage.png" self.mainListUri = "https://www.omroepzeeland.nl/tvgemist" self.baseUrl = "https://www.omroepzeeland.nl" self.liveUrl = "https://zeeland.rpoapp.nl/v01/livestreams/AndroidTablet.json" elif self.channelCode == "rtvutrecht": self.noImage = "rtvutrechtimage.png" self.mainListUri = "https://www.rtvutrecht.nl/gemist/rtvutrecht/" self.baseUrl = "https://www.rtvutrecht.nl" # Uses NPO stream with smshield cookie self.liveUrl = "https://utrecht.rpoapp.nl/v02/livestreams/AndroidTablet.json" else: raise NotImplementedError("Channelcode '%s' not implemented" % (self.channelCode, )) # JSON Based Main lists self._add_data_parser( "https://www.omroepzeeland.nl/tvgemist", preprocessor=self.add_live_channel_and_extract_data, match_type=ParserData.MatchExact, parser=[], creator=self.create_json_episode_item, json=True) # HTML Based Main lists html_episode_regex = r'<option\s+value="(?<url>/gemist/uitzending/[^"]+)">(?<title>[^<]*)' html_episode_regex = Regexer.from_expresso(html_episode_regex) self._add_data_parser( "https://www.rtvutrecht.nl/gemist/rtvutrecht/", preprocessor=self.add_live_channel_and_extract_data, match_type=ParserData.MatchExact, parser=html_episode_regex, creator=self.create_episode_item, json=False) video_item_regex = r'<img src="(?<thumburl>[^"]+)"[^>]+alt="(?<title>[^"]+)"[^>]*/>\W*' \ r'</a>\W*<figcaption(?:[^>]+>\W*){2}<time[^>]+datetime="' \ r'(?<date>[^"]+)[^>]*>(?:[^>]+>\W*){3}<a[^>]+href="(?<url>[^"]+)"' \ r'[^>]*>\W*(?:[^>]+>\W*){3}<a[^>]+>(?<description>.+?)</a>' video_item_regex = Regexer.from_expresso(video_item_regex) self._add_data_parser( "https://www.rtvutrecht.nl/", name="HTML Video parsers and updater for JWPlayer embedded JSON", parser=video_item_regex, creator=self.create_video_item, updater=self.update_video_item_json_player) # Json based stuff self._add_data_parser("https://www.omroepzeeland.nl/RadioTv/Results?", name="Video item parser", json=True, parser=[ "searchResults", ], creator=self.create_json_video_item) self._add_data_parser( "https://www.omroepzeeland.nl/", name="Updater for Javascript file based stream data", updater=self.update_video_item_javascript) # Live Stuff self._add_data_parser(self.liveUrl, name="Live Stream Creator", creator=self.create_live_item, parser=[], json=True) self._add_data_parser(".+/live/.+", match_type=ParserData.MatchRegex, updater=self.update_live_item) #=============================================================================================================== # non standard items #=============================================================================================================== # Test cases: # Omroep Zeeland: M3u8 playist # ====================================== Actual channel setup STOPS here ======================================= return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ==== Actual channel setup STARTS here and should be overwritten from derived classes ===== self.noImage = "rtbfimage.png" # setup the urls self.mainListUri = "https://www.rtbf.be/auvio/emissions" self.baseUrl = "https://www.rtbf.be" # setup the main parsing data episode_regex = r'<article[^>]+data-id="(?<id>(?<url>\d+))"[^>]*>\W+<figure[^>]+>\W+' \ r'<figcaption[^>]+>(?<title>[^{][^<]+)</figcaption>\W*<div[^>]*>\W*' \ r'<img[^>]*(?<thumburl>http[^"]+) \d+w"' episode_regex = Regexer.from_expresso(episode_regex) self._add_data_parser(self.mainListUri, match_type=ParserData.MatchExact, preprocessor=self.add_category_and_live_items, parser=episode_regex, creator=self.create_episode_item) self._add_data_parser("http://www.rtbf.be/news/api/menu?site=media", json=True, match_type=ParserData.MatchExact, parser=["item", 3, "item"], creator=self.create_category) live_regex = r'<img[^>]*(?<thumburl>http[^"]+) \d+w"[^>]*>[\w\W]{0,1000}Maintenant' \ r'</span> (?:sur )?(?<channel>[^>]+)</div>\W*<h3[^>]*>\W*<a[^>]+href="' \ r'(?<url>[^"]+=(?<liveId>\d+))"[^>]+title="(?<title>[^"]+)' live_regex = Regexer.from_expresso(live_regex) self._add_data_parser("https://www.rtbf.be/auvio/direct/", parser=live_regex, creator=self.create_video_item) self._add_data_parser("https://www.rtbf.be/auvio/embed/direct", updater=self.update_live_item) video_regex = r'<img[^>]*alt="(?<title>[^"]+)"[^>]*(?<thumburl>http[^"]+) \d+w"[^>]*>' \ r'[\w\W]{0,1000}?<h4[^>]+>\W+<a[^>]+href="(?<url>[^<"]+=(?<videoId>\d+))"' \ r'[^>]*>[^<]*</a>\W*</h4>\W*(?:<h5[^>]+>(?<description>[^<]*)</h5>|<div)' \ r'[\w\W]{0,1000}?<time[^>]+datetime="(?<date>[^"]+)"' video_regex = Regexer.from_expresso(video_regex) self._add_data_parser("*", parser=video_regex, creator=self.create_video_item, updater=self.update_video_item) self.pageNavigationRegexIndex = 1 page_regex = r'<li class="(?:|[^a][^"]+)">\W+<a class="rtbf-pagination__link" ' \ r'href="([^"]+&p=)(\d+)"' self._add_data_parser("*", parser=page_regex, creator=self.create_page_item) self.swfUrl = "http://www.static.rtbf.be/rtbf/embed/js/vendor/jwplayer/jwplayer.flash.swf" # ========================================================================================== # Test cases: # 5@7 # ====================================== Actual channel setup STOPS here =================== return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ==== Actual channel setup STARTS here and should be overwritten from derived classes ==== self.noImage = "urplayimage.png" # setup the urls self.mainListUri = "#mainlist_merge" self.baseUrl = "https://urplay.se" self.swfUrl = "https://urplay.se/assets/jwplayer-6.12-17973009ab259c1dea1258b04bde6e53.swf" # Match the "series" API -> shows TV Shows self._add_data_parser( self.mainListUri, json=True, name="Show parser with categories", match_type=ParserData.MatchExact, preprocessor=self.merge_add_categories_and_search, parser=["results"], creator=self.create_episode_json_item) # Match Videos (programs) self._add_data_parser( "https://urplay.se/api/bff/v1/search?product_type=program", name="Most viewed", json=True, parser=["results"], creator=self.create_video_item_json_with_show_title) self._add_data_parser("*", json=True, name="Json based video parser", parser=["accessibleEpisodes"], creator=self.create_video_item_json) self._add_data_parser("*", updater=self.update_video_item) # Categories cat_reg = r'<a[^>]+href="(?<url>/blad[^"]+/(?<slug>[^"]+))"[^>]*>' \ r'(?:<svg[\w\W]{0,2000}?</svg>)?(?<title>[^<]+)<' cat_reg = Regexer.from_expresso(cat_reg) self._add_data_parser("https://urplay.se/", name="Category parser", match_type=ParserData.MatchExact, parser=cat_reg, creator=self.create_category_item) self._add_data_parsers([ "https://urplay.se/api/bff/v1/search?play_category", "https://urplay.se/api/bff/v1/search?main_genre", "https://urplay.se/api/bff/v1/search?response_type=category", "https://urplay.se/api/bff/v1/search?type=programradio", "https://urplay.se/api/bff/v1/search?age=", "https://urplay.se/api/bff/v1/search?response_type=limited" ], name="Category content", json=True, preprocessor=self.merge_category_items, parser=["results"], creator=self.create_json_item) # Searching self._add_data_parser("https://urplay.se/search/json", json=True, parser=["programs"], creator=self.create_search_result_program) self._add_data_parser("https://urplay.se/search/json", json=True, parser=["series"], creator=self.create_search_result_serie) self.mediaUrlRegex = r"urPlayer.init\(([^<]+)\);" #=========================================================================================== # non standard items self.__videoItemFound = False # There is either a slug lookup or an url lookup self.__cateogory_slugs = {} self.__cateogory_urls = { "alla-program": "https://urplay.se/api/bff/v1/search?" "response_type=limited&" "product_type=series&" "rows={}&start={}&view=title", "barn": "https://urplay.se/api/bff/v1/search?" "age=children&" "platform=urplay&" "rows={}&" "singles_and_series=true&" "start={}" "&view=title", "dokumentarfilmer": "https://urplay.se/api/bff/v1/search?" "main_genre[]=dokument%C3%A4rfilm&main_genre[]=dokument%C3%A4rserie&" # "platform=urplay&" "singles_and_series=true&view=title&" "rows={}&" "singles_and_series=true&" "start={}" "&view=title", "drama": "https://urplay.se/api/bff/v1/search?" "main_genre[]=drama&main_genre[]=kortfilm&main_genre[]=fiktiva%20ber%C3%A4ttelser&" "platform=urplay&" "rows={}&" "singles_and_series=true&" "start={}&" "view=title", "forelasningar": "https://urplay.se/api/bff/v1/search?" "main_genre[]=f%C3%B6rel%C3%A4sning&main_genre[]=panelsamtal&" "platform=urplay&" "rows={}&" "singles_and_series=true&" "start={}&" "view=title", "halsa-och-relationer": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&" "main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=kropp%20%26%20sinne&" "singles_and_series=true&" "start={}&" "view=title", "kultur-och-historia": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=kultur%20%26%20historia&" "singles_and_series=true&" "start={}&" "view=title", "natur-och-resor": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=natur%20%26%20resor&" "singles_and_series=true&" "start={}&" "view=title", "radio": "https://urplay.se/api/bff/v1/search?" "type=programradio&" "platform=urplay&" "rows={}&" "singles_and_series=true&" "start={}&" "view=title", "samhalle": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=samh%C3%A4lle&" "singles_and_series=true&" "start={}&" "view=title", "sprak": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=spr%C3%A5k&" "singles_and_series=true&" "start={}&" "view=title", "syntolkat": "https://urplay.se/api/bff/v1/search?" "response_type=category&" "is_audio_described=true&" "platform=urplay&" "rows={}&" "singles_and_series=true&" "start={}&" "view=title", "teckensprak": "https://urplay.se/api/bff/v1/search?" "response_type=category&" "language=sgn-SWE&" "platform=urplay&" "rows={}&" "singles_and_series=true&" "start={}&" "view=title", "utbildning-och-media": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&" "main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=utbildning%20%26%20media&" "singles_and_series=true&" "start={}&" "view=title", "vetenskap": "https://urplay.se/api/bff/v1/search?" "main_genre_must_not[]=forelasning&main_genre_must_not[]=panelsamtal&" "platform=urplay&" "rows={}&" "sab_category=vetenskap%20%26%20teknik&" "singles_and_series=true&" "start={}&" "view=title" } self.__timezone = pytz.timezone("Europe/Amsterdam") self.__episode_text = LanguageHelper.get_localized_string( LanguageHelper.EpisodeId) #=========================================================================================== # Test cases: # Anaconda Auf Deutch : RTMP, Subtitles # ====================================== Actual channel setup STOPS here =================== return
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ============== Actual channel setup STARTS here and should be overwritten from derived classes =============== # The following data was taken from http://playapi.mtgx.tv/v3/channels self.channelIds = None self.mainListUri = None # The LV channels if self.channelCode == "tv3lv": self.noImage = "tv3lvimage.png" self.mainListUri = "https://tvplay.skaties.lv/seriali/" self.channelIds = ( 1482, # TV3 6400, # LNT 6401, # TV6 6402, # TV5 6403, # Kanals2 6404, # TVPlay 6405 # 3+ ) # EE channels elif self.channelCode == "tv3ee": self.mainListUri = "https://tvplay.tv3.ee/saated/tv3/" self.noImage = "tv3noimage.png" self.channelId = (1375, 6301, 6302) elif self.channelCode == "tv6ee": self.mainListUri = "https://tvplay.tv3.ee/saated/tv6/" self.noImage = "tv6seimage.png" self.channelId = (6300, ) # Lithuanian channels elif self.channelCode == "tv3lt": self.mainListUri = "https://tvplay.tv3.lt/pramogines-laidos/tv3/" self.noImage = "tv3ltimage.png" self.channelId = (3000, 6503) elif self.channelCode == "tv6lt": self.mainListUri = "https://tvplay.tv3.lt/pramogines-laidos/tv6/" self.noImage = "tv6ltimage.png" self.channelId = (6501, ) elif self.channelCode == "tv8lt": self.mainListUri = "https://tvplay.tv3.lt/pramogines-laidos/tv8/" self.noImage = "tv8seimage.png" self.channelId = (6502, ) else: raise ValueError("Unknown channelcode {0}".format( self.channelCode)) self.episodeItemRegex = r'<a[^>*]+href="(?<url>[^"]+)"[^>]*>\W+<img[^>]+data-srcset="[^"]*' \ r'(?<thumburl>http[^" ]+)[^"]+"[^>]+alt="(?<title>[^"]+)"' self.videoItemRegex = r'{0}[\w\W]{{0,1000}}?site-thumb-info[^>]+>(?<description>[^<]+)'. \ format(self.episodeItemRegex) self.folderItemRegex = r'<option value="(?<url>[^"]+)"\W*>(?<title>[^<]+)</option>' self.episodeItemRegex = Regexer.from_expresso(self.episodeItemRegex) self._add_data_parser(self.mainListUri, match_type=ParserData.MatchExact, preprocessor=self.add_search, parser=self.episodeItemRegex, creator=self.create_episode_item) self.videoItemRegex = Regexer.from_expresso(self.videoItemRegex) self._add_data_parser("*", preprocessor=self.remove_clips, parser=self.videoItemRegex, creator=self.create_video_item) self.folderItemRegex = Regexer.from_expresso(self.folderItemRegex) self._add_data_parser("*", parser=self.folderItemRegex, creator=self.create_folder_item) # Add an updater self._add_data_parser("*", updater=self.update_video_item) self.baseUrl = "{0}//{2}".format(*self.mainListUri.split("/", 3)) self.searchInfo = { "se": ["sok", "Sök"], "ee": ["otsi", "Otsi"], "dk": ["sog", "Søg"], "no": ["sok", "Søk"], "lt": ["paieska", "Paieška"], "lv": ["meklet", "Meklēt"] }
def __init__(self, channel_info): """ Initialisation of the class. All class variables should be instantiated here and this method should not be overridden by any derived classes. :param ChannelInfo channel_info: The channel info object to base this channel on. """ chn_class.Channel.__init__(self, channel_info) # ==== Actual channel setup STARTS here and should be overwritten from derived classes ==== self.noImage = "urplayimage.png" # setup the urls self.mainListUri = "https://urplay.se/api/bff/v1/search?product_type=series&rows=10000&start=0" self.baseUrl = "https://urplay.se" self.swfUrl = "https://urplay.se/assets/jwplayer-6.12-17973009ab259c1dea1258b04bde6e53.swf" # Match the "series" API -> shows TV Shows self._add_data_parser(self.mainListUri, json=True, name="Show parser with categories", match_type=ParserData.MatchExact, preprocessor=self.add_categories_and_search, parser=["results"], creator=self.create_json_episode_item) # Match Videos (programs) self._add_data_parser("https://urplay.se/api/bff/v1/search?product_type=program", name="Most viewed", json=True, parser=["results"], creator=self.create_json_video_item) item_regex = r'href="/(?<url>[^/]+/(?<id>\d+)[^"]+)"[^>]*>[^<]+</a>\W+<figure[^>]*>[\W\w]' \ r'{0,3000}?<h2[^>]*>(?<title>[^<]+)</h2>\W+<p[^>]+>[^>]*<span[^>]+>' \ r'(?<description>[^<]*).{2}<[^>]+>\s*<span[^>]+>(?<duration>\d{1,3})\smin[^>]+' \ r'>\s*<span[^>]*>(?<description2>[^<]+)' item_regex = Regexer.from_expresso(item_regex) single_video_regex = r'<meta \w+="name" content="(?:[^:]+: )?(?<title>[^"]+)' \ r'"[^>]*>\W*<meta \w+="description" content="(?<description>[^"]+)"' \ r'[^>]*>\W*<meta \w+="url" content="(?:[^"]+/(?<url>\w+/' \ r'(?<id>\d+)[^"]+))"[^>]*>\W*<meta \w+="thumbnailURL[^"]*" ' \ r'content="(?<thumbnail>[^"]+)"[^>]*>\W+<meta \w+="uploadDate" ' \ r'content="(?<date>[^"]+)"' single_video_regex = Regexer.from_expresso(single_video_regex) self._add_data_parser("*", parser=item_regex, preprocessor=self.get_video_section, creator=self.create_video_item) self._add_data_parser("*", parser=single_video_regex, preprocessor=self.get_video_section, creator=self.create_single_video_item, updater=self.update_video_item) # Folders (Seasons) season_regex = '<li[^>]+>[^>]+data-description="(?<description>[^"]+)"[^>]+' \ 'data-asset-id="(?<id>[^"]+)"[^>]+>[\n\r ]*(?<title>[^<]+?)[\n\r ]*<' season_regex = Regexer.from_expresso(season_regex) self._add_data_parser("*", name="Season Folders", parser=season_regex, creator=self.create_folder_item) # Categories cat_reg = r'<a[^>]+href="(?<url>/blad[^"]+/(?<slug>[^"]+))"[^>]*>(?<title>[^<]+)<' cat_reg = Regexer.from_expresso(cat_reg) self._add_data_parser("https://urplay.se/", name="Category parser", match_type=ParserData.MatchExact, parser=cat_reg, creator=self.create_category_item) self._add_data_parsers(["https://urplay.se/api/bff/v1/search?play_category", "https://urplay.se/api/bff/v1/search?response_type=category"], name="Category content", json=True, parser=["results"], creator=self.create_json_item) # Searching self._add_data_parser("https://urplay.se/search/json", json=True, parser=["programs"], creator=self.create_search_result_program) self._add_data_parser("https://urplay.se/search/json", json=True, parser=["series"], creator=self.create_search_result_serie) self.mediaUrlRegex = r"urPlayer.init\(([^<]+)\);" #=========================================================================================== # non standard items self.__videoItemFound = False self.__cateogory_slugs = { "dokumentarfilmer": "dokument%C3%A4rfilmer", "forelasningar": "f%C3%B6rel%C3%A4sningar", "kultur-och-historia": "kultur%20och%20historia", "reality-och-livsstil": "reality%20och%20livsstil", "samhalle": "samh%C3%A4lle" } self.__cateogory_urls = { "radio": "https://urplay.se/api/bff/v1/search?response_type=category" "&singles_and_series=true" "&rows=1000&start=0" "&type=programradio&view=title", "syntolkat": "https://urplay.se/api/bff/v1/search?response_type=category" "&singles_and_series=true" "&rows=1000&start=0" "&view=title" "&with_audio_description=true", "teckensprak": "https://urplay.se/api/bff/v1/search?response_type=category" "&language=sgn-SWE" "&rows=1000&start=0" "&view=title" "&singles_and_series=true&view=title" } #=========================================================================================== # Test cases: # Anaconda Auf Deutch : RTMP, Subtitles # ====================================== Actual channel setup STOPS here =================== return