예제 #1
0
    def __init__(self):
        self.navigateur = Navigateur()

        APIPrive.__init__(self)

        if API.INSTANCE != None:
            raise Exception("API est déjà instancier")
예제 #2
0
	def __init__( self ):
		self.navigateur = Navigateur()
		
		APIPrive.__init__( self )
		
		if API.INSTANCE != None:
			raise Exception("API est déjà instancier")
예제 #3
0
    def __init__(
        self,
        url,  # URL de la video
        proxy=None,  # Proxy a utiliser
        proxySock=False,  # Indique si le proxy est de type SOCK
        sousTitres=False,  # Telechargement des sous-titres ?
        progressFnct=lambda x: None,  # Callback pour la progression du telechargement
        stopDownloadEvent=threading.Event(),  # Event pour arreter un telechargement
        outDir=".",  # Repertoire de sortie de la video telechargee
    ):
        # Classe pour telecharger des fichiers
        self.navigateur = Navigateur(proxy, proxySock)
        # Infos video recuperees dans le XML
        self.id = None
        self.lienMMS = None
        self.lienRTMP = None
        self.manifestURL = None
        self.m3u8URL = None
        self.drm = None
        self.chaine = None
        self.timeStamp = None
        self.codeProgramme = None

        # Recupere l'id de l'emission
        idEmission = self.getId(url)
        # Recupere la page d'infos de l'emission
        pageInfos = self.navigateur.getFichier(self.XML_DESCRIPTION.replace("_ID_EMISSION_", idEmission))
        # Parse la page d'infos
        self.parseInfos(pageInfos)
        # Petit message en cas de DRM
        if self.drm == "oui":
            logger.warning("La vidéo posséde un DRM ; elle sera sans doute illisible")
            # Verification qu'un lien existe
        if self.m3u8URL is None and self.manifestURL is None and self.lienRTMP is None and self.lienMMS is None:
            raise PluzzDLException("Aucun lien vers la vidéo")
            # Le telechargement se fait de differente facon selon le type du lien disponible
            # Pour l'instant, seule la methode via les liens m3u8 fonctionne
            # Le code pour les autres liens reste quand meme en place pour etre utilise si les elements manquants sont trouves (clef HMAC par exemple)
        if self.m3u8URL is not None:
            # Nom du fichier
            nomFichier = self.getNomFichier(outDir, self.codeProgramme, self.timeStamp, "ts")
            # Downloader
            downloader = PluzzDLM3U8(self.m3u8URL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct)
        elif self.manifestURL is not None:
            # Nom du fichier
            nomFichier = self.getNomFichier(outDir, self.codeProgramme, self.timeStamp, "flv")
            # Downloader
            downloader = PluzzDLF4M(self.manifestURL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct)
        elif self.lienRTMP is not None:
            # Downloader
            downloader = PluzzDLRTMP(self.lienRTMP)
        elif self.lienMMS is not None:
            # Downloader
            downloader = PluzzDLMMS(self.lienMMS)
            # Recupere les sous titres si necessaire
        if sousTitres:
            self.telechargerSousTitres(idEmission, self.chaine, nomFichier)
            # Lance le téléchargement
        downloader.telecharger()
예제 #4
0
	def __init__( self, url, useFragments = False, proxy = None, progressbar = False ):
		self.url              = url
		self.useFragments     = useFragments
		self.proxy            = proxy
		self.progressbar      = progressbar
		self.navigateur       = Navigateur( self.proxy )
		
		self.lienMMS          = None
		self.lienRTMP         = None
		self.manifestURL      = None
		self.m3u8URL          = None
		self.drm              = None
		
		# Recupere l'ID de l'emission
		self.getID()
		# Recupere la page d'infos de l'emission
		self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) )
		# Parse la page d'infos
		self.parseInfos()
		# Petit message en cas de DRM
		if( self.drm == "oui" ):
			logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
예제 #5
0
class API(APIPrive):
	## Instance utilisé par le programme
	INSTANCE = None
	
	## Constructeur.
	# Ne pas utiliser.
	# @param self l'objet courant
	def __init__( self ):
		self.navigateur = Navigateur()
		
		APIPrive.__init__( self )
		
		if API.INSTANCE != None:
			raise Exception("API est déjà instancier")
	
	## Renvoie l'instance d'API
	# @return l'instance d'API
	@staticmethod
	def getInstance():
		"""Renvoie l'instance de l'API"""
		return API.INSTANCE
	
	## Récupère une page web sur internet et remplace les caractères spéciaux (code HTML ou ISO).
	# @param self le plugin courant
	# @param url l'url de la page web
	# @return la page web sous forme d'une chaîne ou la chaîne vide en cas d'échec
	def getPage(self, url):
		return self.navigateur.getPage( url )
		#~ 
		#~ #Vérification de l'url
		#~ match = re.match(API.PATTERN_URL, url)
		#~ if match == None:
			#~ print "API.getPage(): url invalide."
			#~ return ""
		#~ 
		#~ #Téléchargement et décompression si néscessaire
		#~ try:
			#~ connexion = httplib.HTTPConnection(match.group(1), timeout=APIPrive.HTTP_TIMEOUT)
			#~ 
			#~ heads = {"Accept-Encoding":"deflate,gzip",
				#~ "Accept-Charset":"iso-8859-5, utf-8",
				#~ "User-Agent":choice(APIPrive.USER_AGENT)}
			#~ connexion.request("GET", match.group(2), headers=heads)
			#~ reponse = connexion.getresponse()
			#~ if reponse == None:
				#~ print "API.getPage(): erreur de téléchargement."
				#~ return ""
			#~ return self.reponseHttpToUTF8(reponse)
		#~ except Exception, ex:
			#~ print "API.getPage(): erreur de téléchargement.",ex
			#~ print_exc()
		#~ return ""
	
	def getPicture( self, url ):
		return self.navigateur.getPicture( url )
	
	## Récupère des pages webs sur internet et remplace les caractères spéciaux (code HTML ou ISO). Cette méthode reste connecté au serveur si il y a plusieurs page à y télécharger, elle est plus rapide que plusieurs appel à #getPage.
	# @param self le plugin courant
	# @param urls une liste d'url des pages à télécharger
	# @return un dictionnaire avec comme clé les urls et comme valeur les pages sous forme de chaîne
	def getPages(self, urls):
		
		reponses = self.navigateur.getPages( urls )
		return reponses
예제 #6
0
 def __init__(self):
     self.navigateur = Navigateur()
