Example #1
0
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
Example #2
0
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(
                        "&atilde;", "a").replace("&etilde;", "e").replace(
                            "&itilde;", "i").replace("&otilde;", "o").replace(
                                "&utilde;",
                                "u").replace("&ntilde;",
                                             "ñ").replace("&#8217;", "'")

            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
Example #3
0
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
Example #4
0
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}|(<!--.*?-->)|&nbsp;", "",
                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}|(<!--.*?-->)|&nbsp;", "",
                    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(
                        "&atilde;", "a").replace("&etilde;", "e").replace(
                            "&itilde;", "i").replace("&otilde;", "o").replace(
                                "&utilde;",
                                "u").replace("&ntilde;",
                                             "ñ").replace("&#8217;", "'")

            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
Example #5
0
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}|(<!--.*?-->)|&nbsp;", "",
                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*>(?:&raquo;)?(?:\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('&#038;', '&')
        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('&#038;', '&')
            title = title.replace("á", "a").replace("é", "e").replace(
                "í", "i").replace("ó", "o").replace("ú", "u").replace(
                    "ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace(
                        "&atilde;", "a").replace("&etilde;", "e").replace(
                            "&itilde;", "i").replace("&otilde;", "o").replace(
                                "&utilde;",
                                "u").replace("&ntilde;", "ñ").replace(
                                    "&#8217;", "'").replace('&#038;', '&')

            #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('&#038;', '&').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
Example #6
0
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
Example #7
0
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 + 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

    #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.45 and curr_page <= last_page and fin > time.time(
    ):

        # Descarga la página
        data = ''
        try:
            data = re.sub(
                r"\n|\r|\t|\s{2}|(<!--.*?-->)|&nbsp;", "",
                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

        #Patrón para todo, menos para Series completas, incluido búsquedas en cualquier caso
        patron = '<tr><td(?: class="[^"]+")?><a href="([^"]+)".?title="([^"]+)".*?<\/a><\/td><td(?: class="[^"]+")?>(?:<a href="[^"]+">)?(.*?)(?:<\/a>)?<\/td><td(?: class="[^"]+")?>.*?<\/td><td(?: class="[^"]+")?>(.*?)<\/td><\/tr>'

        #Si son series completas, ponemos un patrón especializado
        if item.extra == 'series':
            patron = '<div class="[^"]+"><p class="[^"]+"><a href="([^"]+)".?title="([^"]+)"><img src="([^"]+)".*?<a href=\'[^\']+\'.?title="([^"]+)".*?<\/p><\/div>'

        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_next = "<ul class=\"pagination\">.*?\(current\).*?href='([^']+)'>(\d+)<\/a><\/li>"
        #patron_last = "<ul class=\"pagination\">.*?\(current\).*?href='[^']+'>\d+<\/a><\/li>.*?href='[^']+\/(\d+)\/(?:\?s=[^']+)?'><span aria-hidden='[^']+'>&\w+;<\/span><\/a><\/li><\/ul><\/nav><\/div><\/div><\/div>"
        patron_last = "<ul class=\"pagination\">.*?\(current\).*?href='[^']+'>\d+<\/a><\/li>.*?href='[^']+\/(\d+)\/(?:\?[^']+)?'>(?:\d+)?(?:<span aria-hidden='[^']+'>&\w+;<\/span>)?<\/a><\/li><\/ul><\/nav><\/div><\/div><\/div>"

        try:
            next_page_url, next_page = scrapertools.find_single_match(
                data, patron_next)
            next_page = int(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
            try:
                last_page = int(
                    scrapertools.find_single_match(
                        data, 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 scrapedurl, scrapedtitle, cat_ppal, size in matches:
            if "/programas" in scrapedurl or "/otros" in scrapedurl:
                continue

            title = scrapedtitle
            url = scrapedurl
            title = title.replace("á", "a").replace("é", "e").replace(
                "í", "i").replace("ó", "o").replace("ú", "u").replace(
                    "ü", "u").replace("�", "ñ").replace("ñ", "ñ").replace(
                        "&atilde;", "a").replace("&etilde;", "e").replace(
                            "&itilde;", "i").replace("&otilde;", "o").replace(
                                "&utilde;",
                                "u").replace("&ntilde;",
                                             "ñ").replace("&#8217;", "'")
            extra = item.extra

            #Si es una búsqueda, convierte los episodios en Series completas, aptas para la Videoteca
            if extra == 'search' and '/series' in scrapedurl and not "Temp" in title and not "emporada" in title:
                if scrapedurl in title_lista:  #Si ya hemos procesado la serie, pasamos de los episodios adicionales
                    continue

                # Descarga la página del episodio, buscando el enlace a la serie completa
                data_serie = ''
                try:
                    data_serie = re.sub(
                        r"\n|\r|\t|\s{2}|(<!--.*?-->)|&nbsp;", "",
                        httptools.downloadpage(scrapedurl,
                                               timeout=timeout).data)
                    data = unicode(data, "utf-8",
                                   errors="replace").encode("utf-8")
                except:
                    pass

                if not data_serie:  #Si la web está caída salimos sin dar error. Pintamos el episodio
                    logger.error(
                        "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: "
                        + scrapedurl + " / SERIE: " + scrapedurl)
                else:
                    patron_serie = '<div id="where_i_am">.*?<a href="[^"]+">.*?<\/a>.*?<a href="([^"]+)">'
                    url = scrapertools.find_single_match(
                        data_serie,
                        patron_serie)  #buscamos la url de la serie completa
                    if url:
                        url = host + url
                        extra = 'series'  #es una serie completa
                        title_lista += [
                            scrapedurl
                        ]  #la añadimos a la lista de series completas procesadas
                        title = scrapedurl  #salvamos el título de la serie completa
                    else:
                        url = scrapedurl  #No se encuentra la Serie, se trata como Episodio suelto

            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.post_num:
                del item_local.post_num
            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
            if item_local.url_plus:
                del item_local.url_plus

            title_subs = []  #creamos una lista para guardar info importante
            item_local.language = []  #creamos lista para los idiomas
            item_local.quality = ''  #iniciamos calidad
            quality_alt = ''
            if 'series' in cat_ppal or extra == 'series':
                item_local.thumbnail = cat_ppal  #si son series, contiene el thumb
            else:
                quality_alt = scrapedurl.lower().strip(
                )  #si no son series, contiene la calidad
                item_local.thumbnail = ''  #guardamos el thumb
            item_local.extra = extra  #guardamos el extra procesado
            item_local.url = url  #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 '/peliculas/' in scrapedurl or item_local.extra == 'Películas':
                item_local.quality = 'HDRip '
            elif '/peliculas-hd' in scrapedurl or item_local.extra == 'Películas HD':
                item_local.quality = 'HD '
            elif '/peliculas-dvdr' in scrapedurl or item_local.extra == 'Películas DVDR':
                item_local.quality = 'DVDR '
            elif 'subtituladas' in cat_ppal or item_local.extra == 'VOSE' or 'vose' in title.lower(
            ):
                item_local.language += ['VOSE']
            elif 'Version Original' in cat_ppal or item_local.extra == 'VO' or 'vo' in title.lower(
            ):
                item_local.language += ['VO']

            #Analizamos los formatos de series, temporadas y episodios
            elif '/series' in scrapedurl or item_local.extra == 'series':
                item_local.contentType = "tvshow"
                item_local.action = "episodios"
                item_local.season_colapse = True  #Muestra las series agrupadas por temporadas
            elif item_local.extra == 'episodios':
                item_local.contentType = "episode"
                item_local.extra = "episodios"
                if "Temp" in title or "emporada" in title:
                    try:
                        item_local.contentSeason = int(
                            scrapertools.find_single_match(
                                title, '[t|T]emp.*?(\d+)'))
                    except:
                        item_local.contentSeason = 1
                    title = re.sub(r'[t|T]emp.*?\d+', '', title)
                    title_subs += ["Temporada"]
                    item_local.contentType = "season"
                    item_local.extra = "season"

            if item_local.contentType == "movie":  #para las peliculas ponemos el mismo extra
                item_local.extra = "peliculas"

            #Detectamos idiomas
            if "latino" in scrapedurl.lower() or "latino" in title.lower():
                item_local.language += ['LAT']
            elif "vose" in scrapedurl.lower() or "vos" in scrapedurl.lower(
            ) or "vose" in title.lower() or "vos" in title.lower():
                item_local.language += ['VOSE']

            if item_local.language == []:
                item_local.language = ['CAST']

            #Detectamos el año
            patron = '(\d{4})\s*?(?:\)|\])?$'
            item_local.infoLabels["year"] = '-'
            year = ''
            year = scrapertools.find_single_match(title, patron)
            if year:
                title_alt = re.sub(patron, "", title)
                title_alt = title_alt.strip()
                if title_alt:
                    title = title_alt
                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 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 = 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", "").replace(
                                    "LATINO",
                                    "").replace("Spanish", "").replace(
                                        "Trailer", "").replace("Audio", "")
            title = title.replace("HDTV-Screener", "").replace(
                "DVDSCR",
                "").replace("TS ALTA", "").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(" 480p", "").replace(
                            " 480P", "").replace(
                                " 720p", "").replace(
                                    " 720P", "").replace(" 1080p", "").replace(
                                        " 1080P",
                                        ""
                                    ).replace(
                                        "DVDRip", ""
                                    ).replace(
                                        " Dvd",
                                        "").replace(
                                            " DVD",
                                            "").replace(
                                                " V.O",
                                                ""
                                            ).replace(" Unrated", "").replace(
                                                " UNRATED",
                                                ""
                                            ).replace(" unrated", "").replace(
                                                "screener",
                                                ""
                                            ).replace(
                                                "TS-SCREENER", ""
                                            ).replace(
                                                "TSScreener", ""
                                            ).replace(
                                                "HQ",
                                                ""
                                            ).replace(
                                                "AC3 5.1", ""
                                            ).replace("Telesync", "").replace(
                                                "Line Dubbed", ""
                                            ).replace(
                                                "line Dubbed", ""
                                            ).replace("LineDuB", "").replace(
                                                "Line",
                                                ""
                                            ).replace(
                                                "XviD",
                                                ""
                                            ).replace(
                                                "xvid",
                                                ""
                                            ).replace(
                                                "XVID",
                                                ""
                                            ).replace(
                                                "Mic Dubbed", "").replace(
                                                    "HD",
                                                    ""
                                                ).replace(
                                                    "V2",
                                                    ""
                                                ).replace("CAM", "").replace(
                                                    "VHS.SCR", ""
                                                ).replace(
                                                    "Dvd5",
                                                    ""
                                                ).replace(
                                                    "DVD5",
                                                    ""
                                                ).replace("Iso", "").replace(
                                                    "ISO", "").replace(
                                                        "Reparado",
                                                        "").replace(
                                                            "reparado",
                                                            "").replace(
                                                                "DVD9",
                                                                "").replace(
                                                                    "Dvd9", "")

            #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()

            if item_local.contentType == "episode":
                item_local.title = '%sx%s ' % (
                    str(item_local.contentSeason),
                    str(item_local.contentEpisodeNumber).zfill(2))
                item_local.extra3 = 'completa'
            else:
                item_local.title = title.strip().lower().title()

            if scrapertools.find_single_match(size,
                                              '\d+.\d+\s?[g|G|m|M][b|B]'):
                size = size.replace('b', ' B').replace('B', ' B').replace(
                    'b', 'B').replace('g', 'G').replace('m',
                                                        'M').replace('.', ',')
                item_local.quality += '[%s]' % size

            #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']

            itemlist.append(item_local.clone())  #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 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
Example #8
0
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}|(<!--.*?-->)|&nbsp;", "",
                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(
                        "&atilde;", "a").replace("&etilde;", "e").replace(
                            "&itilde;", "i").replace("&otilde;", "o").replace(
                                "&utilde;",
                                "u").replace("&ntilde;",
                                             "ñ").replace("&#8217;", "'")

            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
Example #9
0
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
Example #10
0
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("&#8217;", "'")\
                    .replace("&amp;", "&")

            # 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
Example #11
0
def listado(item):
    logger.info()
    itemlist = []

    # Descarga la página
    data = ''
    try:
        data = re.sub(r"\n|\r|\t|\s{2}|(<!--.*?-->)", "",
                      httptools.downloadpage(item.url).data)
    except:
        pass

    if not data and item.extra != "año":  #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
    elif not data and item.extra == "año":  #cuando no hay datos para un año, da error.  Tratamos de evitar el error
        return itemlist

    patron = '<div class="browse-movie-wrap col-xs-10 col-sm-4 col-md-5 col-lg-4"><a href="([^"]+)".*?src="([^"]+)".*?alt="([^"]+)".*?rel="tag">([^"]+)<\/a>\s?<\/div><div class="[^"]+">(.*?)<\/div><\/div><\/div>'
    #data = scrapertools.find_single_match(data, patron)
    matches = re.compile(patron, re.DOTALL).findall(data)
    if not matches and not '<ul class="tsc_pagination tsc_pagination' 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'
            ))
        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, scrapedthumbnail, scrapedtitle, scrapedyear, scrapedqualities in matches:
        item_local = item.clone()  #Creamos copia de Item para trabajar
        title_subs = []

        title = re.sub('\r\n', '', scrapedtitle).decode('utf8').strip()
        item_local.url = scrapedurl
        item_local.thumbnail = scrapedthumbnail

        scrapedtorrent = ''
        if scrapedqualities:
            patron_quality = '<a href="([^"]+)"\s?rel="[^"]+"\s?title="[^"]+">(.*?)<\/a>'
            matches_quality = re.compile(patron_quality,
                                         re.DOTALL).findall(scrapedqualities)
            quality = ''

            for scrapedtorrent, scrapedquality in matches_quality:
                quality_inter = scrapedquality
                quality_inter = re.sub('HDr$', 'HDrip', quality_inter)
                quality_inter = re.sub('720$', '720p', quality_inter)
                quality_inter = re.sub('1080$', '1080p', quality_inter)
                if quality:
                    quality += ', %s' % quality_inter
                else:
                    quality = quality_inter
            if quality:
                item_local.quality = quality

        item_local.language = [
        ]  #Verificamos el idioma por si encontramos algo
        if "latino" in scrapedtorrent.lower(
        ) or "latino" in item.url or "latino" in title.lower():
            item_local.language += ["LAT"]
        if "ingles" in scrapedtorrent.lower(
        ) or "ingles" in item.url or "vose" in scrapedurl or "vose" in item.url:
            if "VOSE" in scrapedtorrent.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 scrapedtorrent.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", "")
        title = re.sub(r'\??\s?\d*?\&.*', '', title).title().strip()
        item_local.from_title = title  #Guardamos esta etiqueta para posible desambiguación de título

        item_local.contentType = "movie"
        item_local.contentTitle = title
        item_local.extra = "peliculas"
        item_local.action = "findvideos"
        item_local.title = title.strip()
        item_local.infoLabels['year'] = "-"

        if scrapedyear >= "1900" and scrapedyear <= "2040":
            title_subs += [scrapedyear]

        itemlist.append(item_local.clone())  #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 = '<li><a href="[^"]+">(\d+)<\/a><\/li>'  #total de páginas
    patron += '<li><a href="([^"]+\/page\/(\d+)\/)"\s?rel="[^"]+">Página siguiente[^<]+<\/a><\/li><\/ul><\/div><\/ul>'  #url siguiente
    url_next = ''
    if scrapertools.find_single_match(data, patron):
        last_page, url_next, next_num = scrapertools.find_single_match(
            data, patron)

    if url_next:
        if last_page:
            title = '[COLOR gold]Página siguiente >>[/COLOR] %s de %s' % (
                int(next_num) - 1, last_page)
        else:
            title = '[COLOR gold]Página siguiente >>[/COLOR] %s' % (
                int(next_num) - 1)

        itemlist.append(
            Item(channel=item.channel,
                 action="listado",
                 title=title,
                 url=url_next,
                 extra=item.extra))

    return itemlist