Forum Astuces.divers Télécharger Arte+7

Posté par . Licence CC by-sa
Tags :
9
29
mai
2014

Salut à tous

Voici une nouvelle version de mon téléchargeur pour Arte+7.
Passez la liste des urles Arte+7 en paramètres, et hop!

Les options :
* -q HD|DVD : qualité, HD par défaut
* -t <tentatives> : nombre de tentatives pour wget

Il nécessite toujours BeautifulSoup 4, mais il utilise wget désormais. La reprise sur erreur ou interruption est gérée par celui-ci.

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Téléchargeur pour Arte+7 via wget
# Ceci est une adaptation du service http://floriancrouzat.net/arte/ de Florian Crouzat
#
import os
import sys
import json
import shlex
import argparse
import subprocess
import urllib.request
from datetime import datetime

try:
    from bs4 import BeautifulSoup
except ImportError:
    print("artedl.py nécessite BeautifulSoup 4.")
    sys.exit(1)

class ArtePlus7NotFound(Exception): pass
class ArtePlus7Error(Exception): pass

class ArtePlus7:
    ''' Téléchargeur pour Arte+7 '''
    WGET_PATH = [ '/usr/bin/wget' ]
    WGET_OPTS = [ '-c', '-T', '60' ]
    QUALITY = { 'HD': 'SQ', 'DVD': 'EQ' }

    def __init__(self, url, tries=1, quality='HD'):
        assert tries > 0 and quality in self.QUALITY

        self.plus7 = url
        self.tries = tries
        self.quality = quality
        self.cmd_line = []
        self.video_name = ''
        self.video_when = ''
        self.video_excerpt = ''
        if not self._search_video():
            raise ArtePlus7NotFound

    def _search_video(self):
        ''' Recherche la vidéo et construit la ligne de commande.
            Retourne True si trouvée, False sinon.
        '''
        try:
            url = urllib.request.urlopen(self.plus7)
        except Exception as e:
            print("\n{}".format(e))
            return False
        soup = BeautifulSoup(url.read().decode())
        divs = soup.find_all('div', {'class':'video-container'})
        for a in divs:
            json_url = a.attrs.get('arte_vp_url', '').replace('/player/', '/')
            if 'PLUS7' in json_url:
                break
        else:
            print("\nAucune vidéo trouvée : {}".format(self.plus7))
            return False

        jdic = json.loads(urllib.request.urlopen(json_url).read().decode())
        vjp = jdic['video']

        vti = vjp['VTI']
        title = vti.replace('"', '«', 1).replace('"', '»', 1)
        title = title.translate(str.maketrans('/', 'x', '"')).strip()

        try:
            vda = datetime.strptime(vjp['VDA'], '%d/%m/%Y %H:%M:%S %z')
        except ValueError:
            vda = datetime.now()
        vda = vda.replace(vda.year, vda.month, vda.day, vda.hour, vda.minute, 0, 0)
        self.video_when = vda.strftime('%Y-%m-%d %Hh%M')
        self.video_name = 'Arte - {} - {}'.format(title, self.video_when)
        self.video_excerpt = vjp.get('V7T', '<Aucune description>')
        print("\nVidéo trouvée : {}\n{}".format(self.video_name, self.video_excerpt))

        for video in vjp['VSR']:
            if video['VFO'] == 'HBBTV' and video['VMT'] == 'mp4' and video['VQU'] == self.QUALITY[self.quality]:
                self.video_file = video['VUR']
                break
        else:
            print("Aucun fichier pour cette qualité : {}\n".format(self.quality))
            return False

        self.cmd_line = self.WGET_PATH + self.WGET_OPTS + [ '-t', str(self.tries), '-O', self.file_from_video(), self.video_file ]
        return True

    def file_from_video(self):
        return self.video_name + '.mp4'

    def file_from_excerpt(self):
        return self.video_name + '.txt'

    def video_exists(self):
        return os.path.isfile(self.file_from_video())

    def delete_video(self):
        try:
            os.remove(self.file_from_video())
        except FileNotFoundError:
            pass

    def touch_video(self):
        try:
            os.utime(self.file_from_video())
        except FileNotFoundError:
            pass

    def dump_video(self):
        ''' Télécharge la vidéo '''
        if not os.path.isfile(self.WGET_PATH[0]):
            print("artedl.py nécessite wget.")
            raise ArtePlus7Error
        try:
            subprocess.check_call(self.cmd_line)
        except subprocess.CalledProcessError:
            print("\nTéléchargement incomplet.\n")
        except KeyboardInterrupt:
            print("\nTéléchargement interrompu.\n")
        else:
            self.touch_video()
            return
        raise ArtePlus7Error

    def dump_excerpt(self):
        ''' Sauvegarde le résumé '''
        with open(self.file_from_excerpt(), 'w') as fd:
            fd.write("{}\n{}\n".format(self.video_name, self.video_excerpt))

    def show_command(self):
        ''' Affiche la ligne de commande au format shell '''
        quoted_args = [ shlex.quote(arg) for arg in self.cmd_line ]
        print("\n{}\n".format(' '.join(quoted_args)))

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="ArtePlus7")
    parser.add_argument('-q', dest='quality', default='HD', choices=('HD', 'DVD'))
    parser.add_argument('-t', dest='tries', default=5, type=int)
    parser.add_argument('url_list', metavar='URL', nargs='+')
    args = parser.parse_args()

    for url in args.url_list:
        try:
            arte7 = ArtePlus7(url, tries=args.tries, quality=args.quality)
        except ArtePlus7NotFound:
            continue
        arte7.show_command()
        try:
            arte7.dump_video()
            arte7.dump_excerpt()
        except ArtePlus7Error:
            break