예제 #7
0
class UpdateManager(object):

    # Liste des sites qui disposent des mises a jour
    listeSites = [
        "http://tvdownloader.googlecode.com/svn/branches/MAJ_Plugins"
    ]

    # Instance de la classe (singleton)
    instance = None

    ## Surcharge de la methode de construction standard (pour mettre en place le singleton)
    def __new__(self, *args, **kwargs):
        if (self.instance is None):
            self.instance = super(UpdateManager, self).__new__(self)
        return self.instance

    ## Constructeur
    def __init__(self):
        self.navigateur = Navigateur()

    ## Methode pour generer le fichier XML de description des plugins
    @staticmethod
    def creerXML():
        # On ouvre le fichier XML
        try:
            fichierXML = open("versionsPlugins.xml", "wt")
        except:
            logger.error("impossible d'ouvrir le fichier XML en ecriture")
            return
        fichierXML.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        fichierXML.write("<plugins>\n")

        # Pour chaque fichier de plugin
        for fichier in os.listdir("plugins"):
            # Tous les fichiers .py autre que __init__.py sont des plugins
            if (fichier[-3:] == ".py" and fichier.find("__init__.py") == -1):
                fichierCheminComplet = "plugins/%s" % (fichier)
                # Nom du fichier
                nom = fichier
                # Date de la derniere modification
                date = os.stat(fichierCheminComplet).st_mtime
                # Somme de controle SHA1
                fichierPlugin = open(fichierCheminComplet, "rt")
                sha1 = hashlib.sha1(fichierPlugin.read()).hexdigest()
                fichierPlugin.close()
                # On ajoute l'element au fichier XML
                fichierXML.write(
                    '\t<plugin nom="%s" dateModification="%s" sha1="%s"></plugin>\n'
                    % (nom, date, sha1))

        # On ferme le fichier XML
        fichierXML.write("</plugins>\n")
        fichierXML.close()

    ## Methode qui verifie si les plugins disposent d'une mise a jour
    # @param site Sites sur lesquel aller chercher la mise a jour
    # @return     Liste des plugins a mettre a jour [ Nom du plugin, URL ou charger le plugin, SHA1 du plugin ]
    def verifierMiseAjour(self, site):
        listePluginsXML = []  # [ Nom, date derniere modification, SHA1 ]
        listePluginAMettreAJour = [
        ]  # [ Nom du plugin, URL ou charger le plugin, SHA1 du plugin ]
        handler = UpdateManagerHandler(listePluginsXML)

        # On recupere le fichier XML de description des plugins
        fichierXML = self.navigateur.getPage("%s/versionsPlugins.xml" % (site))
        if (fichierXML == ""
            ):  # Si on n'a rien recupere, on essaye un autre site
            logger.warn("aucune information disponible sur le site %s" %
                        (site))
            return []
        # On vide la liste
        del listePluginsXML[:]
        # On parse le fichier XML
        try:
            xml.sax.parseString(fichierXML, handler)
        except:
            logger.error("impossible de parser le fichier XML du site %s" %
                         (site))
            return []
        # Pour chaque plugin decrit dans le fichier XML
        for (nom, dateModification, sha1) in listePluginsXML:
            # On n'a pas une nouvelle version du plugin
            nouvelleVersion = False
            # Dans chacun des repertoires qui contiennent des plugins
            for rep in repPlugins:
                pluginCheminComplet = "%s/%s" % (rep, nom)
                # Si le plugin est present
                if (os.path.isfile(pluginCheminComplet)):
                    # Si la version dont l'on dispose est moins recente que celle du site
                    if (os.stat(pluginCheminComplet).st_mtime <
                            dateModification):
                        nouvelleVersion = True
                    else:
                        nouvelleVersion = False
                        break  # On peut arrete de chercher, on a deja le plus recent
            # S'il y a une nouvelle version
            if (nouvelleVersion):
                listePluginAMettreAJour.append(
                    [nom, "%s/%s" % (site, nom), sha1])

        # On a fini de lire les infos sur ce site, pas besoin de parcourir les autres
        return listePluginAMettreAJour

    # Methode pour installer la mise a jour d'un plugin
    # @param nomPlugin Nom du fichier du plugin a mettre a jour
    # @param urlPlugin URL ou charger le plugin
    # @param sha1      Somme de controle SHA1 du plugin
    # @return Si le plugin a ete correctement installe
    def mettreAJourPlugin(self, nomPlugin, urlPlugin, sha1):
        logger.info("mise a jour du plugin %s" % (nomPlugin))
        # On telecharge le plugin
        codePlugin = self.navigateur.getPage(urlPlugin)
        if (codePlugin == ""):
            return False
        # On verifie la somme de controle du plugin
        if (hashlib.sha1(codePlugin).hexdigest() != sha1):
            logger.warn("somme de controle incorrecte pour le fichier %s" %
                        (urlPlugin))
            return False
        # On met en place le plugin
        fichier = open("%s/%s" % (repPlugins[0], nomPlugin), 'wt')
        fichier.write(codePlugin)
        fichier.close()

        return True
예제 #8
0
	def __init__( self ):
		self.navigateur = Navigateur()
예제 #9
0
class UpdateManager( object ):
	
	# Liste des sites qui disposent des mises a jour
	listeSites = [ "http://tvdownloader.googlecode.com/svn/branches/MAJ_Plugins" ]
	
	# Instance de la classe (singleton)
	instance = None
	
	## Surcharge de la methode de construction standard (pour mettre en place le singleton)
	def __new__( self, *args, **kwargs ):
		if( self.instance is None ):
			self.instance = super( UpdateManager, self ).__new__( self )
		return self.instance
	
	## Constructeur
	def __init__( self ):
		self.navigateur = Navigateur()
	
	## Methode pour generer le fichier XML de description des plugins
	@staticmethod
	def creerXML():
		# On ouvre le fichier XML
		try:
			fichierXML = open( "versionsPlugins.xml", "wt" )
		except:
			logger.error( "impossible d'ouvrir le fichier XML en ecriture" )
			return
		fichierXML.write( '<?xml version="1.0" encoding="UTF-8"?>\n' )
		fichierXML.write( "<plugins>\n" )
		
		# Pour chaque fichier de plugin
		for fichier in os.listdir( "plugins" ): 
			# Tous les fichiers .py autre que __init__.py sont des plugins
			if( fichier [ -3 : ] == ".py" and fichier.find( "__init__.py" ) == -1 ):
				fichierCheminComplet = "plugins/%s" %( fichier )
				# Nom du fichier
				nom  = fichier
				# Date de la derniere modification
				date = os.stat( fichierCheminComplet ).st_mtime
				# Somme de controle SHA1
				fichierPlugin = open( fichierCheminComplet, "rt" )
				sha1 = hashlib.sha1( fichierPlugin.read() ).hexdigest()
				fichierPlugin.close()
				# On ajoute l'element au fichier XML
				fichierXML.write( '\t<plugin nom="%s" dateModification="%s" sha1="%s"></plugin>\n' %( nom, date, sha1 ) )
		
		# On ferme le fichier XML
		fichierXML.write( "</plugins>\n" )
		fichierXML.close()
		
	## Methode qui verifie si les plugins disposent d'une mise a jour
	# @param site Sites sur lesquel aller chercher la mise a jour
	# @return     Liste des plugins a mettre a jour [ Nom du plugin, URL ou charger le plugin, SHA1 du plugin ]
	def verifierMiseAjour( self, site ):
		listePluginsXML         = [] # [ Nom, date derniere modification, SHA1 ]
		listePluginAMettreAJour = [] # [ Nom du plugin, URL ou charger le plugin, SHA1 du plugin ]
		handler                 = UpdateManagerHandler( listePluginsXML )
		
		# On recupere le fichier XML de description des plugins
		fichierXML = self.navigateur.getPage( "%s/versionsPlugins.xml" %( site ) )
		if( fichierXML == "" ): # Si on n'a rien recupere, on essaye un autre site
			logger.warn( "aucune information disponible sur le site %s" %( site ) )
			return []
		# On vide la liste
		del listePluginsXML[ : ]
		# On parse le fichier XML
		try:
			xml.sax.parseString( fichierXML, handler )
		except:
			logger.error( "impossible de parser le fichier XML du site %s" %( site ) )
			return []
		# Pour chaque plugin decrit dans le fichier XML
		for( nom, dateModification, sha1 ) in listePluginsXML:
			# On n'a pas une nouvelle version du plugin
			nouvelleVersion = False
			# Dans chacun des repertoires qui contiennent des plugins
			for rep in repPlugins:
				pluginCheminComplet = "%s/%s" %( rep, nom )
				# Si le plugin est present
				if( os.path.isfile( pluginCheminComplet ) ):
					# Si la version dont l'on dispose est moins recente que celle du site
					if( os.stat( pluginCheminComplet ).st_mtime < dateModification ):
						nouvelleVersion = True
					else:
						nouvelleVersion = False
						break # On peut arrete de chercher, on a deja le plus recent
			# S'il y a une nouvelle version
			if( nouvelleVersion ):
				listePluginAMettreAJour.append( [ nom, "%s/%s" %( site, nom ), sha1 ] )
		
		# On a fini de lire les infos sur ce site, pas besoin de parcourir les autres	
		return listePluginAMettreAJour
	
	# Methode pour installer la mise a jour d'un plugin
	# @param nomPlugin Nom du fichier du plugin a mettre a jour
	# @param urlPlugin URL ou charger le plugin
	# @param sha1      Somme de controle SHA1 du plugin
	# @return Si le plugin a ete correctement installe
	def mettreAJourPlugin( self, nomPlugin, urlPlugin, sha1 ):
		logger.info( "mise a jour du plugin %s" %( nomPlugin ) )
		# On telecharge le plugin
		codePlugin = self.navigateur.getPage( urlPlugin )
		if( codePlugin == "" ):
			return False
		# On verifie la somme de controle du plugin
		if( hashlib.sha1( codePlugin ).hexdigest() != sha1 ):
			logger.warn( "somme de controle incorrecte pour le fichier %s" %( urlPlugin ) )
			return False
		# On met en place le plugin
		fichier = open( "%s/%s" %( repPlugins[ 0 ], nomPlugin ), 'wt' )
		fichier.write( codePlugin )
		fichier.close()
		
		return True
