Exemplo n.º 1
0
def submenu(item):
    logger.info()

    from datetime import date
    todays_date = date.today()

    itemlist = []
    item.filter_lang = True

    patron = '<div class="cab_menu"\s*>.*?<\/div>'  #Menú principal
    data, response, item, itemlist = generictools.downloadpage(
        item.url,
        timeout=timeout,
        s2=False,
        canonical=canonical,
        patron=patron,
        item=item,
        itemlist=[])  # Descargamos la página

    # Verificamos si se ha cargado una página, y si además tiene la estructura correcta
    if not response.sucess or itemlist:  # Si ERROR o lista de errores ...
        return itemlist  # ... Salimos

    data1 = scrapertools.find_single_match(data, patron)
    patron = '<div id="menu_langen"\s*>.*?<\/div>'  #Menú de idiomas
    data1 += scrapertools.find_single_match(data, patron)

    patron = '<a href="(.*?)".*?title="(.*?)"'  #Encontrar todos los apartados
    matches = re.compile(patron, re.DOTALL).findall(data1)

    #logger.debug(patron)
    #logger.debug(matches)
    #logger.debug(data)

    if not matches:
        logger.error(
            "ERROR 02: SUBMENU: Ha cambiado la estructura de la Web " +
            " / PATRON: " + patron + " / DATA: " + data)
        itemlist.append(
            item.clone(
                action='',
                title=item.category +
                ': ERROR 02: SUBMENU: 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

    for scrapedurl, scrapedtitle in matches:
        title = scrapedtitle.replace(" torrent",
                                     "").replace(" Torrent",
                                                 "").replace("Series y ",
                                                             "").title()
        if item.extra in ['novedades'] and 'estreno' in scrapedurl:
            if str(todays_date.year) in scrapedurl:
                title = 'Estrenos %s' % todays_date.year
            elif str(todays_date.year - 1) in scrapedurl:
                title = 'Estrenos %s' % str(todays_date.year - 1)
            else:
                continue
            item.url = scrapedurl
            item.title = title
            return listado(item)

        elif item.extra not in ['novedades']:
            if 'estreno' in scrapedurl:
                continue

            if "castellano" in scrapedtitle.lower(
            ):  # Evita la entrada de peliculas castellano del menú de idiomas
                continue

            if item.extra == "series":  # Tratamos Series
                if not "/serie" in scrapedurl:
                    continue
            else:  # Tratamos Películas
                if "/serie" in scrapedurl:
                    continue

            if 'subtitulado' in scrapedtitle.lower(
            ) or 'latino' in scrapedtitle.lower(
            ) or 'original' in scrapedtitle.lower():
                item.filter_lang = False

            itemlist.append(
                item.clone(action="listado", title=title, url=scrapedurl))

    if item.extra == "series":  # Añadimos Series VOSE que está fuera del menú principal
        itemlist.append(
            item.clone(action="listado",
                       title="Series VOSE",
                       url=host + "series-vose/",
                       filter_lang=False))

    # Generos
    if item.extra == 'peliculas':
        patron = '<li\s*id="mas_categorias">\s*<i[^>]*>\s*<\/i>\s*categorias<\/li>(.*?)\/ul>'
        data1 = scrapertools.find_single_match(data, patron)

        patron = '<li>\s*<a\s*rel="nofollow"\s*href="([^"]+)"\s*title="[^"]+">\s*([^<]+)<\/a>\s*<\/li>'
        matches = re.compile(patron, re.DOTALL).findall(data1)

        #logger.debug(patron)
        #logger.debug(matches)
        #logger.debug(data1)

        if not matches:
            return itemlist

        itemlist.append(item.clone(action='', title='Géneros', url=''))
        for scrapedurl, scrapedtitle in sorted(matches):
            title = scrapertools.decode_utf8_error(scrapedtitle)
            itemlist.append(
                item.clone(action="listado",
                           title='  - ' + title,
                           url=scrapedurl))

    return itemlist
Exemplo n.º 2
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
Exemplo n.º 3
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
Exemplo n.º 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 = ''
        data, response, item, itemlist = generictools.downloadpage(
            next_page_url,
            timeout=timeout_search,
            canonical=canonical,
            item=item,
            itemlist=itemlist,
            quote_rep=False,
            check_blocked_IP=True)  # Descargamos la página
        data = re.sub(r"&nbsp;", "", data)
        # Verificamos si ha cambiado el Host
        if response.host:
            next_page_url = response.url_new

        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
            if len(itemlist) > 1:  # Si hay algo que pintar lo pintamos
                last_page = 0
                break
            logger.error(
                "ERROR 01: LISTADO: La Web no responde o ha cambiado de URL: "
                + next_page_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 nada más, salimos directamente

        #Patrón para todo, incluido búsquedas en cualquier caso
        patron = '<tr class="lista2"><td align="(?:[^"]+)?"\s*class="(?:[^"]+)?"'
        patron += '\s*width="(?:[^"]+)?"\s*style="(?:[^"]+)?"><a href="[^"]+">'
        patron += '<img src="([^"]+)?"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*\/>'
        patron += '<\/a><\/td><td\s*align="(?:[^"]+)?"\s*class="(?:[^"]+)?"><a onmouseover="'
        patron += '(?:[^"]+)?"\s*onmouseout="(?:[^"]+)?"\s*href="[^"]+" title="[^"]+"'
        patron += '>([^<]+)<\/a>\s*<a href="([^"]+)"><img src="[^"]+"\s*border="'
        patron += '(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*><\/a>\s*(?:<a href="([^"]+)">'
        patron += '<img src="[^"]+"\s*border="(?:[^"]+)?"\s*alt="(?:[^"]+)?"\s*><\/a>)?'
        patron += '\s*<br><span.*?<\/span>\s*<\/td><td align="(?:[^"]+)?"\s*width="'
        patron += '(?:[^"]+)?"\s*class="(?:[^"]+)?">.*?<\/td><td align="(?:[^"]+)?"\s*'
        patron += 'width="(?:[^"]+)?"\s*class="(?:[^"]+)?">([^<]+)?<\/td><td align="'
        patron += '(?:[^"]+)?"\s*width="(?:[^"]+)?"\s*class="(?:[^"]+)?">\s*'
        patron += '<font color="(?:[^"]+)?">(\d+)?<\/font>'
        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
            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, response, item, itemlist = generictools.downloadpage(
                    item.url + '&page=%s' % last_page,
                    timeout=timeout_search,
                    quote_rep=False,
                    item=item,
                    itemlist=itemlist)
                data_last = re.sub(r"&nbsp;", "", data_last)
                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

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

            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