Enjoy!

  • # ArteFetcher

    Posté par (page perso) . Évalué à 2.

    Salut !

    Je te propose de jeter un coup d'œil à ArteFetcher, qui te permet de te passer complètement du site web d'Arte+7 ;)

    Je ne sais pas s'il est présent sur d'autres distributions, mais il est présent dans AUR sur Archlinux.

  • # plein d'alternatives

    Posté par . Évalué à 1.

    Hello,

    citons aussi https://github.com/rg3/youtube-dl

    Et tous les projets autour avec pléthore de gui,
    https://github.com/search?q=youtube-dl&ref=reposearch

    Que je n'ai jamais testé, car j'ai la mienne, interface web, vaguement responsive via bootstrap, mais pas du tout batterie friendly
    https://github.com/maboiteaspam/ytb-wui

    N'étant pas fan de ce Python. Je dois quad même dire que je reconnais une certaine efficacité et rapidité de développement dans ta pythonerie qui me surprend plus qu'agréablement.

    a+

    • [^] # Re: plein d'alternatives

      Posté par . Évalué à 1.

      Y a aussi qarte.

      • [^] # Re: plein d'alternatives

        Posté par . Évalué à 1.

        ouaip, mais qarte à l'époque où je m'en servait, c'était lent (à tout points de vue), et surtout sa leaké de partout.

        Alors, bon, c'était bien utile pour montrer une certaine voie à d'autres développeurs motivés, mais je ne peux décemment recommandé ce logiciel.

  • # erreur décodage url

    Posté par . Évalué à 1.

    Bonjour,
    je teste votre code python suite à la défection actuelle de floriancrouzat.net.
    Je suis devant plusieurs problèmes certainement résolubles (enfin j'espère).
    Le premier est la difficulté de trouver une installation simple de python 3.4 ou 3.5 sur Maverick-OSX 10.9.
    Le deuxième problème induit par le premier est qu'avec la version de base de python sur mac os x (2.7) je ne suis pas sur du bon fonctionnement de NeautifulSoup 4.3.2 malgré l'absence d'erreur à la compilation. Le dernier est que l'absence de urllib.request sur python 2.7 m'a obligé à utiliser urllib2 et à changer "url = urllib.request.urlopen(self.plus7)" par "url = urllib2.urlopen(self.plus7)".
    Mais jusque là tout va bien.
    En mettant comme argument une URL quelconque je me retrouve devant cette erreur (je vous mets ma commande et le retour) :

    python artetv.py http://www.arte.tv/guide/fr/049879-014/l-assiette-bresilienne
    Traceback (most recent call last):
    File "artetv.py", line 149, in
    arte7 = ArtePlus7(url, tries=args.tries, quality=args.quality)
    File "artetv.py", line 43, in init
    if not self._search_video():
    File "artetv.py", line 55, in _search_video
    soup = BeautifulSoup(url.read().decode())
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 614: ordinal not in range(128)

    voilà si vous pouvez m'aider.
    Merci d'avance

    • [^] # Re: erreur décodage url

      Posté par . Évalué à 2.

      Et en beaucoup beaucoup plus simple cela donne (il faut passer l'url de la page en paramètre) :

      from re import split
      import urllib2
      import json
      import sys
      html = urllib2.urlopen(sys.argv[1]).read()
      url = split('.*arte_vp_url="(.*\.json)".*',html)[1]
      url = url.replace("/player/","/")
      videos = json.loads(urllib2.urlopen(url).read())
      for video in videos["video"]["VSR"]:
          if video["VFO"] == "HBBTV":
              if video["version"] == "VF-STF" and video ["VQU"] == "HQ":
                  print video["VUR"]
    • [^] # Re: erreur décodage url

      Posté par . Évalué à 1. Dernière modification le 17/06/14 à 14:36.

      hello,

      essayez avec youtube-dl, ici ça fonctionne bien.

      youtube-dl http://www.arte.tv/guide/fr/049879-014/l-assiette-bresilienne

      chapeau bas rems.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.