예제 #10
0
파일: PluzzDL.py 프로젝트: BantouTV/Pluzzdl
class PluzzDL( object ):

	def __init__( self, url, useFragments = False, proxy = None, resume = False, progressFnct = lambda x : None, stopDownloadEvent = threading.Event(), outDir = ".", manifest = False, playlist = False ):
		self.url               = url
		self.useFragments      = useFragments
		self.proxy             = proxy
		self.resume            = resume
		self.progressFnct      = progressFnct
		self.stopDownloadEvent = stopDownloadEvent
		self.outDir            = outDir
		self.navigateur        = Navigateur( self.proxy )
		self.historique        = Historique()
		self.configuration     = Configuration()
		self.lienMMS           = None
		self.lienRTMP          = None
		self.manifestURL       = None
		self.drm               = None
		if playlist:
			self.mode = "playlist"
			self.ext  = "ts"
		else:
			self.mode = "manifest"
			self.ext  = "flv"

		self.hmacKey           = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash        = self.configuration[ "player_hash" ]

		if( re.match( "http://www.pluzz.fr/[^\.]+?\.html", self.url ) ):
			# Recupere l'ID de l'emission
			self.getID()
			# Recupere la page d'infos de l'emission
			self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) )
			# Parse la page d'infos
			self.parseInfos()
			# Petit message en cas de DRM
			if( self.drm == "oui" ):
				logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
			# Lien MMS trouve
			if( self.lienMMS is not None ):
				logger.info( "Lien MMS : %s\nUtiliser par exemple mimms ou msdl pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienMMS ) )
			# Lien RTMP trouve
			if( self.lienRTMP is not None ):
				logger.info( "Lien RTMP : %s\nUtiliser par exemple rtmpdump pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienRTMP ) )
			# N'utilise pas les fragments si cela n'a pas ete demande et que des liens directs ont ete trouves
			if( ( ( self.lienMMS is not None ) or ( self.lienRTMP is not None ) ) and not self.useFragments ):
				sys.exit( 0 )

			if self.mode == "manifest":
				# Lien du manifest non trouve
				if( self.manifestURL is None ):
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )

			if self.mode == "playlist":
				# Lien de la playlist M3U8 non trouve
				if( self.playlistM3U8 is None ):
					logger.critical( "Pas de lien vers la playlist" )
					sys.exit( -1 )

			self.nomFichier = os.path.join( self.outDir, "%s.%s" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ], self.ext ) )
		else:
			if self.mode == "manifest":
				page = self.navigateur.getFichier( self.url )
				try:
					self.manifestURL = re.findall( "(http://.+?manifest.f4m)", page )[ 0 ]
				except:
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )
				try:
					self.nomFichier = os.path.join( self.outDir, "%s.flv" %( self.url.split( "/" )[ -1 ] ) )
				except:
					self.nomFichier = os.path.join( self.outDir, "video.flv" )

		self.generateNomFichier()

		if self.mode == "manifest":
			self.getVideoViaManifest()

		if self.mode == "playlist":
			self.getVideoViaPlaylist()

	def getVideoViaManifest( self ):
		# Verifie si le lien du manifest contient la chaine "media-secure"
		if( self.manifestURL.find( "media-secure" ) != -1 ):
			logger.critical( "pluzzdl ne sait pas encore gérer ce type de vidéo..." )
			sys.exit( 0 )
		# Lien du manifest (apres le token)
		self.manifestURLToken = self.navigateur.getFichier( "http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s" %( self.manifestURL[ self.manifestURL.find( "/z/" ) : ] ) )
		# Recupere le manifest
		self.manifest = self.navigateur.getFichier( self.manifestURLToken )
		# Parse le manifest
		self.parseManifest()
		# Calcul les elements
		self.hdnea = self.manifestURLToken[ self.manifestURLToken.find( "hdnea" ) : ]
		self.pv20, self.hdntl = self.pv2.split( ";" )
		self.pvtokenData = r"st=0000000000~exp=9999999999~acl=%2f%2a~data=" + self.pv20 + "!" + self.playerHash
		self.pvtoken = "pvtoken=%s~hmac=%s" %( urllib.quote( self.pvtokenData ), hmac.new( self.hmacKey, self.pvtokenData, hashlib.sha256 ).hexdigest() )

		#
		# Creation de la video
		#
		self.premierFragment    = 1
		self.telechargementFini = False

		# S'il faut reprendre le telechargement
		if( self.resume ):
			video = self.historique.getVideo( self.urlFrag )
			# Si la video est dans l'historique
			if( video is not None ):
				# Si la video existe sur le disque
				if( os.path.exists( self.nomFichier ) ):
					if( video.finie ):
						logger.info( "La vidéo a déjà été entièrement téléchargée" )
						sys.exit( 0 )
					else:
						self.ouvrirVideoExistante()
						self.premierFragment = video.fragments
						logger.info( "Reprise du téléchargement de la vidéo au fragment %d" %( video.fragments ) )
				else:
					self.ouvrirNouvelleVideo()
					logger.info( "Impossible de reprendre le téléchargement de la vidéo, le fichier %s n'existe pas" %( self.nomFichier ) )
			else: # Si la video n'est pas dans l'historique
				self.ouvrirNouvelleVideo()
		else: # S'il ne faut pas reprendre le telechargement
			self.ouvrirNouvelleVideo()

		# Calcul l'estimation du nombre de fragments
		self.nbFragMax = round( self.duree / 6 )
		logger.debug( "Estimation du nombre de fragments : %d" %( self.nbFragMax ) )

		# Ajout des fragments
		logger.info( "Début du téléchargement des fragments" )
		try :
			i = self.premierFragment
			while( not self.stopDownloadEvent.isSet() ):
				frag  = self.navigateur.getFichier( "%s%d?%s&%s&%s" %( self.urlFrag, i, self.pvtoken, self.hdntl, self.hdnea ) )
				debut = self.debutVideo( i, frag )
				self.fichierVideo.write( frag[ debut : ] )
				# Affichage de la progression
				self.progressFnct( min( int( ( i / self.nbFragMax ) * 100 ), 100 ) )
				i += 1
		except urllib2.URLError, e :
			if( hasattr( e, 'code' ) ):
				if( e.code == 403 ):
					if( e.reason == "Forbidden" ):
						logger.info( "Le hash du player semble invalide ; calcul du nouveau hash" )
						newPlayerHash = self.getPlayerHash()
						if( newPlayerHash != self.playerHash ):
							self.configuration[ "player_hash" ] = newPlayerHash
							self.configuration.writeConfig()
							logger.info( "Un nouveau hash a été trouvé ; essayez de relancer l'application" )
						else:
							logger.critical( "Pas de nouveau hash disponible..." )
					else:
						logger.critical( "Impossible de charger la vidéo" )
				elif( e.code == 404 ):
					self.progressFnct( 100 )
					self.telechargementFini = True
					logger.info( "Fin du téléchargement" )
					self.convertVideo()
		except KeyboardInterrupt:
			logger.info( "Interruption clavier" )
예제 #11
0
    def __init__(self,
                 url,                # URL de la video
                 proxy = None,       # Proxy à utiliser
                 proxySock = False,  # Proxy est-il de type SOCK?
                 sousTitres = False, # Télécharger les sous-titres?
                 progressFnct = lambda x: None, # Callback de progression
                 stopDownloadEvent = threading.Event(), # → Arrêt
                 outDir = "."        # Répertoire de sortie
                 ):
        # Classe pour télécharger des fichiers
        self.url = url
        self.navigateur = Navigateur(proxy, proxySock)
        self.pageHtml= None
        # Infos vidéo récupérées (dans la page, le xml, ou le json...)
        self.id = None
        self.lienMms = None
        self.lienRtmp = None
        self.lienCurl = None
        self.manifestUrl = None
        self.manifestUrlToken = None
        self.m3u8Url = None
        self.drm = None
        self.chaine = None
        self.timeStamp = None
        self.codeProgramme = None

        # Récupère la page html
        self.pageHtml = self.navigateur.getFichier(url)
        # Récupère les infos requises
        self.getInfos()          # virtuelle
        # Petit message en cas de DRM
        if self.drm == "oui":
            logger.warning("La vidéo possède un DRM; elle sera sans doute illisible.")
        # Le téléchargement s'effectue en fonction du type de lien disponible
        if self.m3u8Url is not None:
            downloader = DlM3u8(self.m3u8Url,
                                outDir, self.codeProgramme, self.timeStamp,
                                self.navigateur,
                                stopDownloadEvent, progressFnct)
        elif self.manifestUrl is not None:
            downloader = DlF4m(self.manifestUrl, self.manifestUrlToken,
                               outDir, self.codeProgramme, self.timeStamp,
                               self.navigateur,
                               stopDownloadEvent, progressFnct)
        elif self.lienRtmp is not None:
            downloader = DlRtmp(self.lienRtmp, self.swfPlayerUrl,
                                outDir, self.codeProgramme, self.timeStamp,
                                self.navigateur,
                                stopDownloadEvent, progressFnct)
        elif self.lienMms is not None:
            downloader = DlMms(self.lienMms,
                               outDir, self.codeProgramme, self.timeStamp,
                               self.navigateur,
                               stopDownloadEvent, progressFnct)
        elif self.lienCurl:
            # Downloader
            downloader = DlCurl(self.lienCurl,
                               outDir, self.codeProgramme, self.timeStamp,
                                self.navigateur,
                                stopDownloadEvent, progressFnct)
        else:                   #  pas de lien connu détecté
            raise ReplayDlException("Aucun lien vers la vidéo!")

        # Récupère les sous-titres si possible
        if(sousTitres):
            self.telechargerSousTitres(self.id, self.chaine, nomFichier)
        # Lance le téléchargement
        downloader.telecharger()
        # Conversion finale
        downloader.convertir()
