def findvideos(item): logger.info() itemlist = [] data = httptools.downloadpage(item.url).data patron = 'href="([^"]+)".*?domain=.*?>([^<]+).*?gold">([^<]+)<' matches = re.compile(patron, re.DOTALL).findall(data) for scrapedurl, scrapedserver, scrapedidioma in matches: url = scrapedurl idioma = audio[scrapedidioma] server = scrapedserver.strip(' ') if server == 'streamin': server = 'streaminto' title = item.contentSerieName + ' ' + str( item.contentSeasonNumber) + 'x' + str( item.contentEpisodeNumber) + ' ' + idioma + ' (' + server + ')' new_item = item.clone( title=title, url=url, action="play", language=IDIOMAS[scrapedidioma], server=server, quality='default', fulltitle=item.ContentSeriename, ) # Requerido para FilterTools itemlist = filtertools.get_link(itemlist, new_item, list_language) import os for videoitem in itemlist: videoitem.infoLabels = item.infoLabels videoitem.thumbnail = os.path.join(config.get_runtime_path(), "resources", "media", "servers", "server_%s.png" % videoitem.server) # Requerido para AutoPlay autoplay.start(itemlist, item) return itemlist
def findvideos(item): logger.info() itemlist = [] data = httptools.downloadpage(item.url).data patron = 'href="([^"]+)".*?domain=.*?>([^<]+).*?gold">([^<]+)<' matches = re.compile(patron, re.DOTALL).findall(data) import time for scrapedurl, scrapedserver, scrapedidioma in matches: url = scrapedurl idioma = audio[scrapedidioma] server = scrapedserver.strip(' ') title = item.contentSerieName + ' ' + str( item.contentSeasonNumber) + 'x' + str( item.contentEpisodeNumber) + ' ' + idioma + ' (' + server + ')' new_item = item.clone( title=title, url=url, action="play", language=IDIOMAS[scrapedidioma], server=server, quality='default', fulltitle=item.ContentSeriename, ) # Requerido para FilterTools itemlist = filtertools.get_link(itemlist, new_item, list_language) for videoitem in itemlist: videoitem.infoLabels = item.infoLabels videoitem.thumbnail = "https://raw.githubusercontent.com/MiTvSpain/mitvspain/master/servers/server_%s.png" % videoitem.server # Requerido para AutoPlay autoplay.start(itemlist, item) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto try: tmdb.set_infoLabels(item, True) #TMDB actualizado except: pass #Bajamos los datos de la página data = '' try: data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) except: pass if not data: logger.error("ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log')) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? link_torrent = item.emergency_urls[0][0] #Guardamos la url del .Torrent link_magnet = item.emergency_urls[1][0] #Guardamos la url del .Magnet item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #data = unicode(data, "utf-8", errors="replace") patron_t = '<div class="enlace_descarga".*?<a href="(.*?\.torrent)"' patron_m = '<div class="enlace_descarga".*?<a href="(magnet:?.*?)"' if not item.armagedon: #Si es un proceso normal, seguimos link_torrent = scrapertools.find_single_match(data, patron_t) link_torrent = urlparse.urljoin(item.url, link_torrent) link_torrent = link_torrent.replace(" ", "%20") #sustituimos espacios por %20, por si acaso #logger.info("link Torrent: " + link_torrent) link_magnet = scrapertools.find_single_match(data, patron_m) link_magnet = urlparse.urljoin(item.url, link_magnet) #logger.info("link Magnet: " + link_magnet) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if (link_torrent or link_magnet) and item.videolibray_emergency_urls: item.emergency_urls = [] item.emergency_urls.append([link_torrent]) #Salvamos el enlace de .torrent item.emergency_urls.append([link_magnet]) #Salvamos el enlace de .magnet return item #... y nos vamos #Añadimos el tamaño para todos size = scrapertools.find_single_match(item.quality, '\s\[(\d+,?\d*?\s\w\s*[b|B]s*)\]') if size: item.title = re.sub('\s\[\d+,?\d*?\s\w\s*[b|B]s*\]', '', item.title) #Quitamos size de título, si lo traía item.title = '%s [%s]' % (item.title, size) #Agregamos size al final del título item.quality = re.sub('\s\[\d+,?\d*?\s\w\s*[b|B]s*\]', '', item.quality) #Quitamos size de calidad, si lo traía if not link_torrent and not link_magnet: #error item = generictools.web_intervenida(item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Llamamos al método para el pintado del error else: logger.error("ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron_t + " / " + patron_m + " / DATA: " + data) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log')) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? link_torrent = item.emergency_urls[0][0] #Guardamos la url del .Torrent link_magnet = item.emergency_urls[1][0] #Guardamos la url del .Magnet item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) if not size and not item.armagedon: size = generictools.get_torrent_size(link_torrent) #Buscamos el tamaño en el .torrent if size: item.quality = '%s [%s]' % (item.quality, size) #Agregamos size al final de calidad item.quality = item.quality.replace("GB", "G B").replace("MB", "M B").replace("Gb", "G B").replace("Mb", "M B") #Se evita la palabra reservada en Unify #Ahora pintamos el link del Torrent, si lo hay if link_torrent: # Hay Torrent ? #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() if item_local.quality: item_local.quality += " " item_local.quality += "[Torrent]" if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality item_local.url = link_torrent if item_local.url and item.emergency_urls and not item.armagedon: item_local.torrent_alt = item.emergency_urls[0][0] #Guardamos la url del .Torrent ALTERNATIVA item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Torrent #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append(item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting('filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link(itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len(itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb("next.png") #... pintamos todo con aviso itemlist.append(Item(channel=item.channel, url=host, title="[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador)) itemlist.extend(itemlist_t) #Pintar pantalla con todo si no hay filtrado #Ahora pintamos el link del Magnet, si lo hay itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if link_magnet: # Hay Magnet ? #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() if item_local.quality: item_local.quality += " " item_local.quality = item_local.quality.replace("[Torrent]", "") + "[Magnet]" if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality item_local.url = link_magnet item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título de Magnet item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title) #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title) #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append(item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting('filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link(itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len(itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb("next.png") #... pintamos todo con aviso itemlist.append(Item(channel=item.channel, url=host, title="[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador)) itemlist.extend(itemlist_t) #Pintar pantalla con todo si no hay filtrado #logger.debug("TORRENT: " + link_torrent + "MAGNET: " + link_magnet + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): logger.info() itemlist = [] inicio = time.time() # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout # Timeout para descargas if item.extra == 'search': timeout_search = timeout * 2 # Timeout un poco más largo para las búsquedas if timeout_search < 5: timeout_search = 5 # Timeout un poco más largo para las búsquedas # Descarga la página data = '' try: data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout_search).data) except: pass if not data: #Si la web está caída salimos sin dar error logger.error("ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos patron = '<div id="principal">.*?<\/nav><\/div><\/div>' data = scrapertools.find_single_match(data, patron) patron = '<li>\s*<div\s*class="[^"]+">\s*<a href="([^"]+)"\s*' #url patron += 'title="([^"]+)"\s*(?:alt="[^"]+")?\s*>\s*' #título patron += '<img (?:class="[^"]+")?\s*src="([^"]+)"\s*border="[^"]+"\s*' #thumb patron += 'title="([^"]+)".*?' #categoría, idioma patron += '<span class="[^"]+" style="[^"]+"\s*><i>(.*?)<\/i><\/span.*?' #calidad patron += '="dig1">(.*?)<.*?' #tamaño patron += '="dig2">(.*?)<\/span><\/div>' #tipo tamaño matches = re.compile(patron, re.DOTALL).findall(data) if not matches and not '<title>503 Backend fetch failed</title>' in data and not 'No se han encontrado resultados' in data: #error item = generictools.web_intervenida(item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_listado(item, itemlist) #Llamamos al método para el pintado del error return itemlist #Salimos logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log')) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) for scrapedurl, scrapedtitle, scrapedthumbnail, scrapedcategory, scrapedcalidad, scrapedsize, scrapedsizet in matches: item_local = item.clone() #Creamos copia de Item para trabajar title = re.sub('\r\n', '', scrapedtitle).decode('utf8').strip() title = title.replace(" torrent", "").replace(" Torrent", "").replace("Series y ", "") item_local.url = urlparse.urljoin(host, scrapedurl) item_local.thumbnail = urlparse.urljoin(host, scrapedthumbnail) if "---" in scrapedcalidad: #limpiamos calidades scrapedcalidad = '' if "microhd" in title.lower(): item_local.quality = "microHD" if not "/series-vose/" in item.url and not item_local.quality: item_local.quality = scrapedcalidad if scrapertools.find_single_match(item_local.quality, r'\d+\.\d+'): item_local.quality = '' if not item_local.quality and ("DVDRip" in title or "HDRip" in title or "BR-LINE" in title or "HDTS-SCREENER" in title or "BDRip" in title or "BR-Screener" in title or "DVDScreener" in title or "TS-Screener" in title): item_local.quality = scrapertools.find_single_match(title, r'\((.*?)\)') item_local.quality = item_local.quality.replace("Latino", "") if not scrapedsizet: scrapedsize = '' else: item_local.quality += ' [%s %s]' % (scrapedsize.replace(".", ","), scrapedsizet) item_local.language = [] #Verificamos el idioma por si encontramos algo if "latino" in scrapedcategory.lower() or "latino" in item.url or "latino" in title.lower(): item_local.language += ["LAT"] if "ingles" in scrapedcategory.lower() or "ingles" in item.url or "vose" in scrapedurl or "vose" in item.url: if "VOSE" in scrapedcategory.lower() or "sub" in title.lower() or "vose" in scrapedurl or "vose" in item.url: item_local.language += ["VOS"] else: item_local.language += ["VO"] if "dual" in scrapedcategory.lower() or "dual" in title.lower(): item_local.language[0:0] = ["DUAL"] if item_local.language == []: item_local.language = ['CAST'] #Por defecto #Limpiamos el título de la basura innecesaria title = title.replace("Dual", "").replace("dual", "").replace("Subtitulada", "").replace("subtitulada", "").replace("Subt", "").replace("subt", "").replace("Sub", "").replace("sub", "").replace("(Proper)", "").replace("(proper)", "").replace("Proper", "").replace("proper", "").replace("#", "").replace("(Latino)", "").replace("Latino", "") title = title.replace("- HDRip", "").replace("(HDRip)", "").replace("- Hdrip", "").replace("(microHD)", "").replace("(DVDRip)", "").replace("(HDRip)", "").replace("(BR-LINE)", "").replace("(HDTS-SCREENER)", "").replace("(BDRip)", "").replace("(BR-Screener)", "").replace("(DVDScreener)", "").replace("TS-Screener", "").replace(" TS", "").replace(" Ts", "").replace("temporada", "").replace("Temporada", "").replace("capitulo", "").replace("Capitulo", "") title = re.sub(r'(?:\d+)?x.?\s?\d+', '', title) title = re.sub(r'\??\s?\d*?\&.*', '', title).title().strip() item_local.from_title = title #Guardamos esta etiqueta para posible desambiguación de título if item_local.extra == "peliculas": #preparamos Item para películas if "/serie" in scrapedurl or "/serie" in item.url: continue if not "/serie" in scrapedurl and not "/serie" in item.url: item_local.contentType = "movie" item_local.contentTitle = title item_local.extra = "peliculas" if item_local.extra == "series": #preparamos Item para series if not "/serie" in scrapedurl and not "/serie" in item.url: continue if "/serie" in scrapedurl or "/serie" in item.url: item_local.contentType = "episode" item_local.extra = "series" epi_mult = scrapertools.find_single_match(item_local.url, r'cap.*?-\d+-al-(\d+)') item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'temporada-(\d+)') item_local.contentEpisodeNumber = scrapertools.find_single_match(item_local.url, r'cap.*?-(\d+)') if not item_local.contentSeason: item_local.contentSeason = scrapertools.find_single_match(item_local.url, r'-(\d+)[x|X]\d+') if not item_local.contentEpisodeNumber: item_local.contentEpisodeNumber = scrapertools.find_single_match(item_local.url, r'-\d+[x|X](\d+)') if not item_local.contentSeason or item_local.contentSeason < 1: item_local.contentSeason = 0 if item_local.contentEpisodeNumber < 1: item_local.contentEpisodeNumber = 1 item_local.contentSerieName = title if epi_mult: title = "%sx%s al %s -" % (item_local.contentSeason, str(item_local.contentEpisodeNumber).zfill(2), str(epi_mult).zfill(2)) #Creamos un título con el rango de episodios else: title = '%sx%s ' % (str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2)) item_local.action = "findvideos" item_local.title = title.strip() item_local.infoLabels['year'] = "-" #Pasamos a TMDB cada Item, para evitar el efecto memoria de tmdb #if item.category: #Si este campo no existe es que viene de la primera pasada de una búsqueda global, pasamos # tmdb.set_infoLabels(item_local, True) #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting('filter_languages', channel) > 0 and item.filter_lang: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla #if not item.category: #Si este campo no existe es que viene de la primera pasada de una búsqueda global # return itemlist #Retornamos sin pasar por la fase de maquillaje para ahorra tiempo #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, True) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Extrae el paginador patron = '<div class="paginacion">.*?<span class="pagina pag_actual".*?' patron += "<a href='([^']+)'.*?" #url siguiente página patron += 'class="pagina">(\d+)<' #próxima página matches = scrapertools.find_single_match(data, patron) patron = 'class="pagina pag_sig">Siguiente.*?' patron += "<a href='.*?\/page\/(\d+)\/" #total de páginas last_page = scrapertools.find_single_match(data, patron) if not last_page: patron = '<div class="paginacion">.*?' patron += 'class="pagina">(\d+)<\/a><\/div><\/nav><\/div><\/div>' #total de páginas last_page = scrapertools.find_single_match(data, patron) if matches: scrapedurl = urlparse.urljoin(item.url, matches[0]) if last_page: title = '[COLOR gold]Página siguiente >>[/COLOR] %s de %s' % (int(matches[1]) - 1, last_page) else: title = '[COLOR gold]Página siguiente >>[/COLOR] %s' % (int(matches[1]) - 1) itemlist.append(Item(channel=item.channel, action="listado", title=title, url=scrapedurl, extra=item.extra, filter_lang=item.filter_lang)) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados matches = [] data = '' response = {'data': data, 'sucess': False, 'code': 0} response = type('HTTPResponse', (), response) torrent_params = { 'url': item.url, 'torrents_path': None, 'local_torr': item.torrents_path, 'lookup': False, 'force': True, 'data_torrent': True, 'subtitles': True, 'file_list': True } #logger.debug(item) #Bajamos los datos de la página patron = '<a\s*class="torrent_download[^"]*"\s*href="([^"]+)"' if not item.matches: data, response, item, itemlist = generictools.downloadpage( item.url, timeout=timeout, canonical=canonical, headers=item.headers, s2=False, patron=patron, item=item, itemlist=itemlist) # Descargamos la página #Verificamos si se ha cargado una página, y si además tiene la estructura correcta if (not data and not item.matches) or response.code == 999: if item.emergency_urls and not item.videolibray_emergency_urls: # Hay urls de emergencia? if len(item.emergency_urls) > 1: matches = item.emergency_urls[ 1] # Restauramos matches de vídeos elif len(item.emergency_urls) == 1 and item.emergency_urls[0]: matches = item.emergency_urls[ 0] # Restauramos matches de vídeos - OLD FORMAT item.armagedon = True # Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: # Si es llamado desde creación de Videoteca... return item # Devolvemos el Item de la llamada else: return itemlist # si no hay más datos, algo no funciona, pintamos lo que tenemos if not item.armagedon: if not item.matches: matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) if not matches: # error return itemlist # Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: item.emergency_urls = [] # Iniciamos emergency_urls item.emergency_urls.append( []) # Reservamos el espacio para los .torrents locales matches_list = [] # Convertimos matches-tuple a matches-list for tupla in matches: if isinstance(tupla, tuple): matches_list.append(list(tupla)) if matches_list: item.emergency_urls.append( matches_list) # Salvamnos matches de los vídeos... else: item.emergency_urls.append(matches) # Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB if not item.videolibray_emergency_urls: item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) # Ahora tratamos los enlaces .torrent con las diferentes calidades for x, (scrapedurl) in enumerate(matches): scrapedpassword = '' #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = generictools.convert_url_base64( scrapedurl, host_torrent) if item.videolibray_emergency_urls and item_local.url != scrapedurl: item.emergency_urls[1][x][0] = item_local.url # Buscamos el enlace definitivo, si es necesario if not item_local.url.startswith( 'magnet') and not item_local.url.endswith('.torrent'): patron = '<a\s*id="link"[^>]*href="([^"]+)"' data, response, item, itemlist = generictools.downloadpage( item_local.url, timeout=timeout, canonical=canonical, s2=False, patron=patron, item=item, itemlist=itemlist) item_local.url = scrapertools.find_single_match(data, patron) if not item_local.url: continue # Restauramos urls de emergencia si es necesario local_torr = '' if item.emergency_urls and not item.videolibray_emergency_urls: try: # Guardamos la url ALTERNATIVA if item.emergency_urls[0][0].startswith( 'http') or item.emergency_urls[0][0].startswith('//'): item_local.torrent_alt = generictools.convert_url_base64( item.emergency_urls[0][0], host_torrent) else: item_local.torrent_alt = generictools.convert_url_base64( item.emergency_urls[0][0]) except: item_local.torrent_alt = '' item.emergency_urls[0] = [] from core import filetools if item.contentType == 'movie': FOLDER = config.get_setting("folder_movies") else: FOLDER = config.get_setting("folder_tvshows") if item.armagedon and item_local.torrent_alt: item_local.url = item_local.torrent_alt # Restauramos la url if not item.torrent_alt.startswith('http'): local_torr = filetools.join(config.get_videolibrary_path(), FOLDER, item_local.url) if len(item.emergency_urls[0]) > 1: del item.emergency_urls[0][0] #Buscamos tamaño en el archivo .torrent size = '' if item_local.torrent_info: size = item_local.torrent_info if not size and not item.videolibray_emergency_urls and not item_local.url.startswith( 'magnet:'): if not item.armagedon: torrent_params['url'] = item_local.url torrent_params[ 'local_torr'] = local_torr or item_local.torrents_path torrent_params = generictools.get_torrent_size( item_local.url, torrent_params=torrent_params, item=item_local) size = torrent_params['size'] if torrent_params['torrents_path']: item_local.torrents_path = torrent_params['torrents_path'] if 'ERROR' in size and item.emergency_urls and not item.videolibray_emergency_urls: item_local.armagedon = True try: # Restauramos la url if item.emergency_urls[0][0].startswith( 'http' ) or item.emergency_urls[0][0].startswith('//'): item_local.url = generictools.convert_url_base64( item.emergency_urls[0][0], host_torrent) else: item_local.url = generictools.convert_url_base64( item.emergency_urls[0][0]) if not item.url.startswith('http'): local_torr = filetools.join( config.get_videolibrary_path(), FOLDER, item_local.url) except: item_local.torrent_alt = '' item.emergency_urls[0] = [] torrent_params['url'] = item_local.url torrent_params['local_torr'] = local_torr torrent_params = generictools.get_torrent_size( item_local.url, torrent_params=torrent_params, item=item_local) size = torrent_params['size'] if torrent_params['torrents_path']: item_local.torrents_path = torrent_params[ 'torrents_path'] if size: size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',') item_local.torrent_info = '%s, ' % size #Agregamos size if item_local.url.startswith( 'magnet:') and not 'Magnet' in item_local.torrent_info: item_local.torrent_info += ' Magnet' if item_local.torrent_info: item_local.torrent_info = item_local.torrent_info.strip().strip( ',') if item.videolibray_emergency_urls: item.torrent_info = item_local.torrent_info if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info # Guadamos la password del RAR password = scrapedpassword # Si tiene contraseña, la guardamos y la pintamos if password or item.password: if not item.password: item.password = password item_local.password = item.password itemlist.append( item.clone( action="", title="[COLOR magenta][B] Contraseña: [/B][/COLOR]'" + item_local.password + "'", folder=False)) # Guardamos urls de emergencia si se viene desde un Lookup de creación de Videoteca if item.videolibray_emergency_urls: item.emergency_urls[0].append( item_local.url) #guardamos la url y nos vamos continue if item_local.armagedon: item_local.quality = '[COLOR hotpink][E][/COLOR] [COLOR limegreen]%s[/COLOR]' % item_local.quality #Ahora pintamos el link del Torrent item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][Torrent][/COLOR] ' \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) #Preparamos título y calidad, quitando etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace("[]", "")\ .replace("()", "").replace("(/)", "").replace("[/]", "")\ .replace("|", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace("[]", "")\ .replace("()", "").replace("(/)", "").replace("[/]", "")\ .replace("|", "").strip() if not item_local.torrent_info or 'Magnet' in item_local.torrent_info: item_local.alive = "??" #Calidad del link sin verificar elif 'ERROR' in item_local.torrent_info and 'Pincha' in item_local.torrent_info: item_local.alive = "ok" #link en error, CF challenge, Chrome disponible elif 'ERROR' in item_local.torrent_info and 'Introduce' in item_local.torrent_info: item_local.alive = "??" #link en error, CF challenge, ruta de descarga no disponible item_local.channel = 'setting' item_local.action = 'setting_torrent' item_local.unify = False item_local.folder = False item_local.item_org = item.tourl() elif 'ERROR' in item_local.torrent_info: item_local.alive = "no" #Calidad del link en error, CF challenge? else: item_local.alive = "ok" #Calidad del link verificada if item_local.channel != 'setting': item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: return item #... nos vamos if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) if len(itemlist_t) == 0: if len(itemlist) == 0 or (len(itemlist) > 0 and itemlist[-1].server != 'torrent'): return [] itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): logger.info() itemlist = [] item.category = categoria #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial last_title = 99999 # Última línea inicial cnt_matches = 0 # Contador de líneas insertadas en Itemlist if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos if item.cnt_matches: cnt_matches = int( item.cnt_matches) # Si viene de una pasada anterior, lo usamos item.cnt_matches = 0 del item.cnt_matches # ... y lo borramos cnt_tot = 40 # Poner el num. máximo de items por página cnt_pct = 0.625 #% de la página a llenar cnt_title = 0 # Contador de líneas insertadas en Itemlist inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 10 # Después de este tiempo pintamos (segundos) timeout_search = timeout # Timeout para descargas if item.extra == 'search': timeout_search = timeout * 2 # Timeout un poco más largo para las búsquedas if timeout_search < 5: timeout_search = 5 # Timeout un poco más largo para las búsquedas item.tmdb_stat = True # Este canal no es ambiguo en los títulos #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' next_page_url = item.url #Máximo num. de líneas permitidas por TMDB. Máx de 10 segundos por Itemlist para no degradar el rendimiento while cnt_title < cnt_tot * cnt_pct and cnt_matches + 1 < last_title and fin > time.time( ): # Descarga la página data = '' try: data = httptools.downloadpage(next_page_url, timeout=timeout_search).data data = unicode(data, "utf-8", errors="replace").encode("utf-8") pos = data.find('[') if pos > 0: data = data[pos:] except: pass if not data: #Si la web está caída salimos sin dar error logger.error( "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos matches = jsontools.load(data) #cargamos lo datos como dict. if not matches and data[1] != ']': #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_episodios( item, itemlist) #Llamamos al método para el pintado del error return itemlist #Salimos logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log' )) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos last_title = len(matches) #Tamaño de total matches matches = matches[cnt_matches:] #avanzamos hasta la página actual #logger.debug(matches) #logger.debug(data) if last_page == 99999: #Si es el valor inicial, cargamos el num. de items last_page = int((last_title / (cnt_tot * cnt_pct))) curr_page = 1 #Empezamos el procesado de matches for titulo in matches: cnt_title += 1 #Sumamos 1 a los títulos tratados if cnt_title > cnt_tot * cnt_pct: cnt_title += last_title break cnt_matches += 1 #Sumamos 1 a total títulos tratados title = titulo.get("nom", "") #nombre del título title = title.replace("á", "a").replace("é", "e").replace( "í", "i").replace("ó", "o").replace("ú", "u").replace( "ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace( "ã", "a").replace("&etilde;", "e").replace( "ĩ", "i").replace("õ", "o").replace( "ũ", "u").replace("ñ", "ñ").replace("’", "'") item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.post_num: del item_local.post_num if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color if titulo.get("posterurl", ""): item_local.thumbnail = "http://image.tmdb.org/t/p/w342%s" % titulo.get( "posterurl", "") #thumb if titulo.get("backurl", ""): item_local.fanart = "http://image.tmdb.org/t/p/w1280%s" % titulo.get( "backurl", "") #Fanart url = titulo.get("magnets", {}) #magnet de diversas calidades year = titulo.get("year", "") #año if titulo.get("id", ""): item_local.infoLabels["tmdb_id"] = titulo.get("id", "") #TMDB id title_subs = [] #creamos una lista para guardar info importante item_local.language = [] #iniciamos Lenguaje item_local.quality = '' #inicialmos la calidad item_local.context = "['buscar_trailer']" item_local.contentType = "movie" #por defecto, son películas item_local.action = "findvideos" #Analizamos los formatos de series if item_local.extra == 'series': item_local.contentType = "tvshow" item_local.action = "episodios" item_local.season_colapse = True #Muestra las series agrupadas por temporadas item_local.url = "%s?id=%s" % (api_temp, titulo.get( "id", "")) #Salvamos la url special para series #Revisamos para peliculas todos los magnets, extrayendo dirección y calidad if item_local.contentType == "movie": item_local.url = [] #iniciamos dict. de magnets for etiqueta, magnet in titulo.get("magnets", {}).iteritems(): if magnet.get("magnet"): #buscamos los magnets activos url = magnet.get("magnet") #salvamos el magnet quality = magnet.get( "quality", "") #salvamos la calidad del magnet item_local.url += [ (url, quality) ] #guardamos todo como url para findvideos item_local.quality += "%s, " % quality.strip( ) #agregamos a la calidad del título item_local.quality = re.sub(r', $', '', item_local.quality) if not item_local.url: #si no hay magnets, no seguimos continue if item_local.language == []: item_local.language = ['CAST'] #Detectamos info interesante a guardar para después de TMDB if scrapertools.find_single_match(title, '[m|M].*?serie'): title = re.sub(r'[m|M]iniserie', '', title) title_subs += ["Miniserie"] if scrapertools.find_single_match(title, '[s|S]aga'): title = re.sub(r'[s|S]aga', '', title) title_subs += ["Saga"] if scrapertools.find_single_match(title, '[c|C]olecc'): title = re.sub(r'[c|C]olecc...', '', title) title_subs += ["Colección"] if "duolog" in title.lower(): title_subs += ["[Saga]"] title = title.replace(" Duologia", "").replace( " duologia", "").replace(" Duolog", "").replace(" duolog", "") if "trilog" in title.lower(): title_subs += ["[Saga]"] title = title.replace(" Trilogia", "").replace( " trilogia", "").replace(" Trilog", "").replace(" trilog", "") if "extendida" in title.lower() or "v.e." in title.lower( ) or "v e " in title.lower(): title_subs += ["[V. Extendida]"] title = title.replace("Version Extendida", "").replace( "(Version Extendida)", "").replace("V. Extendida", "").replace("VExtendida", "").replace( "V Extendida", "").replace("V.Extendida", "").replace( "V Extendida", "").replace("V.E.", "").replace( "V E ", "").replace("V:Extendida", "") #Analizamos el año. Si no está claro ponemos '-' try: yeat_int = int(year) if yeat_int >= 1950 and yeat_int <= 2040: item_local.infoLabels["year"] = yeat_int else: item_local.infoLabels["year"] = '-' except: item_local.infoLabels["year"] = '-' #Empezamos a limpiar el título en varias pasadas title = re.sub(r'[s|S]erie', '', title) title = re.sub(r'- $', '', title) #Limpiamos el título de la basura innecesaria title = re.sub( r'TV|Online|Spanish|Torrent|en Espa\xc3\xb1ol|Español|Latino|Subtitulado|Blurayrip|Bluray rip|\[.*?\]|R2 Pal|\xe3\x80\x90 Descargar Torrent \xe3\x80\x91|Completa|Temporada|Descargar|Torren', '', title, flags=re.IGNORECASE) #Terminamos de limpiar el título title = re.sub(r'\??\s?\d*?\&.*', '', title) title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').strip().lower().title() item_local.from_title = title.strip().lower().title( ) #Guardamos esta etiqueta para posible desambiguación de título #Salvamos el título según el tipo de contenido if item_local.contentType == "movie": item_local.contentTitle = title.strip().lower().title() else: item_local.contentSerieName = title.strip().lower().title() item_local.title = title.strip().lower().title() #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla #logger.debug(item_local) #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if cnt_title >= cnt_tot * cnt_pct: title = '%s' % curr_page if cnt_matches + 1 >= last_title: #Si hemos pintado ya todo lo de esta página... cnt_matches = 0 #... la próxima pasada leeremos otra página next_page_url = re.sub( r'page=(\d+)', r'page=' + str(int(re.search('\d+', next_page_url).group()) + 1), next_page_url) itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page + 1), cnt_matches=str(cnt_matches))) return itemlist
def listado(item): logger.info() itemlist = [] title_subs = [] item.category = categoria thumb_pelis = get_thumb("channels_movie.png") thumb_series = get_thumb("channels_tvshow.png") #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial last_page_print = 1 # Última página inicial, para píe de página page_factor = 1.0 # Factor de conversión de pag. web a pag. Alfa if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos if item.page_factor: page_factor = float( item.page_factor) # Si viene de una pasada anterior, lo usamos del item.page_factor # ... y lo borramos if item.last_page_print: last_page_print = item.last_page_print # Si viene de una pasada anterior, lo usamos del item.last_page_print # ... y lo borramos cnt_tot = 30 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist if item.cnt_tot_match: cnt_tot_match = float( item.cnt_tot_match ) # restauramos el contador TOTAL de líneas procesadas de matches del item.cnt_tot_match else: cnt_tot_match = 0.0 # Contador TOTAL de líneas procesadas de matches inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout * 2 # Timeout para descargas #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos matches = [] post = None forced_proxy_opt = None referer = item.url if item.post: # Rescatamos el Post, si lo hay post = item.post forced_proxy_opt = None if item.referer: referer = item.referer patron_canonical = 'rel="?canonical"?\s*href="?([^"|>]+)["|>|\s*]' next_page_url = item.url #Máximo num. de líneas permitidas por TMDB. Máx de 5 segundos por Itemlist para no degradar el rendimiento while (cnt_title < cnt_tot and curr_page <= last_page and fin > time.time()) or item.matches: # Descarga la página data = '' cnt_match = 0 # Contador de líneas procesadas de matches if not item.matches: # si no viene de una pasada anterior, descargamos data, response, item, itemlist = generictools.downloadpage( next_page_url, timeout=timeout_search, post=post, s2=False, canonical=canonical, forced_proxy_opt=forced_proxy_opt, referer=referer, item=item, itemlist=itemlist) # Descargamos la página) # Verificamos si ha cambiado el Host if response.host: next_page_url = response.url_new if scrapertools.find_single_match(data, patron_canonical): next_page_url = scrapertools.find_single_match( data, patron_canonical) if not 'page/' in next_page_url: if curr_page == 1: next_page_url += 'page/1/' else: next_page_url += 'page/%s/' % curr_page referer = next_page_url curr_page += 1 #Apunto ya a la página siguiente if not data: #Si la web está caída salimos sin dar error if len(itemlist) > 1: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist # Si no hay nada más, salimos directamente patron = '<div id="principal">.*?<\/nav><\/div><\/div>' data = scrapertools.find_single_match(data, patron) patron = '<li>\s*<div\s*class="[^"]+"\s*>\s*<a\s*href="([^"]+)"\s*' patron += 'title="([^"]+)"\s*(?:alt="[^"]+")?\s*>\s*<img\s*(?:class="[^"]+")?' patron += '\s*src="([^"]+)".*?border="[^"]+"\s*title="([^"]+)".*?<span\s*class="[^"]+"' patron += '\s*id="[^"]+"\s*>\s*<i>\s*<img\s*src="[^"]+"\s*data-src="[^"]+\/(\w+).png"' patron += '.*?<span\s*class="[^"]+"\s*style="[^"]+"\s*>\s*<i>(.*?)?<\/i>' patron += '(?:<\/span.*?="dig1"\s*>(.*?)?)?(?:<.*?="dig2">(.*?)?)?<\/span>\s*<\/div>' if not item.matches: # De pasada anterior o desde Novedades? matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches del item.matches if not matches and len( itemlist) > 0: # Página vacía pero hay algo que pintar last_page = 0 break if not matches and not '<title>503 Backend fetch failed</title>' in data and not 'No se han encontrado resultados' in data: logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. ' + 'Reportar el error con el log')) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Buscamos la próxima página next_page_url = re.sub(r'page\/(\d+)', 'page/%s' % str(curr_page), next_page_url) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page) + ' / page_factor: ' + str(page_factor)) #Buscamos la última página if last_page == 99999: # Si es el valor inicial, buscamos patron_last = '(?i)siguiente[^<]*<\/a>\s*<a\s*href="[^"]+\/(\d+)\/[^"]*"' if not scrapertools.find_single_match(data, patron_last): patron_last = 'class="pagina">(\d+)<\/a>\s*<\/div>' try: last_page = int( scrapertools.find_single_match(data, patron_last)) page_factor = float(len(matches)) / float(cnt_tot) except: # Si no lo encuentra, lo ponemos a 999 last_page = 999 #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page) + ' / page_factor: ' + str(page_factor)) for scrapedurl, scrapedtitle, scrapedthumbnail, scrapedcategory, scrapedlang, \ scrapedcalidad, scrapedsize, scrapedsizet in matches: cnt_match += 1 item_local = item.clone() # Creamos copia de Item para trabajar title = scrapedtitle.replace(" torrent", "").replace( " Torrent", "").replace("Series y ", "") item_local.url = urlparse.urljoin(host, scrapedurl) item_local.thumbnail = urlparse.urljoin(host, scrapedthumbnail) if "---" in scrapedcalidad: # limpiamos calidades scrapedcalidad = '' if "microhd" in title.lower(): item_local.quality = "microHD" if not "/series-vose/" in item.url and not item_local.quality: item_local.quality = scrapedcalidad if scrapertools.find_single_match(item_local.quality, r'\d+\.\d+'): item_local.quality = '' if not item_local.quality and ("DVDRip" in title or "HDRip" in title \ or "BR-LINE" in title or "HDTS-SCREENER" in title \ or "BDRip" in title or "BR-Screener" in title \ or "DVDScreener" in title or "TS-Screener" in title): item_local.quality = scrapertools.find_single_match( title, r'\((.*?)\)') item_local.quality = item_local.quality.replace("Latino", "") if not scrapedsizet or "---" in scrapedsizet: scrapedsize = '' else: item_local.quality += ' [%s %s]' % (scrapedsize.replace( ".", ","), scrapedsizet) item_local.language = [ ] # Verificamos el idioma por si encontramos algo if "latino" in scrapedlang.lower( ) or "latino" in item.url or "latino" in title.lower(): item_local.language += ["LAT"] if scrapedlang.lower() in ['vos', 'vose'] or "vose" in item.url or "vos" in item.url \ or "vose" in scrapedurl or "vos" in scrapedurl or "subt" in title.lower(): item_local.language += ["VOSE"] elif scrapedlang.lower() in ['ingles', 'inglés', 'english', 'original', 'vo'] or "ingles" in item.url \ or "vo" in item.url or "ingles" in scrapedurl or "vo" in scrapedurl: item_local.language += ["VO"] if item_local.language == []: item_local.language = ['CAST'] # Por defecto if "dual" in scrapedlang.lower() or "dual" in title.lower(): item_local.language[0:0] = ["DUAL"] #Limpiamos el título de la basura innecesaria title = title.replace("Dual", "").replace("dual", "").replace( "Subtitulada", "").replace("subtitulada", "").replace("Subt", "").replace( "subt", "").replace("Sub", "").replace("sub", "").replace( "(Proper)", "").replace("(proper)", "").replace( "Proper", "").replace("proper", "").replace( "#", "").replace("(Latino)", "").replace("Latino", "") title = title.replace("- HDRip", "").replace( "(HDRip)", "").replace("- Hdrip", "").replace("(microHD)", "").replace( "(DVDRip)", "").replace("(HDRip)", "").replace( "(BR-LINE)", "").replace("(HDTS-SCREENER)", "").replace( "(BDRip)", "").replace("(BR-Screener)", "").replace( "(DVDScreener)", "").replace("TS-Screener", "").replace( " TS", "").replace(" Ts", "").replace( "temporada", "").replace("Temporada", "").replace( "capitulo", "").replace("Capitulo", "") title = re.sub(r'(?i)\s*S\d+E\d+', '', title) title = re.sub(r'(?:\d+)?x.?\s?\d+', '', title) title = re.sub(r'\??\s?\d*?\&.*', '', title).title().strip() item_local.from_title = title # Guardamos esta etiqueta para posible desambiguación de título title_subs = [] # Creamos una lista para guardar info importante if item_local.extra == "peliculas": # preparamos Item para películas if "/serie" in scrapedurl or "/serie" in item.url: continue if not "/serie" in scrapedurl and not "/serie" in item.url: item_local.contentType = "movie" item_local.contentTitle = title item_local.extra = "peliculas" if item_local.extra == "series": # preparamos Item para series if not "/serie" in scrapedurl and not "/serie" in item.url: continue if "/serie" in scrapedurl or "/serie" in item.url: item_local.contentType = "episode" item_local.extra = "series" epi_mult = scrapertools.find_single_match( item_local.url, r'cap.*?-\d+-al-(\d+)') if scrapertools.find_single_match(scrapedtitle, r'(?i)\s*S(\d+)E(\d+)'): item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match( scrapedtitle, r'(?i)\s*S(\d+)E(\d+)') else: item_local.contentSeason = scrapertools.find_single_match( item_local.url, r'temporada-(\d+)') item_local.contentEpisodeNumber = scrapertools.find_single_match( item_local.url, r'cap.*?-(\d+)') if not item_local.contentSeason: item_local.contentSeason = scrapertools.find_single_match( item_local.url, r'-(\d+)[x|X]\d+') if not item_local.contentEpisodeNumber: item_local.contentEpisodeNumber = scrapertools.find_single_match( item_local.url, r'-\d+[x|X](\d+)') try: if not item_local.contentSeason: item_local.contentSeason = 0 if not item_local.contentEpisodeNumber: item_local.contentEpisodeNumber = 1 item_local.contentSeason = int(item_local.contentSeason) item_local.contentEpisodeNumber = int( item_local.contentEpisodeNumber) except: pass if not item_local.contentSeason or item_local.contentSeason < 1: item_local.contentSeason = 0 if item_local.contentEpisodeNumber < 1: item_local.contentEpisodeNumber = 1 #title_subs += ['Episodio %sx%s' % (item_local.contentSeason, str(item_local.contentEpisodeNumber).zfill(2))] title_subs += [' (MAX_EPISODIOS)'] item_local.contentSerieName = title if epi_mult: title = "%sx%s al %s" % ( item_local.contentSeason, str(item_local.contentEpisodeNumber).zfill(2), str(epi_mult).zfill(2) ) #Creamos un título con el rango de episodios else: title = '%sx%s - ' % ( str(item_local.contentSeason), str(item_local.contentEpisodeNumber).zfill(2)) item_local.action = "findvideos" item_local.title = title.strip() item_local.infoLabels['year'] = "-" #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting( 'filter_languages', channel ) > 0 and item.filter_lang: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len( itemlist) # Recalculamos los items después del filtrado if cnt_title >= cnt_tot and ( len(matches) - cnt_match ) + cnt_title > cnt_tot * 1.3: #Contador de líneas añadidas break #logger.debug(item_local) matches = matches[cnt_match:] # Salvamos la entradas no procesadas cnt_tot_match += cnt_match # Calcular el num. total de items mostrados #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__, idioma_busqueda=idioma_busqueda) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page or len(matches) > 0: curr_page_print = int(cnt_tot_match / float(cnt_tot)) if curr_page_print < 1: curr_page_print = 1 if last_page: if last_page > 1: last_page_print = int((last_page * page_factor) + 0.999999) title = '%s de %s' % (curr_page_print, last_page_print) else: title = '%s' % curr_page_print itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page), page_factor=str(page_factor), cnt_tot_match=str(cnt_tot_match), matches=matches, last_page_print=last_page_print, post=post, referer=referer)) return itemlist
def listado(item): # Listado principal logger.info() itemlist = [] matches = [] logos = {'Fórmula 1': '/f1-logo', 'Fórmula 2': '/f2-', 'Fórmula E': '/fe-', 'MotoGP': '/moto-gp', 'Moto2': '/moto2', 'Moto3': '/moto3'} item.category = categoria #logger.debug(item) cnt_tot = 30 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist cnt_offset = 0 # offset para cnt_title en searchs curr_page = 1 last_page = 999 inicio = time.time() # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout * 2 # Timeout para descargas next_page_url = item.url # Máximo num. de líneas permitidas por TMDB. Máx de 5 segundos por Itemlist para no degradar el rendimiento while (next_page_url and cnt_title < cnt_tot and curr_page <= last_page and fin > time.time()) or item.matches: # Descarga la página data = '' cnt_match = 0 # Contador de líneas procesadas de matches if item.extra2 == 'novedades': patron = '<div\s*class="elementor-widget-container">\s*<div\s*class=' patron += '"elementor-image">\s*<a\s*href="([^"]+)">\s*<img\s*(?:width="[^"]+"\s*' patron += 'height="[^"]+"\s*)?src="([^"]+)"\s*class="attachment-medium_large\s*' patron += 'size-medium_large"\s*alt="[^"]*"\s*(?:loading="[^"]*"\s*)?srcset=.*?<h4\s*class=' patron += '"elementor-heading[^>]+>\s*<a\s*href="[^"]+">\s*(.*?)\s*<\/a>\s*<\/h4>' else: patron = '<article\s*class="[^>]+>\s*<div\s*class="elementor-post__card">\s*' patron += '<a\s*class="[^"]+"\s*href="([^"]+)"\s*>\s*<div\s*class=' patron += '"elementor-post__thumbnail"\s*>\s*<\s*img.*?src="([^"]+)".*?' patron += '<h3\s*class="elementor-post__title"\s*>\s*<a href="[^"]+"\s*>' patron += '\s*(.*?)\s*<\/a>\s*<\/h3>\s*<\/div>\s*<\/div>\s*<\/article>' if not item.matches: # si no viene de una pasada anterior, descargamos data, success, code, item, itemlist = generictools.downloadpage(next_page_url, timeout=timeout_search, s2=False, patron=patron, item=item, itemlist=itemlist) # Descargamos la página) # Verificamos si se ha cargado una página correcta curr_page += 1 # Apunto ya a la página siguiente if not data or not success: # Si la web está caída salimos sin dar error if len(itemlist) > 1: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist # Si no hay nada más, salimos directamente # Comprobar si hay más páginas patron_page = '<a\s*class="page-numbers[^"]+"\s*href="([^"]+)">Siguiente' if scrapertools.find_single_match(data, patron_page): next_page_url = scrapertools.find_single_match(data, patron_page) else: next_page_url = '' if not item.matches: # De pasada anterior? matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches del item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) # Iniciamos el Plot y marcamos TMDB como no usable item.contentPlot = '[COLOR gold][B]%s[/B][/COLOR]%s\n\n' % (item.title, item.channel_sufix) #iniciamos el Plot con el Deporte item.from_title = '%s - ' % item.title item.infoLabels['tmdb_id'] = null #Empezamos el procesado de matches for scrapedurl, scrapedthumb, scrapedtitle in matches: #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() cnt_match += 1 title = scrapedtitle title = scrapertools.remove_htmltags(title).rstrip('.') # Removemos Tags del título title = title.replace("á", "a").replace("é", "e").replace("í", "i")\ .replace("ó", "o").replace("ú", "u").replace("ü", "u")\ .replace("�", "ñ").replace("ñ", "ñ").replace("’", "'")\ .replace("&", "&") cnt_title += 1 # Incrementamos el contador de entradas válidas # Procesamos idiomas item_local.language = [] #creamos lista para los idiomas if not item_local.language: item_local.language = ['CAST'] # [CAST] por defecto # Procesamos Calidad if not item_local.quality: item_local.quality = 'HDTV' item_local.thumbnail = scrapedthumb #iniciamos thumbnail item_local.contentThumbnail = scrapedthumb #iniciamos thumbnail item_local.infoLabels['fanart'] = scrapedthumb #iniciamos Fanart # Para Novedades buscamos el Deporte en los thumbs if item_local.extra2 == 'novedades': for sport, logo in list(logos.items()): if logo in item_local.thumbnail.lower(): item_local.contentPlot = '[COLOR gold][B]%s[/B][/COLOR]%s\n\n' % (sport, item.channel_sufix) item_local.from_title = '%s - ' % sport break item_local.url = scrapedurl #iniciamos la url item_local.url_tvshow = item_local.url # Guardamos los formatos para películas item_local.contentType = event item_local.action = "episodios" year = scrapertools.find_single_match(title, '\d{4}') if year: item_local.infoLabels['year'] = int(year) item_local.infoLabels['aired'] = str(year) title = re.sub(r'(?i)TV|Online|(4k-hdr)|(fullbluray)|4k| - 4k|(3d)|miniserie|\d{4}', '', title).strip() item_local.title = title.strip().lower().title() item_local.contentTitle = item_local.title item_local.from_title += item_local.title #Ahora se filtra por idioma, si procede, y se pinta lo que vale if filter_languages > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len(itemlist) - cnt_offset # Recalculamos los items después del filtrado if cnt_title >= cnt_tot and (len(matches) - cnt_match) + cnt_title > cnt_tot * 1.3: #Contador de líneas añadidas break #logger.debug(item_local) matches = matches[cnt_match:] # Salvamos la entradas no procesadas # Enlace a Temporadas anteriores if item.extra2 != 'novedades': patron = '<h2\s*class=".*?<a\s*href="([^"]+)"\s*class="' url_temp_anteriores = scrapertools.find_single_match(data, patron) itemlist.insert(0,item.clone(title="Temporadas anteriores", url=url_temp_anteriores, action="temporadas_anteriores", thumbnail=thumb_sports, url_tvshow = url_temp_anteriores, language=['CAST'], quality = 'HDTV')) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto item.category = categoria item.extra2 = 'xyz' del item.extra2 #logger.debug(item) #Bajamos los datos de la página data = '' patron = '<p><a href="([^"]+)" rel' try: data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "utf-8", errors="replace").encode("utf-8") except: pass if not data: logger.error( "ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log' )) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[1] #Restauramos matches item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos if not item.armagedon: matches = re.compile(patron, re.DOTALL).findall(data) if not matches: #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_findvideos( item, itemlist) #Llamamos al método para el pintado del error else: logger.error( "ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web " + " / PATRON: " + patron + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log' )) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[1] #Restauramos matches item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: item.emergency_urls = [] #Iniciamos emergency_urls item.emergency_urls.append( []) #Reservamos el espacio para los .torrents locales item.emergency_urls.append( matches) #Salvamnos matches de los vídeos... #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB if not item.videolibray_emergency_urls: item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent for scrapedurl in matches: #leemos los torrents con la diferentes calidades if 'javascript' in scrapedurl: #evitamos la basura continue url = '' if not item.armagedon: url = urlparse.urljoin(host, scrapedurl) #Leemos la siguiente página, que es de verdad donde está el magnet/torrent try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(url, timeout=timeout).data) data = unicode(data, "utf-8", errors="replace").encode("utf-8") except: pass patron = "window.open\('([^']+)'" url = scrapertools.find_single_match(data, patron) if not url: #error logger.error( "ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web " + " / PATRON: " + patron + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log' )) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? item.armagedon = True #Marcamos la situación como catastrófica else: continue #si no hay más datos, algo no funciona, pasamos al siguiente #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = urlparse.urljoin(host, url) if item.videolibray_emergency_urls: item.emergency_urls[0].append( item_local.url) #guardamos la url y pasamos a la siguiente continue if item.emergency_urls and not item.videolibray_emergency_urls: item_local.torrent_alt = item.emergency_urls[0][ 0] #Guardamos la url del .Torrent ALTERNATIVA if item.armagedon: item_local.url = item.emergency_urls[0][0] #Restauramos la url if len(item.emergency_urls[0]) > 1: del item.emergency_urls[0][0] #Buscamos si ya tiene tamaño, si no, los buscamos en el archivo .torrent size = scrapertools.find_single_match( item_local.quality, '\s?\[(\d+,?\d*?\s\w\s?[b|B])\]') if not size and not item.armagedon: size = generictools.get_torrent_size( item_local.url) #Buscamos el tamaño en el .torrent if size: item_local.title = re.sub( r'\s?\[\d+,?\d*?\s\w\s?[b|B]\]', '', item_local.title) #Quitamos size de título, si lo traía item_local.title = '%s [%s]' % ( item_local.title, size) #Agregamos size al final del título size = size.replace('GB', 'G B').replace('Gb', 'G b').replace( 'MB', 'M B').replace('Mb', 'M b') item_local.quality = re.sub( r'\s?\[\d+,?\d*?\s\w\s?[b|B]\]', '', item_local.quality) #Quitamos size de calidad, si lo traía item_local.quality = '%s [%s]' % ( item_local.quality, size ) #Agregamos size al final de la calidad if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality #Ahora pintamos el link del Torrent item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % ( item_local.quality, str(item_local.language)) #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality).strip() item_local.quality = item_local.quality.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) if item.videolibray_emergency_urls: #Si ya hemos guardado todas las urls... return item #... nos vamos if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): logger.info() itemlist = [] item.category = categoria #logger.debug(item) curr_page = 1 # Página inicial cnt_title = 0 # Contador de líneas insertadas en Itemlist if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos cnt_tot = 40 # Poner el num. máximo de items por página cnt_pct = 0.725 #% de la página a llenar inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout # Timeout para descargas if item.extra == 'search': timeout_search = timeout * 2 # Timeout un poco más largo para las búsquedas if timeout_search < 5: timeout_search = 5 # Timeout un poco más largo para las búsquedas if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' next_page_url = item.url #Máximo num. de líneas permitidas por TMDB. Máx de 10 segundos por Itemlist para no degradar el rendimiento while cnt_title < cnt_tot * cnt_pct and fin > time.time(): # Descarga la página data = '' try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(next_page_url, timeout=timeout_search).data) data = unicode(data, "utf-8", errors="replace").encode("utf-8") except: pass if not data: #Si la web está caída salimos sin dar error logger.error( "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #Patrón para todo, menos para Alfabeto if item.extra == 'search': patron = '<div class="moditemfdb"><a title="([^"]+)"\s+href="([^"]+)"><img.*?class="thumbnailresult" src="([^"]+)"\/><\/a>' elif item.extra2 == 'categorias': patron = '<div class="blogitem "><a href="([^"]+)".*?src="([^"]+)" alt.*?title="([^"]+)">' else: patron = '<div class="blogitem "><a title="([^"]+)"\s+href="([^"]+)">.*?src="([^"]+)" onload' matches = re.compile(patron, re.DOTALL).findall(data) if not matches and not 'Total: 0 resultados encontrados' in data and not 'Total: 0 results found' in data: item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_episodios( item, itemlist) #Llamamos al método para el pintado del error return itemlist #Salimos logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Buscamos la url de paginado y la última página patron = '<a href="([^"]+=(\d+))" title="Next">Next<\/a>' if not scrapertools.find_single_match(data, patron): patron = '<a href="([^"]+=(\d+))" title="Siguiente">Siguiente<\/a>' try: next_page_url, curr_page = scrapertools.find_single_match( data, patron) curr_page = int(curr_page) / len(matches) except: #Si no lo encuentra, lo ponemos a 1 #logger.error('ERROR 03: LISTADO: Al obtener la paginación: ' + patron + ' / ' + data) fin = 0 #Forzamos a salir del WHILE al final del FOR cnt_title = 0 #Evitamos pié de página curr_page = 1 next_page_url = item.url next_page_url = urlparse.urljoin(host, next_page_url) #logger.debug('curr_page: ' + str(curr_page) + ' / url: ' + next_page_url) #Empezamos el procesado de matches for scrapedtitle, scrapedurl, scrapedthumb in matches: if item.extra2 == 'categorias': #Cambia el orden de tres parámetros (Categorías) title = scrapedthumb url = urlparse.urljoin(host, scrapedtitle) thumb = scrapedurl else: #lo estándar title = scrapedtitle url = urlparse.urljoin(host, scrapedurl) thumb = scrapedthumb quality = scrapertools.find_single_match( title, '\[(.*?)\]') #capturamos quality title = re.sub(r'\[.*?\]', '', title) #y lo borramos de title title = title.replace("á", "a").replace("é", "e").replace( "í", "i").replace("ó", "o").replace("ú", "u").replace( "ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace( "ã", "a").replace("&etilde;", "e").replace( "ĩ", "i").replace("õ", "o").replace( "ũ", "u").replace("ñ", "ñ").replace("’", "'") item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.post_num: del item_local.post_num if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color title_subs = [] #creamos una lista para guardar info importante item_local.language = [] #iniciamos Lenguaje item_local.quality = quality #guardamos la calidad, si la hay item_local.url = url #guardamos el thumb item_local.thumbnail = thumb #guardamos el thumb item_local.context = "['buscar_trailer']" item_local.contentType = "movie" #por defecto, son películas item_local.action = "findvideos" #Ajustamos los idiomas if ("-latino-" in url.lower() or "(latino)" in title.lower()) and "LAT" not in item_local.language: item_local.language += ['LAT'] elif ('-vos-' in url.lower() or '-vose-' in url.lower() or '(vos)' in title.lower() or '(vose)' in title.lower()) and "VOSE" not in item_local.language: item_local.language += ['VOSE'] elif ('-vo-' in url.lower() or '(vo)' in title.lower()) and "VO" not in item_local.language: item_local.language += ['VO'] if item_local.language == []: item_local.language = ['CAST'] #Por defecto title = re.sub(r'\(.*?\)', '', title) #Limpiamos del idioma de title #Detectamos info interesante a guardar para después de TMDB if scrapertools.find_single_match(title, '[m|M].*?serie'): title = re.sub(r'[m|M]iniserie', '', title) title_subs += ["Miniserie"] if scrapertools.find_single_match(title, '[s|S]aga'): title = re.sub(r'[s|S]aga', '', title) title_subs += ["Saga"] if scrapertools.find_single_match(title, '[c|C]olecc'): title = re.sub(r'[c|C]olecc...', '', title) title_subs += ["Colección"] if "duolog" in title.lower(): title_subs += ["[Saga]"] title = title.replace(" Duologia", "").replace( " duologia", "").replace(" Duolog", "").replace(" duolog", "") if "trilog" in title.lower(): title_subs += ["[Saga]"] title = title.replace(" Trilogia", "").replace( " trilogia", "").replace(" Trilog", "").replace(" trilog", "") if "extendida" in title.lower() or "v.e." in title.lower( ) or "v e " in title.lower(): title_subs += ["[V. Extendida]"] title = title.replace("Version Extendida", "").replace( "(Version Extendida)", "").replace("V. Extendida", "").replace("VExtendida", "").replace( "V Extendida", "").replace("V.Extendida", "").replace( "V Extendida", "").replace("V.E.", "").replace( "V E ", "").replace("V:Extendida", "") item_local.infoLabels["year"] = '-' #Reseteamos el año para TMDB #Limpiamos el título de la basura innecesaria title = re.sub(r'- $', '', title) title = re.sub( r'TV|Online|Spanish|Torrent|en Espa\xc3\xb1ol|Español|Latino|Subtitulado|Blurayrip|Bluray rip|\[.*?\]|R2 Pal|\xe3\x80\x90 Descargar Torrent \xe3\x80\x91|Completa|Temporada|Descargar|Torren', '', title, flags=re.IGNORECASE) #Terminamos de limpiar el título title = re.sub(r'\??\s?\d*?\&.*', '', title) title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').strip().lower().title() item_local.from_title = title.strip().lower().title( ) #Guardamos esta etiqueta para posible desambiguación de título #Salvamos el título según el tipo de contenido if item_local.contentType == "movie": item_local.contentTitle = title.strip().lower().title() else: item_local.contentSerieName = title.strip().lower().title() item_local.title = title.strip().lower().title( ) #Guardamos el título #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len(itemlist) #Contador de líneas añadidas #logger.debug(item_local) #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if cnt_title >= cnt_tot * cnt_pct: title = '%s' % curr_page itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, url=next_page_url, extra=item.extra, extra2=item.extra2)) return itemlist
def listado(item): # Listado principal y de búsquedas logger.info() itemlist = [] item.category = categoria thumb_pelis = get_thumb("channels_movie.png") thumb_series = get_thumb("channels_tvshow.png") #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial last_page_print = 1 # Última página inicial, para píe de página page_factor = 1.0 # Factor de conversión de pag. web a pag. Alfa if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos if item.page_factor: page_factor = float( item.page_factor) # Si viene de una pasada anterior, lo usamos del item.page_factor # ... y lo borramos if item.last_page_print: last_page_print = item.last_page_print # Si viene de una pasada anterior, lo usamos del item.last_page_print # ... y lo borramos cnt_tot = 30 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist if item.cnt_tot_match: cnt_tot_match = float( item.cnt_tot_match ) # restauramos el contador TOTAL de líneas procesadas de matches del item.cnt_tot_match else: cnt_tot_match = 0.0 # Contador TOTAL de líneas procesadas de matches inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout * 2 # Timeout para descargas if item.extra == 'search' and item.extra2 == 'episodios': # Si viene de episodio que quitan los límites cnt_tot = 999 fin = inicio + 30 #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos matches = [] if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' post = None if item.post: # Rescatamos el Post, si lo hay post = item.post next_page_url = item.url # Máximo num. de líneas permitidas por TMDB. Máx de 5 segundos por Itemlist para no degradar el rendimiento while (cnt_title < cnt_tot and curr_page <= last_page and fin > time.time()) or item.matches: # Descarga la página data = '' cnt_match = 0 # Contador de líneas procesadas de matches if not item.matches: # si no viene de una pasada anterior, descargamos data, response, item, itemlist = generictools.downloadpage( next_page_url, timeout=timeout_search, post=post, s2=False, item=item, itemlist=itemlist) # Descargamos la página) # Verificamos si ha cambiado el Host global host, canonical if response.canonical and response.canonical != host: host, canonical = generictools.check_host( channel, [response.canonical] + host_alt, host_black_list, host='', CF=True, alfa_s=True, canonical=True) # Verificamos si se ha cargado una página correcta curr_page += 1 # Apunto ya a la página siguiente if not data or not response.sucess: # Si la web está caída salimos sin dar error if len(itemlist) > 1: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist # Si no hay nada más, salimos directamente if item.extra2 == 'PELICULA': #Patrón para seleccionar el bloque patron = '(?i)<header\s*class="archive_post">\s*<h2>\s*A.adido\s*recientemente\s*<\/h2>' patron += '\s*<span>\s*[^<]*\s*<\/span>\s*<\/header>\s*<div\s*id="archive-content"' patron += '\s*class="animation[^"]*">(.*?<\/article>\s*<\/div>' patron += '(?:\s*<div\s*class="pagination">.*?<\/div>))' data = scrapertools.find_single_match(data, patron) #logger.debug(data) #Patrón para búsquedas, pelis y series if item.extra == 'search': patron = '<article><div\s*class="image">.*?<img\s*src="([^"]+)".*?<span\s*' patron += 'class="movies">()[^<]*<\/span>.*?<a\s*href="([^"]+)">\s*([^<]*)' patron += '<\/a>\s*<\/div>\s*<div[^<]*<span[^<]*<\/span>\s*<span\s*' patron += 'class="year">\s*(?:(\d{4}))?\s*<\/span>' else: patron = '<article\s*id="post[^>]+>.*?<img\s*src="([^"]+)".*?<span\s*' patron += 'class="quality">\s*([^<]*)<\/span>.*?<h3>\s*<a\s*href="([^"]+)">' patron += '\s*([^<]*)<\/a>\s*<\/h3>\s*<span>(?:.*?(\d{4}))?\s*<\/span>' if not item.matches: # De pasada anterior? matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches del item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) if not matches and item.extra != 'search' and not item.extra2: #error logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. ' + 'Reportar el error con el log')) break #si no hay más datos, algo no funciona, pintamos lo que tenemos if not matches and item.extra == 'search': #búsqueda vacía if len(itemlist) > 0: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist #Salimos # Actualizado la url por si ha habido redirecciones if last_page == 99999: #Si es la primera pasada... patron_canonical = '<link\s*rel="canonical"\s*href="([^"]+)"\s*\/*>' if scrapertools.find_single_match(data, patron_canonical): canonical = scrapertools.find_single_match( data, patron_canonical) if not canonical.endswith('/'): canonical += '/' item.url = canonical + 'page/1/' # Buscamos la próxima página next_page_url = re.sub(r'page\/(\d+)', 'page/%s' % str(curr_page), item.url) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page)) # Buscamos la última página if last_page == 99999: #Si es el valor inicial, buscamos patron_last = '<div\s*class="pagination">\s*<span>P.gina\s*\d+\s*de\s*(\d+)\s*<\/span>' try: last_page = int( scrapertools.find_single_match(data, patron_last)) page_factor = float(len(matches)) / float(cnt_tot) except: #Si no lo encuentra, lo ponemos a 999 last_page = 1 last_page_print = int((float(len(matches)) / float(cnt_tot)) + 0.999999) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page)) #Empezamos el procesado de matches for scrapedthumb, scrapedquality, scrapedurl, scrapedtitle, scrapedyear in matches: scrapedlanguage = '' cnt_match += 1 title = scrapedtitle title = scrapertools.remove_htmltags(title).rstrip( '.') # Removemos Tags del título url = scrapedurl title_subs = [] #creamos una lista para guardar info importante # Slugify, pero más light title = title.replace("á", "a").replace("é", "e").replace("í", "i")\ .replace("ó", "o").replace("ú", "u").replace("ü", "u")\ .replace("�", "ñ").replace("ñ", "ñ") title = scrapertools.decode_utf8_error(title) cnt_title += 1 # Incrementamos el contador de entradas válidas item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.extra2 = True del item_local.extra2 item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color # Procesamos idiomas item_local.language = [] #creamos lista para los idiomas if '[Subs. integrados]' in scrapedquality or '(Sub Forzados)' in scrapedquality \ or 'Sub' in scrapedquality or 'ing' in scrapedlanguage.lower(): item_local.language = ['VOS'] # añadimos VOS if 'lat' in scrapedlanguage.lower(): item_local.language += ['LAT'] # añadimos LAT if 'castellano' in scrapedquality.lower() or ('español' in scrapedquality.lower() \ and not 'latino' in scrapedquality.lower()) or 'cas' in scrapedlanguage.lower(): item_local.language += ['CAST'] # añadimos CAST if '[Dual' in title or 'dual' in scrapedquality.lower( ) or 'dual' in scrapedlanguage.lower(): title = re.sub(r'(?i)\[dual.*?\]', '', title) item_local.language += ['DUAL'] # añadimos DUAL if not item_local.language: item_local.language = ['LAT'] # [LAT] por defecto # Procesamos Calidad if scrapedquality: item_local.quality = scrapertools.remove_htmltags( scrapedquality) # iniciamos calidad if '[720p]' in scrapedquality.lower( ) or '720p' in scrapedquality.lower(): item_local.quality = '720p' if '[1080p]' in scrapedquality.lower( ) or '1080p' in scrapedquality.lower(): item_local.quality = '1080p' if '4k' in scrapedquality.lower(): item_local.quality = '4K' if '3d' in scrapedquality.lower( ) and not '3d' in item_local.quality.lower(): item_local.quality += ', 3D' if not item_local.quality: item_local.quality = '1080p' item_local.thumbnail = urlparse.urljoin( host, scrapedthumb) #iniciamos thumbnail item_local.url = urlparse.urljoin(host, url) #guardamos la url final item_local.context = "['buscar_trailer']" #... y el contexto # Guardamos los formatos para películas item_local.contentType = "movie" item_local.action = "findvideos" title = re.sub( r'(?i)TV|Online|(4k-hdr)|(fullbluray)|4k| - 4k|(3d)|miniserie', '', title).strip() item_local.quality = re.sub( r'(?i)proper|unrated|directors|cut|repack|internal|real|extended|masted|docu|super|duper|amzn|uncensored|hulu', '', item_local.quality).strip() #Analizamos el año. Si no está claro ponemos '-' item_local.infoLabels["year"] = '-' try: if scrapedyear: item_local.infoLabels["year"] = int(scrapedyear) except: pass #Terminamos de limpiar el título title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').replace( '[4K]', '').replace('(4K)', '').strip().lower().title() title = title.strip().lower().title() item_local.from_title = title #Guardamos esta etiqueta para posible desambiguación de título item_local.contentTitle = title item_local.title = title #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Ahora se filtra por idioma, si procede, y se pinta lo que vale if filter_languages > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len( itemlist) # Recalculamos los items después del filtrado if cnt_title >= cnt_tot and ( len(matches) - cnt_match ) + cnt_title > cnt_tot * 1.3: #Contador de líneas añadidas break #logger.debug(item_local) matches = matches[cnt_match:] # Salvamos la entradas no procesadas cnt_tot_match += cnt_match # Calcular el num. total de items mostrados #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__, idioma_busqueda=idioma_busqueda) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page or len(matches) > 0: curr_page_print = int(cnt_tot_match / float(cnt_tot)) if curr_page_print < 1: curr_page_print = 1 if last_page: if last_page > 1: last_page_print = int((last_page * page_factor) + 0.999999) title = '%s de %s' % (curr_page_print, last_page_print) else: title = '%s' % curr_page_print itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page), page_factor=str(page_factor), cnt_tot_match=str(cnt_tot_match), matches=matches, last_page_print=last_page_print, post=post)) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados matches = [] data = '' code = 0 #logger.debug(item) #Bajamos los datos de la página y seleccionamos el bloque patron = '\s*<th\s*class="hide-on-mobile">Total\s*Descargas<\/th>\s*<th>' patron += 'Descargar<\/th>\s*<\/thead>\s*<tbody>\s*(.*?<\/tr>)\s*<\/tbody>' patron += '\s*<\/table>\s*<\/div>\s*<\/div>\s*<\/div>' if not item.matches: data, success, code, item, itemlist = generictools.downloadpage(item.url, timeout=timeout, s2=False, patron=patron, item=item, itemlist=[]) # Descargamos la página) #Verificamos si se ha cargado una página, y si además tiene la estructura correcta if (not data and not item.matches) or code == 999: if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? if len(item.emergency_urls) > 1: matches = item.emergency_urls[1] #Restauramos matches de vídeos item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos elif data: # Seleccionamos el bloque y buscamos los apartados data = scrapertools.find_single_match(data, patron) patron = '<tr>(?:\s*<td>[^<]+<\/td>)?\s*<td>([^<]+)<\/td>\s*<td>([^<]+)<\/td>\s*' patron += '<td\s*class=[^<]+<\/td>(?:<td>([^<]+)<\/td>)?\s*<td\s*class=[^<]+<\/td>\s*' patron += '<td>\s*<a\s*class="[^"]+"\s*(?:data-row="[^"]+"\s*data-post="[^"]+"\s*)?' patron += 'href="([^"]+)"\s*(?:data-season="([^"]+)"\s*data-serie="([^"]+)")?' if not item.armagedon: if not item.matches: matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) if not matches: #error return itemlist #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: item.emergency_urls = [] #Iniciamos emergency_urls item.emergency_urls.append([]) #Reservamos el espacio para los .torrents locales item.emergency_urls.append(matches) #Salvamnos matches de los vídeos... #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB if not item.videolibray_emergency_urls: item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent con las diferentes calidades for scrapedquality, scrapedlanguage, scrapedsize, scrapedurl, season_num, episode_num in matches: scrapedpassword = '' #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = scrapedurl # Restauramos urls de emergencia si es necesario local_torr = '' if item.emergency_urls and not item.videolibray_emergency_urls: item_local.torrent_alt = item.emergency_urls[0][0] #Guardamos la url del .Torrent ALTERNATIVA if item.armagedon: item_local.url = item.emergency_urls[0][0] #Restauramos la url if item_local.url.startswith("\\") or item_local.url.startswith("/"): from core import filetools if item.contentType == 'movie': FOLDER = config.get_setting("folder_movies") else: FOLDER = config.get_setting("folder_tvshows") local_torr = filetools.join(config.get_videolibrary_path(), FOLDER, item_local.url) if len(item.emergency_urls[0]) > 1: del item.emergency_urls[0][0] # Procesamos idiomas item_local.language = [] #creamos lista para los idiomas item_local.quality = scrapedquality # Copiamos la calidad if '[Subs. integrados]' in scrapedlanguage or '(Sub Forzados)' in scrapedlanguage \ or 'Subs integrados' in scrapedlanguage: item_local.language = ['VOS'] # añadimos VOS if 'castellano' in scrapedlanguage.lower() or ('español' in scrapedlanguage.lower() and not 'latino' in scrapedlanguage.lower()): item_local.language += ['CAST'] # añadimos CAST if 'dual' in item_local.quality.lower(): item_local.quality = re.sub(r'(?i)dual.*?', '', item_local.quality).strip() item_local.language += ['DUAL'] # añadimos DUAL if not item_local.language: item_local.language = ['LAT'] # [LAT] por defecto #Buscamos tamaño en el archivo .torrent size = '' if item_local.torrent_info: size = item_local.torrent_info elif scrapedsize: size = scrapedsize if not size and not item.videolibray_emergency_urls and not item_local.url.startswith('magnet:'): if not item.armagedon: size = generictools.get_torrent_size(item_local.url, local_torr=local_torr) #Buscamos el tamaño en el .torrent desde la web if 'ERROR' in size and item.emergency_urls and not item.videolibray_emergency_urls: item_local.armagedon = True item_local.url = item.emergency_urls[0][0] #Restauramos la url local_torr = filetools.join(config.get_videolibrary_path(), FOLDER, item_local.url) size = generictools.get_torrent_size(item_local.url, local_torr=local_torr) #Buscamos el tamaño en el .torrent emergencia if size: size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',') item_local.torrent_info = '%s, ' % size #Agregamos size if item_local.url.startswith('magnet:') and not 'Magnet' in item_local.torrent_info: item_local.torrent_info += ' Magnet' if item_local.torrent_info: item_local.torrent_info = item_local.torrent_info.strip().strip(',') item.torrent_info = item_local.torrent_info if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info # Guadamos la password del RAR password = scrapedpassword # Si tiene contraseña, la guardamos y la pintamos if password or item.password: if not item.password: item.password = password item_local.password = item.password itemlist.append(item.clone(action="", title="[COLOR magenta][B] Contraseña: [/B][/COLOR]'" + item_local.password + "'", folder=False)) # Guardamos urls de emergencia si se viene desde un Lookup de creación de Videoteca if item.videolibray_emergency_urls: item.emergency_urls[0].append(item_local.url) #guardamos la url y nos vamos continue if item_local.armagedon: item_local.quality = '[COLOR hotpink][E][/COLOR] [COLOR limegreen]%s[/COLOR]' % item_local.quality #Ahora pintamos el link del Torrent item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][Torrent][/COLOR] ' \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) #Preparamos título y calidad, quitando etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace("[]", "")\ .replace("()", "").replace("(/)", "").replace("[/]", "")\ .replace("|", "").strip() item_local.quality = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace("[]", "")\ .replace("()", "").replace("(/)", "").replace("[/]", "")\ .replace("|", "").strip() if not size or 'Magnet' in size: item_local.alive = "??" #Calidad del link sin verificar elif 'ERROR' in size and 'Pincha' in size: item_local.alive = "ok" #link en error, CF challenge, Chrome disponible elif 'ERROR' in size and 'Introduce' in size: item_local.alive = "??" #link en error, CF challenge, ruta de descarga no disponible item_local.channel = 'setting' item_local.action = 'setting_torrent' item_local.unify = False item_local.folder = False item_local.item_org = item.tourl() elif 'ERROR' in size: item_local.alive = "no" #Calidad del link en error, CF challenge? else: item_local.alive = "ok" #Calidad del link verificada if item_local.channel != 'setting': item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append(item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting('filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link(itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: return item #... nos vamos if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len(itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb("next.png") #... pintamos todo con aviso itemlist.append(Item(channel=item.channel, url=host, title="[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) itemlist.extend(itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): # Listado principal y de búsquedas logger.info() itemlist = [] item.category = categoria thumb_pelis = get_thumb("channels_movie.png") thumb_series = get_thumb("channels_tvshow.png") #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial last_page_print = 1 # Última página inicial, para píe de página page_factor = 1.0 # Factor de conversión de pag. web a pag. Alfa if item.curr_page: curr_page = int(item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int(item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos if item.page_factor: page_factor = float(item.page_factor) # Si viene de una pasada anterior, lo usamos del item.page_factor # ... y lo borramos if item.last_page_print: last_page_print = item.last_page_print # Si viene de una pasada anterior, lo usamos del item.last_page_print # ... y lo borramos cnt_tot = 30 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist if item.cnt_tot_match: cnt_tot_match = float(item.cnt_tot_match) # restauramos el contador TOTAL de líneas procesadas de matches del item.cnt_tot_match else: cnt_tot_match = 0.0 # Contador TOTAL de líneas procesadas de matches inicio = time.time() # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout * 2 # Timeout para descargas if item.extra == 'search' and item.extra2 == 'episodios': # Si viene de episodio que quitan los límites cnt_tot = 999 fin = inicio + 30 #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend(item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos matches = [] if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' post = None if item.post: # Rescatamos el Post, si lo hay post = item.post next_page_url = item.url # Máximo num. de líneas permitidas por TMDB. Máx de 5 segundos por Itemlist para no degradar el rendimiento while (cnt_title < cnt_tot and curr_page <= last_page and fin > time.time()) or item.matches: # Descarga la página data = '' cnt_match = 0 # Contador de líneas procesadas de matches if not item.matches: # si no viene de una pasada anterior, descargamos data, success, code, item, itemlist = generictools.downloadpage(next_page_url, timeout=timeout_search, post=post, s2=False, item=item, itemlist=itemlist) # Descargamos la página) # Verificamos si se ha cargado una página correcta curr_page += 1 # Apunto ya a la página siguiente if not data or not success: # Si la web está caída salimos sin dar error if len(itemlist) > 1: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist # Si no hay nada más, salimos directamente #Patrón para búsquedas, pelis y series patron = '<div\s*class="[^"]+">\s*<div\s*class="card">\s*<a\s*href="([^"]+)"\s*' patron += 'class="card__cover">\s*<img\s*src="([^"]+)"\s*alt="[^"]*">\s*' patron += '<div\s*class="card__play">.*?<\/div>\s*<ul\s*class="card__list">\s*' patron += '<li>([^<]+)<\/li>\s*<\/ul>\s*<\/a>\s*<div\s*class="card__content">\s*' patron += '<h3\s*class="card__title"><a\s*href="[^"]+">([^<]+)<\/a><\/h3>' patron += '.*?<\/div>\s*<\/div>\s*<\/div>' if not item.matches: # De pasada anterior? matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches del item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) if not matches and item.extra != 'search' and not item.extra2: #error logger.error("ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. ' + 'Reportar el error con el log')) break #si no hay más datos, algo no funciona, pintamos lo que tenemos if not matches and item.extra == 'search': #búsqueda vacía if len(itemlist) > 0: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist #Salimos #Buscamos la próxima página next_page_url = re.sub(r'page\/(\d+)', 'page/%s' % str(curr_page), item.url) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page)) #Buscamos la última página if last_page == 99999: #Si es el valor inicial, buscamos patron_last = '<ul\s*class="pagination[^"]+">.*?<li>\s*<a\s*class="page-numbers"\s*href="[^"]+">' patron_last += '(\d+)<\/a><\/li>\s*<li>\s*<a\s*class="next page-numbers"\s*href="[^"]+">»<\/a><\/li>\s*<\/ul>' try: last_page = int(scrapertools.find_single_match(data, patron_last)) page_factor = float(len(matches)) / float(cnt_tot) except: #Si no lo encuentra, lo ponemos a 999 last_page = 1 last_page_print = int((float(len(matches)) / float(cnt_tot)) + 0.999999) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page)) #Empezamos el procesado de matches for scrapedurl, scrapedthumb, scrapedquality, scrapedtitle in matches: cnt_match += 1 title = scrapedtitle title = scrapertools.remove_htmltags(title).rstrip('.') # Removemos Tags del título url = scrapedurl title_subs = [] #creamos una lista para guardar info importante title = title.replace("á", "a").replace("é", "e").replace("í", "i")\ .replace("ó", "o").replace("ú", "u").replace("ü", "u")\ .replace("�", "ñ").replace("ñ", "ñ").replace("’", "'")\ .replace("&", "&") # Se filtran las entradas para evitar duplicados de Temporadas url_list = url if url_list in title_lista: #Si ya hemos procesado el título, lo ignoramos continue else: title_lista += [url_list] #la añadimos a la lista de títulos # Si es una búsqueda por años, filtramos por tipo de contenido if 'anno' in item.extra2 and item.extra == 'series' and '/serie' not in url: continue elif 'anno' in item.extra2 and item.extra == 'peliculas' and '/serie' in url: continue cnt_title += 1 # Incrementamos el contador de entradas válidas item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.extra2 = True del item_local.extra2 item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color # Después de un Search se restablecen las categorías if item_local.extra == 'search': if '/serie' in url: item_local.extra = 'series' # Serie búsqueda else: item_local.extra = 'peliculas' # Película búsqueda # Procesamos idiomas item_local.language = [] #creamos lista para los idiomas if '[Subs. integrados]' in scrapedquality or '(Sub Forzados)' in scrapedquality \ or 'Sub' in scrapedquality: item_local.language = ['VOS'] # añadimos VOS if 'castellano' in scrapedquality.lower() or ('español' in scrapedquality.lower() and not 'latino' in scrapedquality.lower()): item_local.language += ['CAST'] # añadimos CAST if '[Dual' in title or 'dual' in scrapedquality.lower(): title = re.sub(r'(?i)\[dual.*?\]', '', title) item_local.language += ['DUAL'] # añadimos DUAL if not item_local.language: item_local.language = ['LAT'] # [LAT] por defecto # Procesamos Calidad if scrapedquality: item_local.quality = scrapertools.remove_htmltags(scrapedquality) # iniciamos calidad if '[720p]' in scrapedquality.lower() or '720p' in scrapedquality.lower(): item_local.quality = '720p' if '[1080p]' in scrapedquality.lower() or '1080p' in scrapedquality.lower(): item_local.quality = '1080p' if '4k' in scrapedquality.lower(): item_local.quality = '4K' if '3d' in scrapedquality.lower() and not '3d' in item_local.quality.lower(): item_local.quality += ', 3D' if not item_local.quality or item_local.extra == 'series': item_local.quality = '720p' item_local.thumbnail = '' #iniciamos thumbnail item_local.url = urlparse.urljoin(host, url) #guardamos la url final item_local.context = "['buscar_trailer']" #... y el contexto # Guardamos los formatos para series if item_local.extra == 'series' or '/serie' in item_local.url: item_local.contentType = "tvshow" item_local.action = "episodios" item_local.season_colapse = season_colapse #Muestra las series agrupadas por temporadas? else: # Guardamos los formatos para películas item_local.contentType = "movie" item_local.action = "findvideos" #Limpiamos el título de la basura innecesaria if item_local.contentType == "tvshow": title = scrapertools.find_single_match(title, '(^.*?)\s*(?:$|\(|\[|-)') title = re.sub(r'(?i)TV|Online|(4k-hdr)|(fullbluray)|4k| - 4k|(3d)|miniserie', '', title).strip() item_local.quality = re.sub(r'(?i)proper|unrated|directors|cut|repack|internal|real|extended|masted|docu|super|duper|amzn|uncensored|hulu', '', item_local.quality).strip() #Analizamos el año. Si no está claro ponemos '-' item_local.infoLabels["year"] = '-' try: if 'anno' in item.extra2: item_local.infoLabels["year"] = int(item.extra2.replace('anno', '')) except: pass #Terminamos de limpiar el título title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').replace('[4K]', '').replace('(4K)', '').strip().lower().title() item_local.from_title = title.strip().lower().title() #Guardamos esta etiqueta para posible desambiguación de título #Salvamos el título según el tipo de contenido if item_local.contentType == "movie": item_local.contentTitle = title else: item_local.contentSerieName = title.strip().lower().title() item_local.title = title.strip().lower().title() #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Salvamos y borramos el número de temporadas porque TMDB a veces hace tonterias. Lo pasamos como serie completa if item_local.contentSeason and (item_local.contentType == "season" \ or item_local.contentType == "tvshow"): item_local.contentSeason_save = item_local.contentSeason del item_local.infoLabels['season'] #Ahora se filtra por idioma, si procede, y se pinta lo que vale if filter_languages > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len(itemlist) # Recalculamos los items después del filtrado if cnt_title >= cnt_tot and (len(matches) - cnt_match) + cnt_title > cnt_tot * 1.3: #Contador de líneas añadidas break #logger.debug(item_local) matches = matches[cnt_match:] # Salvamos la entradas no procesadas cnt_tot_match += cnt_match # Calcular el num. total de items mostrados #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__, idioma_busqueda='es') #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page or len(matches) > 0: curr_page_print = int(cnt_tot_match / float(cnt_tot)) if curr_page_print < 1: curr_page_print = 1 if last_page: if last_page > 1: last_page_print = int((last_page * page_factor) + 0.999999) title = '%s de %s' % (curr_page_print, last_page_print) else: title = '%s' % curr_page_print itemlist.append(Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page), page_factor=str(page_factor), cnt_tot_match=str(cnt_tot_match), matches=matches, last_page_print=last_page_print, post=post)) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto matches = [] item.category = categoria try: tmdb.set_infoLabels(item, True) #TMDB actualizado except: pass item.extra2 = 'xyz' del item.extra2 #logger.debug(item) matches = item.url if not matches: #error logger.error("ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web: " + str(item)) itemlist.append(item.clone(action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log')) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[1] #Restauramos matches item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug(matches) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: item.emergency_urls = [] #Iniciamos emergency_urls item.emergency_urls.append([]) #Reservamos el espacio para los .torrents locales item.emergency_urls.append(matches) #Salvamnos matches... #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB if not item.videolibray_emergency_urls: item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent for scrapedurl, quality in matches: #leemos los magnets con la diferentes calidades #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = scrapedurl if item.videolibray_emergency_urls: item.emergency_urls[0].append(scrapedurl) #guardamos la url y pasamos a la siguiente continue if item.emergency_urls and not item.videolibray_emergency_urls: item_local.torrent_alt = item.emergency_urls[0][0] #Guardamos la url del .Torrent ALTERNATIVA if item.armagedon: item_local.url = item.emergency_urls[0][0] #... ponemos la emergencia como primaria del item.emergency_urls[0][0] #Una vez tratado lo limpiamos size = '' if not item.armagedon: size = generictools.get_torrent_size(item_local.url) #Buscamos el tamaño en el .torrent if size: quality += ' [%s]' % size if item.armagedon: #Si es catastrófico, lo marcamos quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % quality #Añadimos la calidad y copiamos la duración item_local.quality = quality if scrapertools.find_single_match(item.quality, '(\[\d+:\d+\ h])'): item_local.quality += ' [/COLOR][COLOR white]%s' % scrapertools.find_single_match(item.quality, '(\[\d+:\d+\ h])') #Ahora pintamos el link del Torrent item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % (item_local.quality, str(item_local.language)) #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality).strip() item_local.quality = item_local.quality.replace("--", "").replace("[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor Torrent itemlist_t.append(item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting('filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link(itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) if item.videolibray_emergency_urls: #Si ya hemos guardado todas las urls... return item #... nos vamos if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len(itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb("next.png") #... pintamos todo con aviso itemlist.append(Item(channel=item.channel, url=host, title="[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador)) itemlist.extend(itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): logger.info() itemlist = [] item.category = categoria #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos cnt_tot = 40 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 3 # Después de este tiempo pintamos (segundos) timeout_search = timeout # Timeout para descargas if item.extra == 'search': timeout_search = timeout * 2 # Timeout un poco más largo para las búsquedas if timeout_search < 5: timeout_search = 5 # Timeout un poco más largo para las búsquedas #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' next_page_url = item.url #Máximo num. de líneas permitidas por TMDB. Máx de 3 segundos por Itemlist para no degradar el rendimiento while cnt_title <= cnt_tot * 0.50 and curr_page <= last_page and fin > time.time( ): # Descarga la página data = '' try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(next_page_url, timeout=timeout_search).data) data = unicode(data, "utf-8", errors="replace").encode("utf-8") except: pass curr_page += 1 #Apunto ya a la página siguiente if not data and not item.extra2: #Si la web está caída salimos sin dar error logger.error( "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos status, itemlist = check_blocked_IP( data, itemlist) #Comprobamos si la IP ha sido bloqueada if status: return itemlist #IP bloqueada #Patrón para todo, incluido búsquedas en cualquier caso patron = '<tr class="lista2"><td align="(?:[^"]+)?"\s*class="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*style="(?:[^"]+)?"><a href="[^"]+"><img src="([^"]+)?"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*\/><\/a><\/td><td\s*align="(?:[^"]+)?"\s*class="(?:[^"]+)?"><a onmouseover="(?:[^"]+)?"\s*onmouseout="(?:[^"]+)?"\s*href="[^"]+" title="[^"]+">([^<]+)<\/a>\s*<a href="([^"]+)"><img src="[^"]+"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*><\/a>\s*(?:<a href="([^"]+)"><img src="[^"]+"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*><\/a>)?\s*<br><span.*?<\/span>\s*<\/td><td align="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">.*?<\/td><td align="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">([^<]+)?<\/td><td align="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">\s*<font color="(?:[^"]+)?">(\d+)?<\/font>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches and item.extra != 'search': #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_episodios( item, itemlist) #Llamamos al método para el pintado del error return itemlist #Salimos logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos if not matches and item.extra == 'search': #búsqueda vacía return itemlist #Salimos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Buscamos la próxima y la última página patron_next = '<a href="([^"]+page=(\d+))" title="next page">' if item.extra == 'search': patron_last = '<a href="[^"]+"\s*title="page\s*\d+">\d+<\/a>\s*<b>(\d+)<\/b><\/div><\/div><\/td>' else: patron_last = 'title="previous page"[^<]+<\/a>\s*<a href="[^>]+>(\d+)<\/a>' try: next_page_url, next_page = scrapertools.find_single_match( data, patron_next) next_page = int(next_page) next_page_url = item.url + '&page=' + str(next_page) except: #Si no lo encuentra, lo ponemos a 1 #logger.error('ERROR 03: LISTADO: Al obtener la paginación: ' + patron_next + ' / ' + patron_last + ' / ' + scrapertools.find_single_match(data, "<ul class=\"pagination\">.*?<\/span><\/a><\/li><\/ul><\/nav><\/div><\/div><\/div>")) next_page = 1 #logger.debug('curr_page: ' + str(curr_page) + ' / next_page: ' + str(next_page) + ' / last_page: ' + str(last_page)) if last_page == 99999: #Si es el valor inicial, buscamos if item.extra == 'search': last_page = 99 try: data_last = '' data_last = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(item.url + '&page=%s' % last_page, timeout=timeout_search).data) data_last = unicode(data_last, "utf-8", errors="replace").encode("utf-8") last_page = int( scrapertools.find_single_match( data_last, patron_last)) #lo cargamos como entero except: #Si no lo encuentra, lo ponemos a 1 #logger.error('ERROR 03: LISTADO: Al obtener la paginación: ' + patron_next + ' / ' + patron_last + ' / ' + scrapertools.find_single_match(data, "<ul class=\"pagination\">.*?<\/span><\/a><\/li><\/ul><\/nav><\/div><\/div><\/div>")) last_page = next_page #logger.debug('curr_page: ' + str(curr_page) + ' / next_page: ' + str(next_page) + ' / last_page: ' + str(last_page)) #Empezamos el procesado de matches for scrapedthumbnail, scrapedtitle, scrapedurl, scrapedepisodes, scrapedsize, scrapedseeds in matches: title = scrapedtitle if scrapedepisodes: url = scrapedepisodes else: url = scrapedurl size = scrapedsize title = title.replace("á", "a").replace("é", "e").replace( "í", "i").replace("ó", "o").replace("ú", "u").replace( "ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace( "ã", "a").replace("&etilde;", "e").replace( "ĩ", "i").replace("õ", "o").replace( "ũ", "u").replace("ñ", "ñ").replace("’", "'") if scrapedurl in title_lista: #Si ya hemos procesado el título, lo ignoramos continue else: title_lista += [scrapedurl] #la añadimos a la lista de títulos #cnt_title += 1 item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.extra2 = True del item_local.extra2 item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color title_subs = [] #creamos una lista para guardar info importante item_local.language = ['VO'] #creamos lista para los idiomas item_local.quality = '' #iniciamos calidad item_local.thumbnail = scrapedthumbnail #iniciamos thumbnail if item.extra == 'search': if scrapedepisodes: item_local.extra = 'series' else: item_local.extra = 'peliculas' item_local.url = urlparse.urljoin(host, url) #guardamos la url final if item_local.extra != 'series': item_local.url += '&order=size&by=ASC' #guardamos la url final item_local.context = "['buscar_trailer']" item_local.contentType = "movie" #por defecto, son películas item_local.action = "findvideos" #Analizamos los formatos de la películas if item_local.extra == 'peliculas': patron_title = '(.*?)\.([1|2][9|0]\d{2})?\.(.*?)(?:-.*?)?$' if not scrapertools.find_single_match(title, patron_title): logger.error('ERROR tratando título PELI: ' + title) continue try: title, year, item_local.quality = scrapertools.find_single_match( title, patron_title) except: title = scrapedtitle year = '' item_local.quality = '' title = title.replace('.', ' ') item_local.quality = item_local.quality.replace('.', ' ') #Analizamos los formatos de series, temporadas y episodios elif item_local.extra == 'series': patron_title = '(.*?)(\.[1|2][9|0]\d{2})?\.S\d{2}.*?\.([\d|A-Z]{2}.*?)(?:-.*?)?$' if not scrapertools.find_single_match(title, patron_title): patron_title = '(.*?)\.*([1|2][9|0]\d{2})?(?:\.\d{2}\.\d{2}).*?\.([\d|A-Z]{2}.*?)(?:-.*?)?$' if not scrapertools.find_single_match(title, patron_title): logger.error('ERROR tratando título SERIE: ' + title) continue try: title, year, item_local.quality = scrapertools.find_single_match( title, patron_title) except: title = scrapedtitle year = '' item_local.quality = '' title = title.replace('.', ' ') item_local.quality = item_local.quality.replace('.', ' ') year = '-' item_local.contentType = "tvshow" item_local.action = "episodios" item_local.season_colapse = True #Muestra las series agrupadas por temporadas #Limpiamos el título de la basura innecesaria title = re.sub(r'(?i)TV|Online', '', title).strip() item_local.quality = re.sub( r'(?i)proper|unrated|directors|cut|german|repack|internal|real|korean|extended|masted|docu|oar|super|duper|amzn|uncensored|hulu', '', item_local.quality).strip() #Analizamos el año. Si no está claro ponemos '-' try: year_int = int(year) if year_int >= 1940 and year_int <= 2050: item_local.infoLabels["year"] = year_int else: item_local.infoLabels["year"] = '-' except: item_local.infoLabels["year"] = '-' #Terminamos de limpiar el título title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').strip().lower().title() item_local.from_title = title.strip().lower().title( ) #Guardamos esta etiqueta para posible desambiguación de título #Salvamos el título según el tipo de contenido if item_local.contentType == "movie": item_local.contentTitle = title else: item_local.contentSerieName = title.strip().lower().title() item_local.title = title.strip().lower().title() #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Salvamos y borramos el número de temporadas porque TMDB a veces hace tonterias. Lo pasamos como serie completa if item_local.contentSeason and (item_local.contentType == "season" or item_local.contentType == "tvshow"): item_local.contentSeason_save = item_local.contentSeason del item_local.infoLabels['season'] #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len(itemlist) #Contador de líneas añadidas #logger.debug(item_local) #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__, idioma_busqueda='es,en') #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page: if last_page: title = '%s de %s' % (curr_page - 1, last_page) else: title = '%s' % curr_page - 1 itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page))) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['VO'] #VO por defecto matches = [] item.category = categoria #logger.debug(item) #Bajamos los datos de la página data = '' patron = '<tr class="lista2">\s*<td align="(?:[^"]+)?"\s*class="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*style="(?:[^"]+)?">\s*<a href="[^"]+">\s*<img src="([^"]+)?"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*\/><\/a><\/td>\s*<td\s*align="(?:[^"]+)?"(?:\s*width="[^"]+")?\s*class="(?:[^"]+)?">\s*<a onmouseover="(?:[^"]+)?"\s*onmouseout="(?:[^"]+)?"\s*href="([^"]+)" title="[^"]+">(.*?)<\/a>\s*<a href="[^"]+">\s*<img src="[^"]+"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*><\/a>(?:\s*<a.*?<\/a>)?\s*<br><span.*?<\/span>\s*<\/td>\s*<td align="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">.*?<\/td>\s*<td align="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">(.*?)?<\/td>\s*<td align="(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">\s*<font color="(?:[^"]+)?">(\d+)?<\/font>' try: data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) data = unicode(data, "utf-8", errors="replace").encode("utf-8") except: pass if not data: logger.error( "ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log', folder=False)) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos status, itemlist = check_blocked_IP( data, itemlist) #Comprobamos si la IP ha sido bloqueada if status: return itemlist #IP bloqueada matches = re.compile(patron, re.DOTALL).findall(data) if not matches: #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_findvideos( item, itemlist) #Llamamos al método para el pintado del error else: logger.error( "ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web " + " / PATRON: " + patron + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log', folder=False)) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent con las diferentes calidades for scrapedthumbnail, scrapedurl, scrapedtitle, scrapedsize, scrapedseeds in matches: #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() title = scrapedtitle #Analizamos los formatos de la películas y series if item_local.contentType == 'movie': patron_title = '(.*?)\.([1|2][9|0]\d{2})?\.(.*?)(?:-.*?)?$' if not scrapertools.find_single_match(title, patron_title): continue else: patron_title = '(.*?)(\.[1|2][9|0]\d{2})?\.S\d{2}.*?\.([\d|A-Z]{2}.*?)(?:-.*?)?$' if not scrapertools.find_single_match(title, patron_title): patron_title = '(.*?)\.*([1|2][9|0]\d{2})?(?:\.\d{2}\.\d{2}).*?\.([\d|A-Z]{2}.*?)(?:-.*?)?$' if not scrapertools.find_single_match(title, patron_title): continue try: title, year, item_local.quality = scrapertools.find_single_match( title, patron_title) except: title = scrapedtitle year = '' item_local.quality = '' title = title.replace('.', ' ') item_local.quality = item_local.quality.replace('.', ' ') item_local.quality = re.sub( r'(?i)proper|unrated|directors|cut|german|repack|internal|real|korean|extended|masted|docu|oar|super|duper|amzn|uncensored|hulu', '', item_local.quality).strip() #Buscamos si ya tiene tamaño, si no, los buscamos en el archivo .torrent size = scrapedsize if size: item_local.title = '%s [%s]' % ( item_local.title, size) #Agregamos size al final del título size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',') item_local.torrent_info = '%s, ' % size #Agregamos size #Añadimos los seeds en calidad, como información adicional if scrapedseeds: item_local.torrent_info += 'Seeds: %s' % scrapedseeds #Agregamos seeds if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info.strip( ).strip(',') #Ahora pintamos el link del Torrent item_local.url = urlparse.urljoin(host, scrapedurl) item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][Torrent][/COLOR] ' \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) #Preparamos título de Torrent #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): logger.info() itemlist = [] item.category = categoria #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos cnt_tot = 40 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout # Timeout para descargas if item.extra == 'search': timeout_search = timeout * 2 # Timeout un poco más largo para las búsquedas if timeout_search < 5: timeout_search = 5 # Timeout un poco más largo para las búsquedas #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' next_page_url = item.url #Máximo num. de líneas permitidas por TMDB. Máx de 10 segundos por Itemlist para no degradar el rendimiento while cnt_title < cnt_tot * 0.5 and curr_page <= last_page and fin > time.time( ): # Descarga la página data = '' try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)| ", "", httptools.downloadpage(next_page_url, timeout=timeout_search).data) #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") except: pass curr_page += 1 #Apunto ya a la página siguiente if not data: #Si la web está caída salimos sin dar error logger.error( "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: " + item.url + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: LISTADO:. La Web no responde o ha cambiado de URL. Si la Web está activa, reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #Patrón para todo, menos para Series completas, incluido búsquedas en cualquier caso patron = '<td class="vertThseccion"><img src="([^"]+)"[^>]+><a href="([^"]+)"\s*title="([^"]+)"\s*>[^<]+<\/a><\/td><td>.*?(\d+)?<\/td><td>([^<]+)?<\/td><td>([^<]+)?<\/td><\/tr>' #Si son series completas, ponemos un patrón especializado if item.extra == 'series': patron = '<(td)><a href="([^"]+)"\s*title="([^"]+)"\s*><[^>]+src="[^"]+\/(\d{4})[^"]+"[^>]+>(?:(\d+))?\s*(?:(\d+))?<\/a>' matches = re.compile(patron, re.DOTALL).findall(data) if not matches and not '<p>Lo sentimos, pero que esta buscando algo que no esta aqui. </p>' in data and not item.extra2 and not '<h2>Sin resultados</h2> in data': #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_episodios( item, itemlist) #Llamamos al método para el pintado del error return itemlist #Salimos logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. Reportar el error con el log' )) break #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) #Buscamos la próxima y la última página patron_last = "<div class='pagination'>.*?<a href='([^']+\/page\/(\d+)[^']+)'\s*>(?:»)?(?:\d+)?<\/a><\/div>" if last_page == 99999: #Si es el valor inicial, buscamos last page try: next_page_url, last_page = scrapertools.find_single_match( data, patron_last) #cargamos la url y la última página last_page = int(last_page) except: #Si no lo encuentra, lo ponemos a 1 last_page = 1 #logger.error('ERROR 03: LISTADO: Al obtener la paginación: ' + patron_last + ' / ' + next_page_url + ' / ' + str(last_page)) #logger.debug('curr_page: ' + str(curr_page) + '/ last_page: ' + str(last_page)) if last_page > 1: next_page_url = re.sub(r'\/page\/\d+\/', '/page/%s/' % curr_page, next_page_url) next_page_url = next_page_url.replace('&', '&') else: next_page_url = item.url #logger.debug('curr_page: ' + str(curr_page) + '/ last_page: ' + str(last_page) + '/ next_page_url: ' + next_page_url) #Empezamos el procesado de matches for scrapedlanguage, scrapedurl, scrapedtitle, year, scrapedcategory, scrapedquality in matches: title = scrapedtitle url = scrapedurl.replace('&', '&') title = title.replace("á", "a").replace("é", "e").replace( "í", "i").replace("ó", "o").replace("ú", "u").replace( "ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace( "ã", "a").replace("&etilde;", "e").replace( "ĩ", "i").replace("õ", "o").replace( "ũ", "u").replace("ñ", "ñ").replace( "’", "'").replace('&', '&') #cnt_title += 1 item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.category: del item_local.category if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.extra2 = True del item_local.extra2 item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color title_subs = [] #creamos una lista para guardar info importante item_local.language = [] #creamos lista para los idiomas item_local.quality = scrapedquality #iniciamos calidad item_local.thumbnail = '' item_local.url = url.replace('&', '&').replace( '.io/', sufix).replace('.com/', sufix) #guardamos la url final item_local.context = "['buscar_trailer']" item_local.contentType = "movie" #por defecto, son películas item_local.action = "findvideos" #Analizamos el formato de series if '/series' in scrapedurl or item_local.extra == 'series' or 'series' in scrapedcategory: item_local.extra = 'series' item_local.contentType = "tvshow" item_local.action = "episodios" item_local.season_colapse = True #Muestra las series agrupadas por temporadas #Detectamos idiomas if "1.png" in scrapedlanguage: item_local.language += ['CAST'] if "512.png" in scrapedlanguage or 'latino' in title.lower(): item_local.language += ['LAT'] if ("1.png" not in scrapedlanguage and "512.png" not in scrapedlanguage ) or "eng" in title.lower() or "sub" in title.lower(): item_local.language += ['VOSE'] if '-3d' in scrapedurl: title = title.replace('3D', '').replace('3d', '') item_local.quality += ' 3D' #Detectamos el año item_local.infoLabels['year'] = '-' if year: try: year = int(year) if year >= 1970 and year <= 2040: item_local.infoLabels["year"] = year except: pass #Detectamos info importante a guardar para después de TMDB if "extendida" in title.lower() or "extended" in title.lower( ) or "v.e." in title.lower() or "v e " in title.lower(): title_subs += ["[V. Extendida]"] title = title.replace("Version Extendida", "").replace( "(Version Extendida)", "").replace("V. Extendida", "").replace("VExtendida", "").replace( "V Extendida", "").replace("V.Extendida", "").replace( "V Extendida", "").replace("V.E.", "").replace("V E ", "") if scrapertools.find_single_match(title, '[m|M].*?serie'): title = re.sub(r'[m|M]iniserie', '', title) title_subs += ["Miniserie"] if scrapertools.find_single_match(title, '[s|S]aga'): title = re.sub(r'[s|S]aga', '', title) title_subs += ["Saga"] if scrapertools.find_single_match(title, '[c|C]olecc'): title = re.sub(r'[c|C]olecc...', '', title) title_subs += ["Colección"] #Empezamos a limpiar el título en varias pasadas patron = '\s?-?\s?(line)?\s?-\s?$' regex = re.compile(patron, re.I) title = regex.sub("", title) title = re.sub(r'\(\d{4}\s*?\)', '', title) title = re.sub(r'\[\d{4}\s*?\]', '', title) title = re.sub(r'[s|S]erie', '', title) title = re.sub(r'- $', '', title) title = re.sub(r'\d+[M|m|G|g][B|b]', '', title) #Limpiamos el título de la basura innecesaria title = re.sub( r'(?i)TV|Online|Spanish|Torrent|en Espa\xc3\xb1ol|Español|Latino|Subtitulado|Blurayrip|Bluray rip|\[.*?\]|R2 Pal|\xe3\x80\x90 Descargar Torrent \xe3\x80\x91|Completa|Temporada|Descargar|Torren|\(iso\)|\(dvd.*?\)|(?:\d+\s*)?\d{3,4}p.*?$|extended|(?:\d+\s*)?bdrip.*?$|\(.*?\).*?$|iso$|unrated|\[.*?$|\d{4}$', '', title) #Obtenemos temporada y episodio si se trata de Episodios if item_local.contentType == "episode": patron = '(\d+)[x|X](\d+)' try: item_local.contentSeason, item_local.contentEpisodeNumber = scrapertools.find_single_match( title, patron) except: item_local.contentSeason = 1 item_local.contentEpisodeNumber = 0 #Si son eisodios múltiples, lo extraemos patron1 = '\d+[x|X]\d+.?(?:y|Y|al|Al)?.?\d+[x|X](\d+)' epi_rango = scrapertools.find_single_match(title, patron1) if epi_rango: item_local.infoLabels[ 'episodio_titulo'] = 'al %s' % epi_rango title = re.sub(patron1, '', title) else: title = re.sub(patron, '', title) #Terminamos de limpiar el título title = re.sub(r'\??\s?\d*?\&.*', '', title) title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').strip().lower().title() item_local.from_title = title.strip().lower().title( ) #Guardamos esta etiqueta para posible desambiguación de título #Salvamos el título según el tipo de contenido if item_local.contentType == "movie": item_local.contentTitle = title else: item_local.contentSerieName = title.strip().lower().title() item_local.title = title.strip().lower().title() item_local.quality = item_local.quality.strip() #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Salvamos y borramos el número de temporadas porque TMDB a veces hace tonterias. Lo pasamos como serie completa if item_local.contentSeason and (item_local.contentType == "season" or item_local.contentType == "tvshow"): item_local.contentSeason_save = item_local.contentSeason del item_local.infoLabels['season'] #Ahora se filtra por idioma, si procede, y se pinta lo que vale if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len(itemlist) #Contador de líneas añadidas #logger.debug(item_local) #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page and last_page > 1: if last_page: title = '%s de %s' % (curr_page - 1, last_page) else: title = '%s' % curr_page - 1 itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page))) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados matches = [] #logger.debug(item) #Ahora tratamos los enlaces .torrent con las diferentes calidades for scrapedurl, scrapedserver in item.url_enlaces: #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = scrapedurl item_local.server = scrapedserver.lower() item_local.action = "play" #Buscamos tamaño en el archivo .torrent size = '' if item_local.server == 'torrent' and not size and not item_local.url.startswith('magnet:'): size = generictools.get_torrent_size(item_local.url) # Buscamos el tamaño en el .torrent desde la web if size: size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',') item_local.torrent_info = '%s, ' % size #Agregamos size if item_local.url.startswith('magnet:') and not 'Magnet' in item_local.torrent_info: item_local.torrent_info += ' Magnet' if item_local.torrent_info: item_local.torrent_info = item_local.torrent_info.strip().strip(',') if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info #Ahora pintamos lo enlaces item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][%s][/COLOR] ' %item_local.server.capitalize() \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) # Verificamos enlaces if item_local.server != 'torrent': if config.get_setting("hidepremium"): #Si no se aceptan servidore premium, se ignoran if not servertools.is_server_enabled(item_local.server): continue devuelve = servertools.findvideosbyserver(item_local.url, item_local.server) #existe el link ? if not devuelve: continue item_local.url = devuelve[0][1] item_local.alive = servertools.check_video_link(item_local.url, item_local.server, timeout=timeout) #activo el link ? if 'NO' in item_local.alive: continue else: if not size or 'Magnet' in size: item_local.alive = "??" #Calidad del link sin verificar elif 'ERROR' in size: item_local.alive = "no" #Calidad del link en error? continue else: item_local.alive = "ok" #Calidad del link verificada itemlist_t.append(item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting('filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link(itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len(itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb("next.png") #... pintamos todo con aviso itemlist.append(Item(channel=item.channel, url=host, title="[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) itemlist.extend(itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto matches = [] subtitles = [] item.category = categoria #logger.debug(item) if item.extra != 'episodios': #Bajamos los datos de la página data = '' patron = '<div class="secciones"><h1>[^<]+<\/h1><br\s*\/><br\s*\/><div class="fichimagen">\s*<img class="carat" src="([^"]+)"' try: data = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(item.url, timeout=timeout).data) #data = unicode(data, "iso-8859-1", errors="replace").encode("utf-8") except: pass if not data: logger.error( "ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log' )) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[ 1] #Restauramos matches de vídeos subtitles = item.emergency_urls[ 2] #Restauramos matches de subtítulos item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos if not item.armagedon: #Extraemos el thumb if not item.thumbnail: item.thumbnail = scrapertools.find_single_match( data, patron) #guardamos thumb si no existe #Extraemos quality, audio, year, country, size, scrapedlanguage patron = '<\/script><\/div><ul>(?:<li><label>Fecha de estreno <\/label>[^<]+<\/li>)?(?:<li><label>Genero <\/label>[^<]+<\/li>)?(?:<li><label>Calidad <\/label>([^<]+)<\/li>)?(?:<li><label>Audio <\/label>([^<]+)<\/li>)?(?:<li><label>Fecha <\/label>.*?(\d+)<\/li>)?(?:<li><label>Pais de Origen <\/label>([^<]+)<\/li>)?(?:<li><label>Tamaño <\/label>([^<]+)<\/li>)?(<li> Idioma[^<]+<img src=.*?<br \/><\/li>)?' try: quality = '' audio = '' year = '' country = '' size = '' scrapedlanguage = '' quality, audio, year, country, size, scrapedlanguage = scrapertools.find_single_match( data, patron) except: pass if quality: item.quality = quality if audio: item.quality += ' %s' % audio.strip() if not item.infoLabels['year'] and year: item.infoLabels['year'] = year if size: item.quality += ' [%s]' % size.replace('GB', 'G B').replace( 'Gb', 'G b').replace('MB', 'M B').replace( 'Mb', 'M b').replace('.', ',').strip() if size: item.title = re.sub( r'\s*\[\d+,?\d*?\s\w\s*[b|B]\]', '', item.title) #Quitamos size de título, si lo traía item.title += ' [%s]' % size.replace('GB', 'G B').replace( 'Gb', 'G b').replace('MB', 'M B').replace( 'Mb', 'M b').replace('.', ',').strip() language = [] matches_lang = re.compile('(\d+.png)', re.DOTALL).findall(scrapedlanguage) for lang in matches_lang: if "1.png" in lang and not 'CAST' in language: language += ['CAST'] if "512.png" in lang and not 'LAT' in language: language += ['LAT'] if ("1.png" not in lang and "512.png" not in lang) and not 'VOSE' in language: language += ['VOSE'] if language: item.language = language #Extraemos los enlaces .torrent #Modalidad de varios archivos patron = '<div class="fichadescargat"><\/div><div class="table-responsive"[^>]+>.*?<\/thead><tbody>(.*?)<\/tbody><\/table><\/div>' if scrapertools.find_single_match(data, patron): data_torrents = scrapertools.find_single_match(data, patron) patron = '<tr><td>.*?<\/td><td><a href="([^"]+)"[^>]+><[^>]+><\/a><\/td><\/tr>' #Modalidad de un archivo else: data_torrents = data patron = '<div class="fichasubtitulos">.*?<\/div><\/li><\/ul>.*?<a href="([^"]+)"' matches = re.compile(patron, re.DOTALL).findall(data_torrents) if not matches: #error logger.error( "ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web " + " / PATRON: " + patron + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log' )) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[ 1] #Restauramos matches de vídeos subtitles = item.emergency_urls[ 2] #Restauramos matches de subtítulos item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos else: #SERIES: ya viene con las urls data = item.url #inicio data por compatibilidad matches = [item.url] #inicio matches por compatibilidad #Extraemos las urls de los subtítulos (Platformtools usa item.subtitle como sub-titulo por defecto) patron = '<div class="fichasubtitulos">\s*<label class="fichsub">\s*<a href="([^"]+)">Subtitulos\s*<\/a>\s*<\/label>' if scrapertools.find_single_match(data, patron) or item.subtitle: if item.extra == 'episodios': #Si viene de Series, ya tengo la primera url subtitle = item.subtitle del item.subtitle else: subtitle = scrapertools.find_single_match(data, patron).replace( '&', '&').replace('.io/', sufix).replace('.com/', sufix) try: data_subtitle = re.sub( r"\n|\r|\t|\s{2}|(<!--.*?-->)", "", httptools.downloadpage(subtitle, timeout=timeout).data) except: pass if not data_subtitle: if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? matches = item.emergency_urls[ 1] #Restauramos matches de vídeos subtitles = item.emergency_urls[ 2] #Restauramos matches de subtítulos item.armagedon = True #Marcamos la situación como catastrófica else: patron = '<tbody>(<tr class="fichserietabla_b">.*?<\/tr>)<\/tbody>' #salvamos el bloque data_subtitle = scrapertools.find_single_match( data_subtitle, patron) patron = '<tr class="fichserietabla_b">.*?<a href="([^"]+)"' subtitles = re.compile(patron, re.DOTALL).findall( data_subtitle) #Creamos una lista con todos los sub-títulos if subtitles: item.subtitle = [] for subtitle in subtitles: subtitle = subtitle.replace('&', '&').replace( '.io/', sufix).replace('.com/', sufix) item.subtitle.append(subtitle) #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(subtitles) #logger.debug(data) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if item.videolibray_emergency_urls: item.emergency_urls = [] #Iniciamos emergency_urls item.emergency_urls.append( []) #Reservamos el espacio para los .torrents locales item.emergency_urls.append( matches) #Salvamnos matches de los vídeos... item.emergency_urls.append( subtitles) #Salvamnos matches de los subtítulos #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB if not item.videolibray_emergency_urls: item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent for scrapedurl in matches: #leemos los torrents con la diferentes calidades #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = scrapedurl.replace('&', '&').replace( '.io/', sufix).replace('.com/', sufix) if item.videolibray_emergency_urls: item.emergency_urls[0].append( scrapedurl) #guardamos la url y pasamos a la siguiente continue if item.emergency_urls and not item.videolibray_emergency_urls: item_local.torrent_alt = item.emergency_urls[0][ 0] #Guardamos la url del .Torrent ALTERNATIVA if item.armagedon: item_local.url = item.emergency_urls[0][ 0] #... ponemos la emergencia como primaria del item.emergency_urls[0][0] #Una vez tratado lo limpiamos #Buscamos si ya tiene tamaño, si no, los buscamos en el archivo .torrent size = scrapertools.find_single_match( item_local.quality, '\s*\[(\d+,?\d*?\s\w\s*[b|B])\]') if not size and not item.armagedon: size = generictools.get_torrent_size( scrapedurl) #Buscamos el tamaño en el .torrent if size: size = size.replace('GB', 'G B').replace('Gb', 'G b').replace( 'MB', 'M B').replace('Mb', 'M b') item_local.title = re.sub( r'\s*\[\d+,?\d*?\s\w\s*[b|B]\]', '', item_local.title) #Quitamos size de título, si lo traía item_local.title = '%s [%s]' % ( item_local.title, size) #Agregamos size al final del título item_local.quality = re.sub( r'\s*\[\d+,?\d*?\s\w\s*[b|B]\]', '', item_local.quality) #Quitamos size de calidad, si lo traía item_local.quality = '%s [%s]' % ( item_local.quality, size ) #Agregamos size al final de la calidad if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality #Ahora pintamos el link del Torrent item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % ( item_local.quality, str(item_local.language)) #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").replace(".", ",").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) if item.videolibray_emergency_urls: #Si ya hemos guardado todas las urls... return item #... nos vamos if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto post = None forced_proxy_opt = None referer = None if item.post: # Rescatamos el Post, si lo hay post = item.post if item.referer: referer = item.referer torrent_params = { 'url': item.url, 'torrents_path': None, 'local_torr': item.torrents_path, 'lookup': False, 'force': True, 'data_torrent': True, 'subtitles': True, 'file_list': True } #Bajamos los datos de la página if not item.matches: data, response, item, itemlist = generictools.downloadpage( item.url, timeout=timeout, canonical=canonical, post=post, referer=referer, forced_proxy_opt=forced_proxy_opt, s2=False, item=item, itemlist=[]) # Descargamos la página) if not data and not item.matches: logger.error( "ERROR 01: FINDVIDEOS: La Web no responde o la URL es erronea: " + item.url + " / DATA: " + data) itemlist.append(item.clone(action='', title=item.channel.capitalize() + \ ': ERROR 01: FINDVIDEOS:. La Web no responde o la URL es erronea. Si la Web está activa, reportar el error con el log', folder=False)) if item.emergency_urls and not item.videolibray_emergency_urls: # Hay urls de emergencia? link_torrent = item.emergency_urls[0][ 0] # Guardamos la url del .Torrent link_magnet = item.emergency_urls[1][ 0] # Guardamos la url del .Magnet item.armagedon = True # Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: # Si es llamado desde creación de Videoteca... return item # Devolvemos el Item de la llamada else: return itemlist # si no hay más datos, algo no funciona, pintamos lo que tenemos patron_t = '(?:<div\s*class="enlace_descarga"[^>]+>\s*<a\s*href=)?"([^"]+\.torrent)"' patron_m = '(?:<div\s*class="enlace_descarga"[^>]+>\s*<a\s*href=)?"(magnet:?[^"]+)"' if not item.armagedon: # Si es un proceso normal, seguimos data_links = data for x in range(2): link_torrent = scrapertools.find_single_match(data_links, patron_t) if link_torrent: link_torrent = urlparse.urljoin(host, link_torrent) link_torrent = link_torrent.replace( " ", "%20") # sustituimos espacios por %20, por si acaso #logger.info("link Torrent: " + link_torrent) link_magnet = scrapertools.find_single_match(data_links, patron_m) #logger.info("link Magnet: " + link_magnet) if not (link_torrent and link_magnet) and x == 0: data_links = generictools.identifying_links(data_links) #Si es un lookup para cargar las urls de emergencia en la Videoteca... if (link_torrent or link_magnet) and item.videolibray_emergency_urls: item.emergency_urls = [] item.emergency_urls.append([link_torrent ]) #Salvamos el enlace de .torrent item.emergency_urls.append([link_magnet ]) #Salvamos el enlace de .magnet return item #... y nos vamos #Añadimos el tamaño para todos size = scrapertools.find_single_match(item.quality, '\s\[(\d+,?\d*?\s\w\s*[b|B]s*)\]') if size: item.title = re.sub('\s\[\d+,?\d*?\s\w\s*[b|B]s*\]', '', item.title) #Quitamos size de título, si lo traía item.quality = re.sub( '\s\[\d+,?\d*?\s\w\s*[b|B]s*\]', '', item.quality) #Quitamos size de calidad, si lo traía if not link_torrent and not link_magnet: #error item = generictools.web_intervenida( item, data) #Verificamos que no haya sido clausurada if item.intervencion: #Sí ha sido clausurada judicialmente item, itemlist = generictools.post_tmdb_findvideos( item, itemlist) #Llamamos al método para el pintado del error else: logger.error( "ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web " + " / PATRON: " + patron_t + " / " + patron_m + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: El archivo Torrent no existe o ha cambiado la estructura de la Web. Verificar en la Web y reportar el error con el log', folder=False)) if item.emergency_urls and not item.videolibray_emergency_urls: #Hay urls de emergencia? link_torrent = item.emergency_urls[0][ 0] #Guardamos la url del .Torrent link_magnet = item.emergency_urls[1][ 0] #Guardamos la url del .Magnet item.armagedon = True #Marcamos la situación como catastrófica else: if item.videolibray_emergency_urls: #Si es llamado desde creación de Videoteca... return item #Devolvemos el Item de la llamada else: return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) if not size and not item.armagedon: torrent_params['url'] = link_torrent torrent_params = generictools.get_torrent_size( link_torrent, torrent_params=torrent_params, referer=host, item=item) # Tamaño en el .torrent size = torrent_params['size'] if torrent_params['torrents_path']: item.torrents_path = torrent_params['torrents_path'] if size: size = size.replace('GB', 'G·B').replace('Gb', 'G·b').replace('MB', 'M·B')\ .replace('Mb', 'M·b').replace('.', ',') #Ahora pintamos el link del Torrent, si lo hay if link_torrent: # Hay Torrent ? #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.torrent_info = "[Torrent] " item_local.torrent_info += '%s' % size #Agregamos size if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info.strip( ).strip(',') if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality item_local.url = link_torrent if item_local.url and item.emergency_urls and not item.armagedon: item_local.torrent_alt = item.emergency_urls[0][ 0] #Guardamos la url del .Torrent ALTERNATIVA item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][Torrent][/COLOR] ' \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) #Preparamos título de Torrent #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality) item_local.quality = item_local.quality.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() if not size or 'Magnet' in size: item_local.alive = "??" # Calidad del link sin verificar elif 'ERROR' in size and 'Pincha' in size: item_local.alive = "ok" # link en error, CF challenge, Chrome disponible elif 'ERROR' in size and 'Introduce' in size: item_local.alive = "??" # link en error, CF challenge, ruta de descarga no disponible item_local.channel = 'setting' item_local.action = 'setting_torrent' item_local.unify = False item_local.folder = False item_local.item_org = item.tourl() elif 'ERROR' in size: item_local.alive = "no" # Calidad del link en error, CF challenge? else: item_local.alive = "ok" # Calidad del link verificada if item_local.channel != 'setting': item_local.action = "play" # Visualizar vídeo item_local.server = "torrent" # Seridor Torrent itemlist_t.append( item_local.clone()) # Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: # Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado #Ahora pintamos el link del Magnet, si lo hay itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if link_magnet: # Hay Magnet ? #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.torrent_info = "[Magnet] " item_local.torrent_info += '%s' % size #Agregamos size if not item.unify: item_local.torrent_info = '[%s]' % item_local.torrent_info.strip( ).strip(',') if item.armagedon: #Si es catastrófico, lo marcamos item_local.quality = '[/COLOR][COLOR hotpink][E] [COLOR limegreen]%s' % item_local.quality item_local.url = link_magnet item_local.title = '[[COLOR yellow]?[/COLOR]] [COLOR yellow][Torrent][/COLOR] ' \ + '[COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR] %s' % \ (item_local.quality, str(item_local.language), \ item_local.torrent_info) #Preparamos título de Magnet item_local.title = re.sub(r'\s\[COLOR \w+\]\[\[?\]?\]\[\/COLOR\]', '', item_local.title) #Quitamos etiquetas vacías item_local.title = re.sub(r'\s\[COLOR \w+\]\[\/COLOR\]', '', item_local.title) #Quitamos colores vacíos item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Seridor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador, folder=False)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado #logger.debug("TORRENT: " + link_torrent + "MAGNET: " + link_magnet + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / tamaño: " + size + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): # Listado principal y de búsquedas logger.info() itemlist = [] item.category = categoria thumb_pelis = get_thumb("channels_movie.png") thumb_series = get_thumb("channels_tvshow.png") #logger.debug(item) curr_page = 1 # Página inicial last_page = 99999 # Última página inicial last_page_print = 1 # Última página inicial, para píe de página page_factor = 1.0 # Factor de conversión de pag. web a pag. Alfa if item.curr_page: curr_page = int( item.curr_page) # Si viene de una pasada anterior, lo usamos del item.curr_page # ... y lo borramos if item.last_page: last_page = int( item.last_page) # Si viene de una pasada anterior, lo usamos del item.last_page # ... y lo borramos if item.page_factor: page_factor = float( item.page_factor) # Si viene de una pasada anterior, lo usamos del item.page_factor # ... y lo borramos if item.last_page_print: last_page_print = item.last_page_print # Si viene de una pasada anterior, lo usamos del item.last_page_print # ... y lo borramos cnt_tot = 30 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist if item.cnt_tot_match: cnt_tot_match = float( item.cnt_tot_match ) # restauramos el contador TOTAL de líneas procesadas de matches del item.cnt_tot_match else: cnt_tot_match = 0.0 # Contador TOTAL de líneas procesadas de matches inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout * 2 # Timeout para descargas if item.extra == 'search' and item.extra2 == 'episodios': # Si viene de episodio que quitan los límites cnt_tot = 999 fin = inicio + 30 #Sistema de paginado para evitar páginas vacías o semi-vacías en casos de búsquedas con series con muchos episodios title_lista = [ ] # Guarda la lista de series que ya están en Itemlist, para no duplicar lineas if item.title_lista: # Si viene de una pasada anterior, la lista ya estará guardada title_lista.extend( item.title_lista) # Se usa la lista de páginas anteriores en Item del item.title_lista # ... limpiamos matches = [] if not item.extra2: # Si viene de Catálogo o de Alfabeto item.extra2 = '' post = None headers = None forced_proxy_opt = None if item.post: forced_proxy_opt = None if item.post or item.post is None: # Rescatamos el Post, si lo hay post = item.post del item.post if item.headers or item.headers is None: # Rescatamos el Headers, si lo hay headers = item.headers del item.headers next_page_url = item.url # Máximo num. de líneas permitidas por TMDB. Máx de 5 segundos por Itemlist para no degradar el rendimiento while (cnt_title < cnt_tot and curr_page <= last_page and fin > time.time()) or item.matches: # Descarga la página data = '' cnt_match = 0 # Contador de líneas procesadas de matches if not item.matches: # si no viene de una pasada anterior, descargamos data, response, item, itemlist = generictools.downloadpage( next_page_url, canonical=canonical, headers=headers, timeout=timeout_search, post=post, s2=False, item=item, itemlist=itemlist) # Descargamos la página) # Verificamos si ha cambiado el Host if response.host: next_page_url = response.url_new # Verificamos si se ha cargado una página correcta curr_page += 1 # Apunto ya a la página siguiente if not data or not response.sucess: # Si la web está caída salimos sin dar error if len(itemlist) > 1: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist # Si no hay nada más, salimos directamente headers = {'referer': next_page_url} #Patrón para búsquedas, pelis y series patron = '<div\s*class="item hitem">\s*<a\s*href="([^"]+)">.*?' patron += '(?:<div\s*class="nota">\s*(.*?)\s*<\/div>)?\s*<img[^>]*src="([^"]+)"' patron += '.*?<div\s*class="titulo">\s*<span>\s*([^<]*)<\/span>' if not item.matches: # De pasada anterior? matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches del item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) if not matches and item.extra != 'search' and not item.extra2: #error logger.error( "ERROR 02: LISTADO: Ha cambiado la estructura de la Web " + " / PATRON: " + patron + " / DATA: " + data) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: LISTADO: Ha cambiado la estructura de la Web. ' + 'Reportar el error con el log')) break #si no hay más datos, algo no funciona, pintamos lo que tenemos if not matches and item.extra == 'search': #búsqueda vacía if len(itemlist) > 0: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist #Salimos # Buscamos la próxima página next_page_url = re.sub(r'page\/(\d+)', 'page/%s' % str(curr_page), item.url) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page)) # Buscamos la última página if last_page == 99999: #Si es el valor inicial, buscamos patron_last = 'Last\s*Page"\s*href="[^"]+\/(\d*)\/"' if not scrapertools.find_single_match(data, patron_last): patron_last = 'href="[^"]+">(\d+)<\/a>(?:<span[^<]*<\/span>)?\s*<a[^>]*aria-label="Next\s*Page"' try: last_page = int( scrapertools.find_single_match(data, patron_last)) page_factor = float(len(matches)) / float(cnt_tot) except: #Si no lo encuentra, lo ponemos a 999 last_page = 1 last_page_print = int((float(len(matches)) / float(cnt_tot)) + 0.999999) #logger.debug('curr_page: ' + str(curr_page) + ' / last_page: ' + str(last_page)) #Empezamos el procesado de matches for scrapedurl, scrapedlang, scrapedthumb, scrapedtitle in matches: cnt_match += 1 title = scrapedtitle title = scrapertools.remove_htmltags(title).rstrip( '.') # Removemos Tags del título url = scrapedurl title_subs = [] #creamos una lista para guardar info importante # Slugify, pero más light title = title.replace("á", "a").replace("é", "e").replace("í", "i")\ .replace("ó", "o").replace("ú", "u").replace("ü", "u")\ .replace("�", "ñ").replace("ñ", "ñ") title = scrapertools.decode_utf8_error(title) cnt_title += 1 # Incrementamos el contador de entradas válidas item_local = item.clone() #Creamos copia de Item para trabajar if item_local.tipo: #... y limpiamos del item_local.tipo if item_local.totalItems: del item_local.totalItems if item_local.intervencion: del item_local.intervencion if item_local.viewmode: del item_local.viewmode item_local.extra2 = True del item_local.extra2 item_local.text_bold = True del item_local.text_bold item_local.text_color = True del item_local.text_color item_local.headers = headers # Tratamos los idiomas if scrapedlang: item_local.language = [] langs = scrapedlang.split('>') logger.error(langs) for lang in langs: if not lang: continue if 'espanol' in lang: item_local.language += ['CAST'] elif 'latin' in lang: item_local.language += ['LAT'] elif 'english' in lang or 'ingles' in lang: item_local.language += ['VO'] else: item_local.language += ['OTHER'] if not item_local.language: item_local.language = ['CAST'] # [CAST] por defecto if not item_local.quality: item_local.quality = 'DVDR' # DVDR por defecto item_local.thumbnail = urlparse.urljoin( host, scrapedthumb) # iniciamos thumbnail item_local.url = urlparse.urljoin(host, url) # guardamos la url final item_local.context = "['buscar_trailer']" # ... y el contexto # Guardamos los formatos para películas item_local.contentType = "movie" item_local.action = "findvideos" title = re.sub( r'(?i)TV|Online|(4k-hdr)|(fullbluray)|4k| - 4k|(3d)|miniserie|ciclo\s*[^-|–]+[-|–]\s*', '', title).strip() item_local.quality = re.sub( r'(?i)proper|unrated|directors|cut|repack|internal|real|extended|masted|docu|super|duper|amzn|uncensored|hulu', '', item_local.quality).strip() # Analizamos el año. Si no está claro ponemos '-' item_local.infoLabels["year"] = '-' # Terminamos de limpiar el título title = re.sub(r'[\(|\[]\s+[\)|\]]', '', title) title = title.replace('()', '').replace('[]', '').replace( '[4K]', '').replace('(4K)', '').strip().lower().title() title = title.strip().lower().title() item_local.from_title = title #Guardamos esta etiqueta para posible desambiguación de título item_local.contentTitle = title item_local.title = title #Guarda la variable temporal que almacena la info adicional del título a ser restaurada después de TMDB item_local.title_subs = title_subs #Ahora se filtra por idioma, si procede, y se pinta lo que vale if filter_languages > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len( itemlist) # Recalculamos los items después del filtrado if cnt_title >= cnt_tot and ( len(matches) - cnt_match ) + cnt_title > cnt_tot * 1.3: #Contador de líneas añadidas break #logger.debug(item_local) matches = matches[cnt_match:] # Salvamos la entradas no procesadas cnt_tot_match += cnt_match # Calcular el num. total de items mostrados #Pasamos a TMDB la lista completa Itemlist tmdb.set_infoLabels(itemlist, __modo_grafico__, idioma_busqueda=idioma_busqueda) #Llamamos al método para el maquillaje de los títulos obtenidos desde TMDB item, itemlist = generictools.post_tmdb_listado(item, itemlist) # Si es necesario añadir paginacion if curr_page <= last_page or len(matches) > 0: curr_page_print = int(cnt_tot_match / float(cnt_tot)) if curr_page_print < 1: curr_page_print = 1 if last_page: if last_page > 1: last_page_print = int((last_page * page_factor) + 0.999999) title = '%s de %s' % (curr_page_print, last_page_print) else: title = '%s' % curr_page_print itemlist.append( Item(channel=item.channel, action="listado", title=">> Página siguiente " + title, title_lista=title_lista, url=next_page_url, extra=item.extra, extra2=item.extra2, last_page=str(last_page), curr_page=str(curr_page), page_factor=str(page_factor), cnt_tot_match=str(cnt_tot_match), matches=matches, last_page_print=last_page_print, post=post, headers=headers)) return itemlist
def findvideos(item): logger.info() itemlist = [] itemlist_t = [] #Itemlist total de enlaces itemlist_f = [] #Itemlist de enlaces filtrados if not item.language: item.language = ['CAST'] #Castellano por defecto matches = [] item.category = categoria item.extra2 = 'xyz' del item.extra2 #logger.debug(item) matches = item.url if not matches: #error logger.error( "ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web: " + item) itemlist.append( item.clone( action='', title=item.channel.capitalize() + ': ERROR 02: FINDVIDEOS: No hay enlaces o ha cambiado la estructura de la Web. Verificar en la Web esto último y reportar el error con el log' )) return itemlist #si no hay más datos, algo no funciona, pintamos lo que tenemos #logger.debug(matches) #Llamamos al método para crear el título general del vídeo, con toda la información obtenida de TMDB item, itemlist = generictools.post_tmdb_findvideos(item, itemlist) #Ahora tratamos los enlaces .torrent for scrapedurl, quality in matches: #leemos los magnets con la diferentes calidades #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() item_local.url = scrapedurl #Añadimos la calidad y copiamos la duración item_local.quality = quality if scrapertools.find_single_match(item.quality, '(\[\d+:\d+\ h])'): item_local.quality += ' [/COLOR][COLOR white]%s' % scrapertools.find_single_match( item.quality, '(\[\d+:\d+\ h])') #Ahora pintamos el link del Torrent item_local.title = '[COLOR yellow][?][/COLOR] [COLOR yellow][Torrent][/COLOR] [COLOR limegreen][%s][/COLOR] [COLOR red]%s[/COLOR]' % ( item_local.quality, str(item_local.language)) #Preparamos título y calidad, quitamos etiquetas vacías item_local.title = re.sub(r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.title) item_local.title = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.title) item_local.title = item_local.title.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.quality = re.sub( r'\s?\[COLOR \w+\]\[\[?\s?\]?\]\[\/COLOR\]', '', item_local.quality) item_local.quality = re.sub(r'\s?\[COLOR \w+\]\s?\[\/COLOR\]', '', item_local.quality).strip() item_local.quality = item_local.quality.replace("--", "").replace( "[]", "").replace("()", "").replace("(/)", "").replace("[/]", "").strip() item_local.alive = "??" #Calidad del link sin verificar item_local.action = "play" #Visualizar vídeo item_local.server = "torrent" #Servidor Torrent itemlist_t.append( item_local.clone()) #Pintar pantalla, si no se filtran idiomas # Requerido para FilterTools if config.get_setting( 'filter_languages', channel) > 0: #Si hay idioma seleccionado, se filtra itemlist_f = filtertools.get_link( itemlist_f, item_local, list_language) #Pintar pantalla, si no está vacío #logger.debug("TORRENT: " + scrapedurl + " / title gen/torr: " + item.title + " / " + item_local.title + " / calidad: " + item_local.quality + " / content: " + item_local.contentTitle + " / " + item_local.contentSerieName) #logger.debug(item_local) if len(itemlist_f) > 0: #Si hay entradas filtradas... itemlist.extend(itemlist_f) #Pintamos pantalla filtrada else: if config.get_setting('filter_languages', channel) > 0 and len( itemlist_t) > 0: #Si no hay entradas filtradas ... thumb_separador = get_thumb( "next.png") #... pintamos todo con aviso itemlist.append( Item( channel=item.channel, url=host, title= "[COLOR red][B]NO hay elementos con el idioma seleccionado[/B][/COLOR]", thumbnail=thumb_separador)) itemlist.extend( itemlist_t) #Pintar pantalla con todo si no hay filtrado # Requerido para AutoPlay autoplay.start(itemlist, item) #Lanzamos Autoplay return itemlist
def listado(item): # Listado principal logger.info() itemlist = [] matches = [] item.category = categoria #logger.debug(item) cnt_tot = 30 # Poner el num. máximo de items por página cnt_title = 0 # Contador de líneas insertadas en Itemlist cnt_offset = 0 # offset para cnt_title en searchs curr_page = 1 last_page = 999 inicio = time.time( ) # Controlaremos que el proceso no exceda de un tiempo razonable fin = inicio + 5 # Después de este tiempo pintamos (segundos) timeout_search = timeout * 2 # Timeout para descargas next_page_url = item.url # Máximo num. de líneas permitidas por TMDB. Máx de 5 segundos por Itemlist para no degradar el rendimiento while (next_page_url and cnt_title < cnt_tot and curr_page <= last_page and fin > time.time()) or item.matches: # Descarga la página data = '' cnt_match = 0 # Contador de líneas procesadas de matches patron = 'data-column-clickable="([^"]+")[^>]*data-id="([^"]+)".*?<h4\s*' patron += 'class="elementor-heading-title[^>]+>\s*<span1[^>]*>\s*([^<]*)' patron += '<\/span1>([^<]*)<\/h4>.*?<h5\s*class="elementor-image-box-title">\s*' patron += '([^<]+)<\/h5>\s*(?:<p\s*class="elementor-image-box-description">\s*([^<]+)<\/p>)?' if not item.matches: # si no viene de una pasada anterior, descargamos data, success, code, item, itemlist = generictools.downloadpage( next_page_url, timeout=timeout_search, s2=False, item=item, itemlist=itemlist) # Descargamos la página) # Verificamos si se ha cargado una página correcta curr_page += 1 # Apunto ya a la página siguiente if not data or not success: # Si la web está caída salimos sin dar error if len(itemlist) > 1: # Si hay algo que pintar lo pintamos last_page = 0 break return itemlist # Si no hay nada más, salimos directamente # Comprobar si hay más páginas patron_page = '<a\s*class="page-numbers[^"]+"\s*href="([^"]+)">Siguiente' if scrapertools.find_single_match(data, patron_page): next_page_url = scrapertools.find_single_match(data, patron_page) else: next_page_url = '' if not item.matches: # De pasada anterior? matches = re.compile(patron, re.DOTALL).findall(data) else: matches = item.matches del item.matches #logger.debug("PATRON: " + patron) #logger.debug(matches) #logger.debug(data) # Iniciamos el Plot y marcamos TMDB como no usable item.contentPlot = '[COLOR gold][B]%s[/B][/COLOR]%s\n\n' % ( item.title, item.channel_sufix) #iniciamos el Plot con el Deporte item.from_title = '%s - ' % item.title item.infoLabels['tmdb_id'] = null #Empezamos el procesado de matches for scrapedurl, scrapedthumb, scrapedtitle1, scrapedtitle2, date1, date2 in matches: #Generamos una copia de Item para trabajar sobre ella item_local = item.clone() cnt_match += 1 title = '%s%s: %s %s' % (scrapedtitle1, scrapedtitle2, date1, date2) title = scrapertools.remove_htmltags(title).rstrip( '.') # Removemos Tags del título title = title.replace("á", "a").replace("é", "e").replace("í", "i")\ .replace("ó", "o").replace("ú", "u").replace("ü", "u")\ .replace("�", "ñ").replace("ñ", "ñ").replace("’", "'")\ .replace("&", "&") cnt_title += 1 # Incrementamos el contador de entradas válidas # Procesamos idiomas item_local.language = [] #creamos lista para los idiomas if not item_local.language: item_local.language = ['CAST'] # [CAST] por defecto # Procesamos Calidad if not item_local.quality: item_local.quality = 'HDTV' patron_thumb = '\.elementor-element\.elementor-element-%s\s*>.*?url\(([^\)]+)\)' % scrapedthumb item_local.thumbnail = scrapertools.find_single_match( data, patron_thumb) #iniciamos thumbnail item_local.contentThumbnail = item_local.thumbnail #iniciamos thumbnail item_local.infoLabels[ 'fanart'] = item_local.thumbnail #iniciamos Fanart item_local.url = urlparse.urljoin(host, scrapedurl) #iniciamos la url item_local.url_tvshow = item_local.url # Guardamos los formatos para películas item_local.contentType = event item_local.action = "episodios" year = scrapertools.find_single_match(title, '\d{4}') if not year: import datetime year = datetime.datetime.now().year if year: item_local.infoLabels['year'] = int(year) item_local.infoLabels['aired'] = str(year) title = re.sub( r'(?i)TV|Online|(4k-hdr)|(fullbluray)|4k| - 4k|(3d)|miniserie|\d{4}', '', title).strip() item_local.title = title.strip().lower().title() item_local.contentTitle = item_local.title item_local.from_title += item_local.title #Ahora se filtra por idioma, si procede, y se pinta lo que vale if filter_languages > 0: #Si hay idioma seleccionado, se filtra itemlist = filtertools.get_link(itemlist, item_local, list_language) else: itemlist.append(item_local.clone()) #Si no, pintar pantalla cnt_title = len( itemlist ) - cnt_offset # Recalculamos los items después del filtrado if cnt_title >= cnt_tot and ( len(matches) - cnt_match ) + cnt_title > cnt_tot * 1.3: #Contador de líneas añadidas break #logger.debug(item_local) matches = matches[cnt_match:] # Salvamos la entradas no procesadas return itemlist