예제 #12
0
class ReplayDl(object):
    """
    Classe principale pour lancer un téléchargement
    """

    def __init__(self,
                 url,                # URL de la video
                 proxy = None,       # Proxy à utiliser
                 proxySock = False,  # Proxy est-il de type SOCK?
                 sousTitres = False, # Télécharger les sous-titres?
                 progressFnct = lambda x: None, # Callback de progression
                 stopDownloadEvent = threading.Event(), # → Arrêt
                 outDir = "."        # Répertoire de sortie
                 ):
        # Classe pour télécharger des fichiers
        self.url = url
        self.navigateur = Navigateur(proxy, proxySock)
        self.pageHtml= None
        # Infos vidéo récupérées (dans la page, le xml, ou le json...)
        self.id = None
        self.lienMms = None
        self.lienRtmp = None
        self.lienCurl = None
        self.manifestUrl = None
        self.manifestUrlToken = None
        self.m3u8Url = None
        self.drm = None
        self.chaine = None
        self.timeStamp = None
        self.codeProgramme = None

        # Récupère la page html
        self.pageHtml = self.navigateur.getFichier(url)
        # Récupère les infos requises
        self.getInfos()          # virtuelle
        # Petit message en cas de DRM
        if self.drm == "oui":
            logger.warning("La vidéo possède un DRM; elle sera sans doute illisible.")
        # Le téléchargement s'effectue en fonction du type de lien disponible
        if self.m3u8Url is not None:
            downloader = DlM3u8(self.m3u8Url,
                                outDir, self.codeProgramme, self.timeStamp,
                                self.navigateur,
                                stopDownloadEvent, progressFnct)
        elif self.manifestUrl is not None:
            downloader = DlF4m(self.manifestUrl, self.manifestUrlToken,
                               outDir, self.codeProgramme, self.timeStamp,
                               self.navigateur,
                               stopDownloadEvent, progressFnct)
        elif self.lienRtmp is not None:
            downloader = DlRtmp(self.lienRtmp, self.swfPlayerUrl,
                                outDir, self.codeProgramme, self.timeStamp,
                                self.navigateur,
                                stopDownloadEvent, progressFnct)
        elif self.lienMms is not None:
            downloader = DlMms(self.lienMms,
                               outDir, self.codeProgramme, self.timeStamp,
                               self.navigateur,
                               stopDownloadEvent, progressFnct)
        elif self.lienCurl:
            # Downloader
            downloader = DlCurl(self.lienCurl,
                               outDir, self.codeProgramme, self.timeStamp,
                                self.navigateur,
                                stopDownloadEvent, progressFnct)
        else:                   #  pas de lien connu détecté
            raise ReplayDlException("Aucun lien vers la vidéo!")

        # Récupère les sous-titres si possible
        if(sousTitres):
            self.telechargerSousTitres(self.id, self.chaine, nomFichier)
        # Lance le téléchargement
        downloader.telecharger()
        # Conversion finale
        downloader.convertir()

    def getInfos(self):
        """
        Cette méthode virtuelle doit être surchargée en fonction du site ciblé.
        Elle est chargée de récupérer toutes les informations nécessaires au
        téléchargement:
        - id de la vidéo
        - type de téléchargement
        - lien de téléchargement
        ...
        """
        pass

    def telechargerSousTitres(self, idEmission, nomChaine, nomVideo):
        """
        Récupère le fichier de sous titre de la vidéo.
        Virtuelle ← spécifique à Pluzz
        """
        pass

    # À virer dans Downloader avec import datetime
    def getNomFichier(self, repertoire, codeProgramme, timeStamp, extension):
        """
        Construit le nom du fichier de sortie
        """
        nomFichier = os.path.join(
            repertoire, "%s_%s.%s" % (
                codeProgramme,  # enlever [ !:;?/<>] ?
                datetime.datetime.fromtimestamp(timeStamp).strftime(
                    "%Y-%m-%d_%H-%M"),
                extension))
        logger.debug(nomFichier)
        return nomFichier
예제 #13
0
    "http://www.canalplus.fr/c-divertissement/pid1784-les-guignols-de-l-info.html?",
    "http://www.canalplus.fr/c-divertissement/pid1778-pepites-sur-le-net.html?",
    "http://www.canalplus.fr/c-divertissement/pid3279-reperages-l-emission.html?",
    "http://www.canalplus.fr/c-divertissement/pid2053-stephane-guillon.html?",
    "http://www.canalplus.fr/c-divertissement/pid3591-une-minute-avant.html?",
    "http://www.canalplus.fr/c-divertissement/pid3403-c-air-guitar-2010.html",
    "http://www.canalplus.fr/c-divertissement/pid3299-album-de-la-semaine.html?",
    "http://www.canalplus.fr/c-divertissement/pid3301-concert-prive.html?",
    "http://www.canalplus.fr/c-divertissement/pid3535-c-la-musicale.html",
    "http://www.canalplus.fr/c-divertissement/pid3308-la-radio-de-moustic.html?",
    "http://www.canalplus.fr/c-divertissement/pid3298-coming-next.html?",
    "http://www.canalplus.fr/c-divertissement/pid3522-u2-en-concert.html?",
    "http://www.canalplus.fr/c-divertissement/pid3303-le-live-du-grand-journal.html?"
]

navigateur = Navigateur()
api = API.getInstance()


def testeMechanize(urls):
    reponses = {}
    for url in urls:
        reponses[url] = navigateur.getPage(url)


def testeGetPage(urls):
    reponses = {}
    for url in urls:
        reponses[url] = api.getPage(url)

예제 #14
0
	def __init__( self,
				  url,  # URL de la video
				  proxy = None,  # Proxy a utiliser
				  proxySock = False,  # Indique si le proxy est de type SOCK
				  sousTitres = False,  # Telechargement des sous-titres ?
				  progressFnct = lambda x : None,  # Callback pour la progression du telechargement
				  stopDownloadEvent = threading.Event(),  # Event pour arreter un telechargement
				  outDir = "."  # Repertoire de sortie de la video telechargee
				):
		# Classe pour telecharger des fichiers
		self.navigateur = Navigateur( proxy, proxySock )
		# Infos video recuperees dans le XML
		self.id = None
		self.lienMMS = None
		self.lienRTMP = None
		self.manifestURL = None
		self.m3u8URL = None
		self.drm = None
		self.chaine = None
		self.timeStamp = None
		self.codeProgramme = None

		# Recupere l'id de l'emission
		idEmission = self.getId( url )
		# Recupere la page d'infos de l'emission
		pageInfos = self.navigateur.getFichier( self.XML_DESCRIPTION.replace( "_ID_EMISSION_", idEmission ) )
		# Parse la page d'infos
		self.parseInfos( pageInfos )
		# Petit message en cas de DRM
		if( self.drm == "oui" ):
			logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
		# Verification qu'un lien existe
		if( self.m3u8URL is None and
			self.manifestURL is None and
			self.lienRTMP is None and
			self.lienMMS is None ):
			raise PluzzDLException( "Aucun lien vers la vidéo" )
		# Le telechargement se fait de differente facon selon le type du lien disponible
		# Pour l'instant, seule la methode via les liens m3u8 fonctionne
		# Le code pour les autres liens reste quand meme en place pour etre utilise si les elements manquants sont trouves (clef HMAC par exemple)
		if( self.m3u8URL is not None ):
			# Nom du fichier
			nomFichier = self.getNomFichier( outDir, self.codeProgramme, self.timeStamp, "ts" )
			# Downloader
			downloader = PluzzDLM3U8( self.m3u8URL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct )
		elif( self.manifestURL is not None ):
			# Nom du fichier
			nomFichier = self.getNomFichier( outDir, self.codeProgramme, self.timeStamp, "flv" )
			# Downloader
			downloader = PluzzDLF4M( self.manifestURL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct )
		elif( self.lienRTMP is not None ):
			# Downloader
			downloader = PluzzDLRTMP( self.lienRTMP )
		elif( self.lienMMS is not None ):
			# Downloader
			downloader = PluzzDLMMS( self.lienMMS )
		# Recupere les sous titres si necessaire
		if( sousTitres ):
			self.telechargerSousTitres( idEmission, self.chaine, nomFichier )
		# Lance le téléchargement
		downloader.telecharger()
예제 #15
0
class PluzzDL( object ):
	"""
	Classe principale pour lancer un telechargement
	"""

	REGEX_ID = "http://info.francetelevisions.fr/\?id-video=([^\"]+)"
	XML_DESCRIPTION = "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=_ID_EMISSION_"
	URL_SMI = "http://www.pluzz.fr/appftv/webservices/video/getFichierSmi.php?smi=_CHAINE_/_ID_EMISSION_.smi&source=azad"
	M3U8_LINK = "http://medias2.francetv.fr/catchup-mobile/france-dom-tom/non-token/non-drm/m3u8/_FILE_NAME_.m3u8"
	REGEX_M3U8 = "/([0-9]{4}/S[0-9]{2}/J[0-9]{1}/[0-9]*-[0-9]{6,8})-"

	def __init__( self,
				  url,  # URL de la video
				  proxy = None,  # Proxy a utiliser
				  proxySock = False,  # Indique si le proxy est de type SOCK
				  sousTitres = False,  # Telechargement des sous-titres ?
				  progressFnct = lambda x : None,  # Callback pour la progression du telechargement
				  stopDownloadEvent = threading.Event(),  # Event pour arreter un telechargement
				  outDir = "."  # Repertoire de sortie de la video telechargee
				):
		# Classe pour telecharger des fichiers
		self.navigateur = Navigateur( proxy, proxySock )
		# Infos video recuperees dans le XML
		self.id = None
		self.lienMMS = None
		self.lienRTMP = None
		self.manifestURL = None
		self.m3u8URL = None
		self.drm = None
		self.chaine = None
		self.timeStamp = None
		self.codeProgramme = None

		# Recupere l'id de l'emission
		idEmission = self.getId( url )
		# Recupere la page d'infos de l'emission
		pageInfos = self.navigateur.getFichier( self.XML_DESCRIPTION.replace( "_ID_EMISSION_", idEmission ) )
		# Parse la page d'infos
		self.parseInfos( pageInfos )
		# Petit message en cas de DRM
		if( self.drm == "oui" ):
			logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
		# Verification qu'un lien existe
		if( self.m3u8URL is None and
			self.manifestURL is None and
			self.lienRTMP is None and
			self.lienMMS is None ):
			raise PluzzDLException( "Aucun lien vers la vidéo" )
		# Le telechargement se fait de differente facon selon le type du lien disponible
		# Pour l'instant, seule la methode via les liens m3u8 fonctionne
		# Le code pour les autres liens reste quand meme en place pour etre utilise si les elements manquants sont trouves (clef HMAC par exemple)
		if( self.m3u8URL is not None ):
			# Nom du fichier
			nomFichier = self.getNomFichier( outDir, self.codeProgramme, self.timeStamp, "ts" )
			# Downloader
			downloader = PluzzDLM3U8( self.m3u8URL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct )
		elif( self.manifestURL is not None ):
			# Nom du fichier
			nomFichier = self.getNomFichier( outDir, self.codeProgramme, self.timeStamp, "flv" )
			# Downloader
			downloader = PluzzDLF4M( self.manifestURL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct )
		elif( self.lienRTMP is not None ):
			# Downloader
			downloader = PluzzDLRTMP( self.lienRTMP )
		elif( self.lienMMS is not None ):
			# Downloader
			downloader = PluzzDLMMS( self.lienMMS )
		# Recupere les sous titres si necessaire
		if( sousTitres ):
			self.telechargerSousTitres( idEmission, self.chaine, nomFichier )
		# Lance le téléchargement
		downloader.telecharger()

	def getId( self, url ):
		"""
		Recupere l'ID de la video a partir de son URL
		"""
		try :
			page = self.navigateur.getFichier( url )
			idEmission = re.findall( self.REGEX_ID, page )[ 0 ]
			logger.debug( "ID de l'émission : %s" % ( idEmission ) )
			return idEmission
		except :
			raise PluzzDLException( "Impossible de récupérer l'ID de l'émission" )

	def parseInfos( self, pageInfos ):
		"""
		Parse le fichier de description XML d'une emission
		"""
		try :
			xml.sax.parseString( pageInfos, PluzzDLInfosHandler( self ) )
			# Si le lien m3u8 n'existe pas, il faut essayer de creer celui de la plateforme mobile
			if( self.m3u8URL is None ):
				self.m3u8URL = self.M3U8_LINK.replace( "_FILE_NAME_", re.findall( self.REGEX_M3U8, pageInfos )[ 0 ] )
			logger.debug( "URL m3u8 : %s" % ( self.m3u8URL ) )
			logger.debug( "URL manifest : %s" % ( self.manifestURL ) )
			logger.debug( "Lien RTMP : %s" % ( self.lienRTMP ) )
			logger.debug( "Lien MMS : %s" % ( self.lienMMS ) )
			logger.debug( "Utilisation de DRM : %s" % ( self.drm ) )
		except :
			raise PluzzDLException( "Impossible de parser le fichier XML de l'émission" )

	def getNomFichier( self, repertoire, codeProgramme, timeStamp, extension ):
		"""
		Construit le nom du fichier de sortie
		"""
		return os.path.join( repertoire, "%s_%s.%s" % ( codeProgramme, datetime.datetime.fromtimestamp( timeStamp ).strftime( "%Y-%m-%d_%H-%M" ), extension ) )

	def telechargerSousTitres( self, idEmission, nomChaine, nomVideo ):
		"""
		Recupere le fichier de sous titre de la video
		"""
		urlSousTitres = self.URL_SMI.replace( "_CHAINE_", nomChaine.lower().replace( " ", "" ) ).replace( "_ID_EMISSION_", idEmission )
		# Essaye de recuperer le sous titre
		try:
			sousTitresSmi = self.navigateur.getFichier( urlSousTitres )
		except:
			logger.debug( "Sous titres indisponibles" )
			return
		logger.debug( "Sous titres disponibles" )
		# Enregistre le fichier de sous titres en smi
		try :
			( nomFichierSansExtension, _ ) = os.path.splitext( nomVideo )
			# Ecrit le fichier
			with open( "%s.smi" % ( nomFichierSansExtension ), "w" ) as f:
				f.write( sousTitresSmi )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )
		logger.debug( "Fichier de sous titre smi enregistré" )
		# Convertit le fichier de sous titres en srt
		try:
			with open( "%s.srt" % ( nomFichierSansExtension ), "w" ) as f:
				pageSoup = BeautifulSoup.BeautifulSoup( sousTitresSmi )
				elmts = pageSoup.findAll( "sync" )
				indice = 1
				for ( elmtDebut, elmtFin ) in ( elmts[ i : i + 2 ] for i in range( 0, len( elmts ), 2 ) ):
					# Extrait le temps de debut et le texte
					tempsEnMs = int( elmtDebut[ "start" ] )
					tempsDebutSrt = time.strftime( "%H:%M:%S,XXX", time.gmtime( int( tempsEnMs / 1000 ) ) )
					tempsDebutSrt = tempsDebutSrt.replace( "XXX", str( tempsEnMs )[ -3 : ] )
					lignes = elmtDebut.p.findAll( "span" )
					texte = "\n".join( map( lambda x : x.contents[ 0 ].strip(), lignes ) )
					# Extrait le temps de fin
					tempsEnMs = int( elmtFin[ "start" ] )
					tempsFinSrt = time.strftime( "%H:%M:%S,XXX", time.gmtime( int( tempsEnMs / 1000 ) ) )
					tempsFinSrt = tempsFinSrt.replace( "XXX", str( tempsEnMs )[ -3 : ] )
					# Ecrit dans le fichier
					f.write( "%d\n" % ( indice ) )
					f.write( "%s --> %s\n" % ( tempsDebutSrt, tempsFinSrt ) )
					f.write( "%s\n\n" % ( texte.encode( "iso-8859-1" ) ) )
					# Element suivant
					indice += 1
		except:
			logger.error( "Impossible de convertir les sous titres en str" )
			return
		logger.debug( "Fichier de sous titre srt enregistré" )
예제 #16
0
파일: PluzzDL.py 프로젝트: BantouTV/Pluzzdl
	def __init__( self, url, useFragments = False, proxy = None, resume = False, progressFnct = lambda x : None, stopDownloadEvent = threading.Event(), outDir = ".", manifest = False, playlist = False ):
		self.url               = url
		self.useFragments      = useFragments
		self.proxy             = proxy
		self.resume            = resume
		self.progressFnct      = progressFnct
		self.stopDownloadEvent = stopDownloadEvent
		self.outDir            = outDir
		self.navigateur        = Navigateur( self.proxy )
		self.historique        = Historique()
		self.configuration     = Configuration()
		self.lienMMS           = None
		self.lienRTMP          = None
		self.manifestURL       = None
		self.drm               = None
		if playlist:
			self.mode = "playlist"
			self.ext  = "ts"
		else:
			self.mode = "manifest"
			self.ext  = "flv"

		self.hmacKey           = self.configuration[ "hmac_key" ].decode( "hex" )
		self.playerHash        = self.configuration[ "player_hash" ]

		if( re.match( "http://www.pluzz.fr/[^\.]+?\.html", self.url ) ):
			# Recupere l'ID de l'emission
			self.getID()
			# Recupere la page d'infos de l'emission
			self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) )
			# Parse la page d'infos
			self.parseInfos()
			# Petit message en cas de DRM
			if( self.drm == "oui" ):
				logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
			# Lien MMS trouve
			if( self.lienMMS is not None ):
				logger.info( "Lien MMS : %s\nUtiliser par exemple mimms ou msdl pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienMMS ) )
			# Lien RTMP trouve
			if( self.lienRTMP is not None ):
				logger.info( "Lien RTMP : %s\nUtiliser par exemple rtmpdump pour la recuperer directement ou l'option -f de pluzzdl pour essayer de la charger via ses fragments" %( self.lienRTMP ) )
			# N'utilise pas les fragments si cela n'a pas ete demande et que des liens directs ont ete trouves
			if( ( ( self.lienMMS is not None ) or ( self.lienRTMP is not None ) ) and not self.useFragments ):
				sys.exit( 0 )

			if self.mode == "manifest":
				# Lien du manifest non trouve
				if( self.manifestURL is None ):
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )

			if self.mode == "playlist":
				# Lien de la playlist M3U8 non trouve
				if( self.playlistM3U8 is None ):
					logger.critical( "Pas de lien vers la playlist" )
					sys.exit( -1 )

			self.nomFichier = os.path.join( self.outDir, "%s.%s" %( re.findall( "http://www.pluzz.fr/([^\.]+?)\.html", self.url )[ 0 ], self.ext ) )
		else:
			if self.mode == "manifest":
				page = self.navigateur.getFichier( self.url )
				try:
					self.manifestURL = re.findall( "(http://.+?manifest.f4m)", page )[ 0 ]
				except:
					logger.critical( "Pas de lien vers le manifest" )
					sys.exit( -1 )
				try:
					self.nomFichier = os.path.join( self.outDir, "%s.flv" %( self.url.split( "/" )[ -1 ] ) )
				except:
					self.nomFichier = os.path.join( self.outDir, "video.flv" )

		self.generateNomFichier()

		if self.mode == "manifest":
			self.getVideoViaManifest()

		if self.mode == "playlist":
			self.getVideoViaPlaylist()
예제 #17
0
class API(APIPrive):
    ## Instance utilisé par le programme
    INSTANCE = None

    ## Constructeur.
    # Ne pas utiliser.
    # @param self l'objet courant
    def __init__(self):
        self.navigateur = Navigateur()

        APIPrive.__init__(self)

        if API.INSTANCE != None:
            raise Exception("API est déjà instancier")

    ## Renvoie l'instance d'API
    # @return l'instance d'API
    @staticmethod
    def getInstance():
        """Renvoie l'instance de l'API"""
        return API.INSTANCE

    ## Récupère une page web sur internet et remplace les caractères spéciaux (code HTML ou ISO).
    # @param self le plugin courant
    # @param url l'url de la page web
    # @return la page web sous forme d'une chaîne ou la chaîne vide en cas d'échec
    def getPage(self, url):
        return self.navigateur.getPage(url)
        #~
        #~ #Vérification de l'url
        #~ match = re.match(API.PATTERN_URL, url)
        #~ if match == None:
        #~ print "API.getPage(): url invalide."
        #~ return ""
        #~
        #~ #Téléchargement et décompression si néscessaire
        #~ try:
        #~ connexion = httplib.HTTPConnection(match.group(1), timeout=APIPrive.HTTP_TIMEOUT)
        #~
        #~ heads = {"Accept-Encoding":"deflate,gzip",
        #~ "Accept-Charset":"iso-8859-5, utf-8",
        #~ "User-Agent":choice(APIPrive.USER_AGENT)}
        #~ connexion.request("GET", match.group(2), headers=heads)
        #~ reponse = connexion.getresponse()
        #~ if reponse == None:
        #~ print "API.getPage(): erreur de téléchargement."
        #~ return ""
        #~ return self.reponseHttpToUTF8(reponse)
        #~ except Exception, ex:
        #~ print "API.getPage(): erreur de téléchargement.",ex
        #~ print_exc()
        #~ return ""

    def getPicture(self, url):
        return self.navigateur.getPicture(url)

    ## Récupère des pages webs sur internet et remplace les caractères spéciaux (code HTML ou ISO). Cette méthode reste connecté au serveur si il y a plusieurs page à y télécharger, elle est plus rapide que plusieurs appel à #getPage.
    # @param self le plugin courant
    # @param urls une liste d'url des pages à télécharger
    # @return un dictionnaire avec comme clé les urls et comme valeur les pages sous forme de chaîne
    def getPages(self, urls):

        reponses = self.navigateur.getPages(urls)
        return reponses
예제 #18
0
class PluzzDL( object ):
	
	def __init__( self, url, useFragments = False, proxy = None, progressbar = False ):
		self.url              = url
		self.useFragments     = useFragments
		self.proxy            = proxy
		self.progressbar      = progressbar
		self.navigateur       = Navigateur( self.proxy )
		
		self.lienMMS          = None
		self.lienRTMP         = None
		self.manifestURL      = None
		self.m3u8URL          = None
		self.drm              = None
		
		# Recupere l'ID de l'emission
		self.getID()
		# Recupere la page d'infos de l'emission
		self.pageInfos = self.navigateur.getFichier( "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=%s" %( self.id ) )
		# Parse la page d'infos
		self.parseInfos()
		# Petit message en cas de DRM
		if( self.drm == "oui" ):
			logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
		
	def getID( self ):
		try :
			page     = self.navigateur.getFichier( self.url )
			self.id  = re.findall( r"http://info.francetelevisions.fr/\?id-video=([^\"]+)", page )[ 0 ]
			logger.debug( "ID de l'émission : %s" %( self.id ) )
		except :
			logger.critical( "Impossible de récupérer l'ID de l'émission" )
			sys.exit( -1 )
		
	def parseInfos( self ):
		try : 
			xml.sax.parseString( self.pageInfos, PluzzDLInfosHandler( self ) )
			logger.debug( "Lien MMS : %s" %( self.lienMMS ) )
			logger.debug( "Lien RTMP : %s" %( self.lienRTMP ) )
			logger.debug( "URL manifest : %s" %( self.manifestURL ) )
			logger.debug( "Utilisation de DRM : %s" %( self.drm ) )
		except :
			logger.critical( "Impossible de parser le fichier XML de l'émission" )
			sys.exit( -1 )
	
	def parseManifest( self ):
		try :
			arbre          = xml.etree.ElementTree.fromstring( self.manifest )
			# Duree
			self.duree     = float( arbre.find( "{http://ns.adobe.com/f4m/1.0}duration" ).text )
			media          = arbre.findall( "{http://ns.adobe.com/f4m/1.0}media" )[ -1 ]
			# Bitrate
			self.bitrate   = int( media.attrib[ "bitrate" ] )
			# URL des fragments
			urlbootstrap   = media.attrib[ "url" ]
			self.urlFrag   = "%s%sSeg1-Frag" %( self.manifestURLToken[ : self.manifestURLToken.find( "manifest.f4m" ) ], urlbootstrap )
			# Header du fichier final
			self.flvHeader = base64.b64decode( media.find( "{http://ns.adobe.com/f4m/1.0}metadata" ).text )
		except :
			logger.critical( "Impossible de parser le manifest" )
			sys.exit( -1 )
예제 #19
0
파일: PluzzDL.py 프로젝트: pierri/Pluzz
class PluzzDL( object ):
	"""
	Classe principale pour lancer un telechargement
	"""

	REGEX_ID = "http://info.francetelevisions.fr/\?id-video=([^\"]+)"
	JSON_DESCRIPTION = "http://webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion=_ID_EMISSION_&catalogue=Pluzz"
	URL_SMI = "http://www.pluzz.fr/appftv/webservices/video/getFichierSmi.php?smi=_CHAINE_/_ID_EMISSION_.smi&source=azad"
	#M3U8_LINK = "http://medias2.francetv.fr/catchup-mobile/france-dom-tom/non-token/non-drm/m3u8/_FILE_NAME_.m3u8"
	M3U8_LINK = "http://medias2.francetv.fr/catchup-mobile/hls-ios-inf/i/streaming-adaptatif_france-dom-tom/_FILE_NAME_-,398,632,934,k.mp4.csmil/master.m3u8"
	REGEX_M3U8 = "/([0-9]{4}/S[0-9]{2}/J[0-9]{1}/[0-9]*-[0-9]{6,8})-"

	def __init__( self,
				  url,  # URL de la video
				  proxy = None,  # Proxy a utiliser
				  proxySock = False,  # Indique si le proxy est de type SOCK
				  sousTitres = False,  # Telechargement des sous-titres ?
				  progressFnct = lambda x : None,  # Callback pour la progression du telechargement
				  stopDownloadEvent = threading.Event(),  # Event pour arreter un telechargement
				  outDir = "."  # Repertoire de sortie de la video telechargee
				):
		# Classe pour telecharger des fichiers
		self.navigateur = Navigateur( proxy, proxySock )
		# Infos video recuperees dans le XML
		self.id = None
		self.lienMMS = None
		self.lienRTMP = None
		self.manifestURL = None
		self.m3u8URL = None
		self.drm = None
		self.chaine = None
		self.timeStamp = None
		self.codeProgramme = None

		# Recupere l'id de l'emission
		idEmission = self.getId( url )
		# Recupere la page d'infos de l'emission
		pageInfos = self.navigateur.getFichier( self.JSON_DESCRIPTION.replace( "_ID_EMISSION_", idEmission ) )
		# Parse la page d'infos
		self.parseInfos( pageInfos )
		# Petit message en cas de DRM
		if( self.drm == "oui" ):
			logger.warning( "La vidéo posséde un DRM ; elle sera sans doute illisible" )
		# Verification qu'un lien existe
		if( self.m3u8URL is None and
			self.manifestURL is None and
			self.lienRTMP is None and
			self.lienMMS is None ):
			raise PluzzDLException( "Aucun lien vers la vidéo" )
		# Le telechargement se fait de differente facon selon le type du lien disponible
		# Pour l'instant, seule la methode via les liens m3u8 fonctionne
		# Le code pour les autres liens reste quand meme en place pour etre utilise si les elements manquants sont trouves (clef HMAC par exemple)
		if( self.m3u8URL is not None ):
			# Nom du fichier
			nomFichier = self.getNomFichier( outDir, self.codeProgramme, self.timeStamp, "ts" )
			# Downloader
			downloader = PluzzDLM3U8( self.m3u8URL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct )
		elif( self.manifestURL is not None ):
			# Nom du fichier
			nomFichier = self.getNomFichier( outDir, self.codeProgramme, self.timeStamp, "flv" )
			# Downloader
			downloader = PluzzDLF4M( self.manifestURL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct )
		elif( self.lienRTMP is not None ):
			# Downloader
			downloader = PluzzDLRTMP( self.lienRTMP )
		elif( self.lienMMS is not None ):
			# Downloader
			downloader = PluzzDLMMS( self.lienMMS )
		# Recupere les sous titres si necessaire
		if( sousTitres ):
			self.telechargerSousTitres( idEmission, self.chaine, nomFichier )
		# Lance le téléchargement
		downloader.telecharger()

	def getId( self, url ):
		"""
		Recupere l'ID de la video a partir de son URL
		"""
		try :
			page = self.navigateur.getFichier( url )
			idEmission = re.findall( self.REGEX_ID, page )[ 0 ]
			logger.debug( "ID de l'émission : %s" % ( idEmission ) )
			return idEmission
		except :
			raise PluzzDLException( "Impossible de récupérer l'ID de l'émission" )

	def parseInfos( self, pageInfos ):
		"""
		Parse le fichier de description XML d'une emission
		"""
		try :
			#xml.sax.parseString( pageInfos, PluzzDLInfosHandler( self ) )
			data = json.loads(pageInfos)
			self.codeProgramme = data["code_programme"]
			self.chaine = data["chaine"]
			self.timeStamp = float( data["diffusion"]["timestamp"] )
			for v in data["videos"]:
				print v
				fmt = v["format"]
				if fmt == "smil-mp4":
					self.manifestURL = v["url"]
				if fmt == "m3u8-download":
					self.m3u8URL = v["url"]
				# TODO: check for other formats?
				self.drm = v["drm"]

			# Si le lien m3u8 n'existe pas, il faut essayer de creer celui de la plateforme mobile
			#XXX:
			#if( self.m3u8URL is None ):
			#	self.m3u8URL = self.M3U8_LINK.replace( "_FILE_NAME_", re.findall( self.REGEX_M3U8, pageInfos )[ 0 ] )
			logger.debug( "URL m3u8 : %s" % ( self.m3u8URL ) )
			logger.debug( "URL manifest : %s" % ( self.manifestURL ) )
			logger.debug( "Lien RTMP : %s" % ( self.lienRTMP ) )
			logger.debug( "Lien MMS : %s" % ( self.lienMMS ) )
			logger.debug( "Utilisation de DRM : %s" % ( self.drm ) )
		except:
			raise PluzzDLException( "Impossible de parser le fichier JSON de l'émission" )

	def getNomFichier( self, repertoire, codeProgramme, timeStamp, extension ):
		"""
		Construit le nom du fichier de sortie
		"""
		return os.path.join( repertoire, "%s_%s.%s" % ( codeProgramme, datetime.datetime.fromtimestamp( timeStamp ).strftime( "%Y-%m-%d_%H-%M" ), extension ) )

	def telechargerSousTitres( self, idEmission, nomChaine, nomVideo ):
		"""
		Recupere le fichier de sous titre de la video
		"""
		urlSousTitres = self.URL_SMI.replace( "_CHAINE_", nomChaine.lower().replace( " ", "" ) ).replace( "_ID_EMISSION_", idEmission )
		# Essaye de recuperer le sous titre
		try:
			sousTitresSmi = self.navigateur.getFichier( urlSousTitres )
		except:
			logger.debug( "Sous titres indisponibles" )
			return
		logger.debug( "Sous titres disponibles" )
		# Enregistre le fichier de sous titres en smi
		try :
			( nomFichierSansExtension, _ ) = os.path.splitext( nomVideo )
			# Ecrit le fichier
			with open( "%s.smi" % ( nomFichierSansExtension ), "w" ) as f:
				f.write( sousTitresSmi )
		except :
			raise PluzzDLException( "Impossible d'écrire dans le répertoire %s" % ( os.getcwd() ) )
		logger.debug( "Fichier de sous titre smi enregistré" )
		# Convertit le fichier de sous titres en srt
		try:
			with open( "%s.srt" % ( nomFichierSansExtension ), "w" ) as f:
				pageSoup = BeautifulSoup.BeautifulSoup( sousTitresSmi )
				elmts = pageSoup.findAll( "sync" )
				indice = 1
				for ( elmtDebut, elmtFin ) in ( elmts[ i : i + 2 ] for i in range( 0, len( elmts ), 2 ) ):
					# Extrait le temps de debut et le texte
					tempsEnMs = int( elmtDebut[ "start" ] )
					tempsDebutSrt = time.strftime( "%H:%M:%S,XXX", time.gmtime( int( tempsEnMs / 1000 ) ) )
					tempsDebutSrt = tempsDebutSrt.replace( "XXX", str( tempsEnMs )[ -3 : ] )
					lignes = elmtDebut.p.findAll( "span" )
					texte = "\n".join( map( lambda x : x.contents[ 0 ].strip(), lignes ) )
					# Extrait le temps de fin
					tempsEnMs = int( elmtFin[ "start" ] )
					tempsFinSrt = time.strftime( "%H:%M:%S,XXX", time.gmtime( int( tempsEnMs / 1000 ) ) )
					tempsFinSrt = tempsFinSrt.replace( "XXX", str( tempsEnMs )[ -3 : ] )
					# Ecrit dans le fichier
					f.write( "%d\n" % ( indice ) )
					f.write( "%s --> %s\n" % ( tempsDebutSrt, tempsFinSrt ) )
					f.write( "%s\n\n" % ( texte.encode( "iso-8859-1" ) ) )
					# Element suivant
					indice += 1
		except:
			logger.error( "Impossible de convertir les sous titres en str" )
			return
		logger.debug( "Fichier de sous titre srt enregistré" )
예제 #20
0
class PluzzDL(object):
    """
	Classe principale pour lancer un telechargement
	"""

    DATA_MAIN_VIDEO= 'data-main-video="([0-9][a-z]-)*"'
    REGEX_ID = "http://info.francetelevisions.fr/\?id-video=([^\"]+)"
    XML_DESCRIPTION = "http://www.pluzz.fr/appftv/webservices/video/getInfosOeuvre.php?mode=zeri&id-diffusion=_ID_EMISSION_"
    JSON_DESCRIPTION = "http://webservices.francetelevisions.fr/tools/getInfosOeuvre/v2/?idDiffusion=_ID_EMISSION_&catalogue=Pluzz"
    URL_SMI = "http://www.pluzz.fr/appftv/webservices/video/getFichierSmi.php?smi=_CHAINE_/_ID_EMISSION_.smi&source=azad"
    M3U8_LINK = "http://medias2.francetv.fr/catchup-mobile/france-dom-tom/non-token/non-drm/m3u8/_FILE_NAME_.m3u8"
    REGEX_M3U8 = "/([0-9]{4}/S[0-9]{2}/J[0-9]{1}/[0-9]*-[0-9]{6,8})-"

    def __init__(self,
                 url,  # URL de la video
                 proxy=None,  # Proxy a utiliser
                 proxySock=False,  # Indique si le proxy est de type SOCK
                 sousTitres=False,  # Telechargement des sous-titres ?
                 progressFnct=lambda x: None,  # Callback pour la progression du telechargement
                 stopDownloadEvent=threading.Event(),  # Event pour arreter un telechargement
                 outDir="."  # Repertoire de sortie de la video telechargee
                 ):
        # Classe pour telecharger des fichiers
        self.navigateur = Navigateur(proxy, proxySock)
        # Infos video recuperees dans le XML
        self.id = None
        self.lienMMS = None
        self.lienRTMP = None
        self.manifestURL = None
        self.m3u8URL = None
        self.drm = None
        self.chaine = None
        self.timeStamp = None
        self.codeProgramme = None

        # Recupere l'id de l'emission
        idEmission = self.getId(url)
        # Recupere la page d'infos de l'emission
        try:
            pageInfos = self.navigateur.getFichier(self.XML_DESCRIPTION.replace("_ID_EMISSION_", idEmission))
            # Parse la page d'infos
            self.parseInfos(pageInfos)
        except:
            logger.debug("Problème avec le fichier XML, récupération du JSON")
            pageInfos = self.navigateur.getFichier(self.JSON_DESCRIPTION.replace("_ID_EMISSION_", idEmission))
            self.parseInfosJSON(pageInfos)
        # Petit message en cas de DRM
        if (self.drm):
            logger.warning("La vidéo posséde un DRM ; elle sera sans doute illisible")
        # Verification qu'un lien existe
        if (self.m3u8URL is None and
                    self.manifestURL is None and
                    self.lienRTMP is None and
                    self.lienMMS is None):
            raise PluzzDLException("Aucun lien vers la vidéo")
        # Le telechargement se fait de differente facon selon le type du lien disponible
        # Pour l'instant, seule la methode via les liens m3u8 fonctionne
        # Le code pour les autres liens reste quand meme en place pour etre utilise si les elements manquants sont trouves (clef HMAC par exemple)
        if (self.m3u8URL is not None):
            # Nom du fichier
            nomFichier = self.getNomFichier(outDir, self.codeProgramme, self.timeStamp, "ts")
            # Downloader
            downloader = PluzzDLM3U8(self.m3u8URL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct)
        elif (self.manifestURL is not None):
            # Nom du fichier
            nomFichier = self.getNomFichier(outDir, self.codeProgramme, self.timeStamp, "flv")
            # Downloader
            downloader = PluzzDLF4M(self.manifestURL, nomFichier, self.navigateur, stopDownloadEvent, progressFnct)
        elif (self.lienRTMP is not None):
            # Downloader
            downloader = PluzzDLRTMP(self.lienRTMP)
        elif (self.lienMMS is not None):
            # Downloader
            downloader = PluzzDLMMS(self.lienMMS)
        # Recupere les sous titres si necessaire
        if (sousTitres):
            self.telechargerSousTitres(idEmission, self.chaine, nomFichier)
        # Lance le téléchargement
        downloader.telecharger()

    def getId(self, url):
        """
		Recupere l'ID de la video a partir de son URL
		"""
        # try :
        page = self.navigateur.getFichier(url)
        # idEmission = re.findall(self.REGEX_ID, page)[0]
        # LBR 10/05/2017
	data_main_video_tag = page[page.find("data-main-video="):]
	data_id = data_main_video_tag[data_main_video_tag.find('"')+1:]
	id_emission = data_id[:data_id.find('"')]
        #data_main_video_tag = re.findall(self.DATA_MAIN_VIDEO, page)[0]
	print "Found data-main-video tag:", id_emission
        #idEmission = re.findall('"[0-9]*"', data_main_video_tag)[0]
        #idEmission = idEmission.strip('"')
        # idEmission = "157542198"
        logger.debug("ID de l'émission : %s" % (id_emission))
        return id_emission

    # except :
    # raise PluzzDLException( "Impossible de récupérer l'ID de l'émission" )

    def parseInfos(self, pageInfos):
        """
		Parse le fichier de description XML d'une emission
		"""
        try:
            xml.sax.parseString(pageInfos, PluzzDLInfosHandler(self))
            # Si le lien m3u8 n'existe pas, il faut essayer de creer celui de la plateforme mobile
            if (self.m3u8URL is None):
                logger.debug("m3u8URL file missing, we will try to guess it")
                if (self.manifestURL is not None):
                    self.m3u8URL = self.manifestURL.replace("manifest.f4m", "index_2_av.m3u8")
                    self.m3u8URL = self.m3u8URL.replace("/z/", "/i/")
                # self.m3u8URL = self.M3U8_LINK.replace( "_FILE_NAME_", re.findall( self.REGEX_M3U8, pageInfos )[ 0 ] )
            logger.debug("URL m3u8 : %s" % (self.m3u8URL))
            logger.debug("URL manifest : %s" % (self.manifestURL))
            logger.debug("Lien RTMP : %s" % (self.lienRTMP))
            logger.debug("Lien MMS : %s" % (self.lienMMS))
            logger.debug("Utilisation de DRM : %s" % (self.drm))
        except:
            raise PluzzDLException("Impossible de parser le fichier XML de l'émission")

    def parseInfosJSON(self, pageInfos):
        """
		Parse le fichier de description JSON d'une emission
		"""
        try:
            data = json.loads(pageInfos)
            self.lienRTMP = None
            self.lienMMS = None
            self.timeStamp = data['diffusion']['timestamp']
            self.codeProgramme = data['code_programme']
            for v in data['videos']:
                if v['format'] == 'm3u8-download':
                    self.m3u8URL = v['url']
                    self.drm = v['drm']
                elif v['format'] == 'smil-mp4':
                    self.manifestURL = v['url']
            logger.debug("URL m3u8 : %s" % (self.m3u8URL))
            logger.debug("URL manifest : %s" % (self.manifestURL))
            logger.debug("Lien RTMP : %s" % (self.lienRTMP))
            logger.debug("Lien MMS : %s" % (self.lienMMS))
            logger.debug("Utilisation de DRM : %s" % (self.drm))
        except:
            raise PluzzDLException("Impossible de parser le fichier JSON de l'émission")

    def getNomFichier(self, repertoire, codeProgramme, timeStamp, extension):
        """
		Construit le nom du fichier de sortie
		"""
        return os.path.join(repertoire, "%s-%s.%s" % (
        datetime.datetime.fromtimestamp(timeStamp).strftime("%Y%m%d"), codeProgramme, extension))

    def telechargerSousTitres(self, idEmission, nomChaine, nomVideo):
        """
		Recupere le fichier de sous titre de la video
		"""
        urlSousTitres = self.URL_SMI.replace("_CHAINE_", nomChaine.lower().replace(" ", "")).replace("_ID_EMISSION_",
                                                                                                     idEmission)
        # Essaye de recuperer le sous titre
        try:
            sousTitresSmi = self.navigateur.getFichier(urlSousTitres)
        except:
            logger.debug("Sous titres indisponibles")
            return
        logger.debug("Sous titres disponibles")
        # Enregistre le fichier de sous titres en smi
        try:
            (nomFichierSansExtension, _) = os.path.splitext(nomVideo)
            # Ecrit le fichier
            with open("%s.smi" % (nomFichierSansExtension), "w") as f:
                f.write(sousTitresSmi)
        except:
            raise PluzzDLException("Impossible d'écrire dans le répertoire %s" % (os.getcwd()))
        logger.debug("Fichier de sous titre smi enregistré")
        # Convertit le fichier de sous titres en srt
        try:
            with open("%s.srt" % (nomFichierSansExtension), "w") as f:
                pageSoup = BeautifulSoup.BeautifulSoup(sousTitresSmi)
                elmts = pageSoup.findAll("sync")
                indice = 1
                for (elmtDebut, elmtFin) in (elmts[i: i + 2] for i in range(0, len(elmts), 2)):
                    # Extrait le temps de debut et le texte
                    tempsEnMs = int(elmtDebut["start"])
                    tempsDebutSrt = time.strftime("%H:%M:%S,XXX", time.gmtime(int(tempsEnMs / 1000)))
                    tempsDebutSrt = tempsDebutSrt.replace("XXX", str(tempsEnMs)[-3:])
                    lignes = elmtDebut.p.findAll("span")
                    texte = "\n".join(map(lambda x: x.contents[0].strip(), lignes))
                    # Extrait le temps de fin
                    tempsEnMs = int(elmtFin["start"])
                    tempsFinSrt = time.strftime("%H:%M:%S,XXX", time.gmtime(int(tempsEnMs / 1000)))
                    tempsFinSrt = tempsFinSrt.replace("XXX", str(tempsEnMs)[-3:])
                    # Ecrit dans le fichier
                    f.write("%d\n" % (indice))
                    f.write("%s --> %s\n" % (tempsDebutSrt, tempsFinSrt))
                    f.write("%s\n\n" % (texte.encode("iso-8859-1")))
                    # Element suivant
                    indice += 1
        except:
            logger.error("Impossible de convertir les sous titres en str")
            return
        logger.debug("Fichier de sous titre srt enregistré")