Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding:Utf-8 -*-
- ########################################################################################################
- # Copyright (C) 2010 La_Poigne #
- # This program is free software: you can redistribute it and/or modify it under the terms of the GNU #
- # General Public License as published by the Free Software Foundation, either version 2 of the #
- # License, or any later version. #
- # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY without #
- # even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
- # General Public License for more details. #
- # You should have received a copy of the GNU General Public License along with this program. If not, #
- # see http://www.gnu.org/licenses/ #
- ########################################################################################################
- #
- # V0.10
- #
- # ------------------------------------------------------------------------
- # CE SCRIPT NECESSITE FLVSTREAMER OU RTMPDUMP DANS LE CAS DES SOURCES RTMP
- # ------------------------------------------------------------------------
- #
- # ---------------------------------------------------------
- # Script de téléchargement des émissions du site de Canal +
- # ---------------------------------------------------------
- # Syntaxe: cplus.py [--help] [--verbose (1|2)] [--test] [--QUALITY] [--outdir OUTdir_PATH]
- #
- # verbose: affiche les infos à l'écran en + des logs
- # test: ne lance pas les téléchargements et ne met donc pas à jour le fichier d'historique
- # QUALITY: choix de la qualité:
- # 'SD' pour le bas débit,
- # 'MD' pour le haut débit,
- # 'HD' pour la HD
- # outdir: désigne le répertoire de téléchargement. S'il n'est pas précisé, c'est le sous répertoire downloads du script qui sera utilisé.
- #
- # Exemples:
- # cplus.py --verbose 2 --HD
- # cplus.py --verbose 1 --HD --outdir /mnt/video/TV
- #
- # L'historique des émissions téléchargées est enregistrée dans le fichier cplus_history.
- # Il est utilisé par le script donc ne pas le supprimer au risque de retélécharger des émissions.
- #
- # Le fichier cplus_unwanted sert à indiquer quelles émissions on ne veut pas télécharger.
- # On peut par exemple vouloir télécharger les émissions quotidiennes du petit journal mais pas
- # l'émission de la semaine.
- #
- # Les émissions non commentées sont celles que j'ai testées et qui dont les téléchargements
- # fonctionnent. Les autres sont à tester (emplacement de la date inclu).
- #
- # Le script gère les émissions en plusieurs parties (attention, il est nécessaire de télécharger toutes
- # les parties en une seule commande, le script ne gèrera pas les différentes parties si certaines ont
- # déjà été téléchargées).
- #
- ########################################################################################################
- #
- # Changelog:
- #
- # v0.1
- # 21/12/2010 : Création par vincentp010.
- #
- # v0.4
- # 10/11/2012 : Refonte par Jx7.
- #
- # v0.5
- # 19/11/2012 : Optimisations.
- # 2 modes: verbose et test.
- #
- # v0.6
- # 20/11/2012 : Correction d'un bug lié à l'utilisation des modes verbose et test.
- # Optimisations.
- # Ajout des noms de fichier supposés (nécessaire pour certains ID regroupant plusieurs
- # émissions).
- #
- # v0.7
- # 20/11/2012 : Ajout d'un paramètre dans la syntaxe pour choisir la qualité par des vidéos sans avoir à
- # éditer le script.
- # Ajout d'explications en début de script sur son utilisation.
- # Ajout de la gestion des émissions en plusieurs parties (attention, il est nécessaire de
- # télécharger toutes les parties en une seule commande, le script ne gèrera pas les
- # différentes parties si certaines ont déjà été téléchargées).
- #
- # v0.8
- # 20/11/2012 : Résolution d'un bug d'affichage
- # Changement de la syntaxe de l'option de qualité (SD, MD, HD)
- # Ajout d'un mode verbose simple
- # Ajout d'une option de choix de répertoire de téléchargement
- #
- # v0.10
- # 20/05/2013: Correction de bugs
- #
- ########################################################################################################
- import os, urllib, subprocess, time, sys
- from xml.dom import minidom
- # Identifiants des émissions ([ID de l'émission, emplacement de la date, nom de l'émission, nom supposé du fichier])
- ShowList = []
- ShowList.append([130,3,"Action discrete","ACTION_DISCRETE"]) # 130, 304, 371 ?
- ShowList.append([304,3,"Action discrete","ACTION_DISCRETE"]) # 130, 304, 371 ?
- ShowList.append([371,3,"Action discrete","ACTION_DISCRETE"]) # 130, 304, 371 ?
- #ShowList.append([62,4,"Le boucan du jour"]) # 204 205 206 316 ?
- #ShowList.append([627,4,"Bref"])
- #ShowList.append([104,4,"Le grand journal","LE_GRAND_JOURNAL"]) # 129
- ShowList.append([254,2,"Groland","GROLAND"])
- ShowList.append([48,3,"Guignols de l'info (les)","LES_GUIGNOLS"]) # 222 555 ?
- #ShowList.append([242,4,"Du hard ou du cochon"])
- #ShowList.append([451,4,"Jamel comedy club"]) # 943 953 ?
- #ShowList.append([896,4,"Le journal du hard"])
- #ShowList.append([39,4,"La matinale"]) # 105 ?
- #ShowList.append([215,4,"Le meilleur du hier","LE_MEILLEUR_DU_HIER"]) # 63 107 110 112 ?
- #ShowList.append([47,4,"Les pépites du net"]) # 319 321 ?
- ShowList.append([249,4,"Petit journal (le)","LE_PETIT_JOURNAL"]) # 249 250 556 557 558 559 ?
- #ShowList.append([843,4,"La question de plus"])
- #ShowList.append([294,4,"La revue de presse de Catherine et Eliane"]) # 852 ?
- ShowList.append([1082,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- ShowList.append([41,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- ShowList.append([74,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- ShowList.append([105,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- ShowList.append([110,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- ShowList.append([316,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- ShowList.append([371,4,"Salut les terriens","SALUT_LES_TERRIENS"])
- #ShowList.append([680,4,"Salut les terriens - edito de Blako"])
- #ShowList.append([1064,4,"Salut les terriens - Gaspard Proust"])
- #ShowList.append([1072,4,"Salut les terriens - les martiens de la semaine"])
- #ShowList.append([252,4,"SAV des émissions"]) # 406 ?
- #ShowList.append([936,4,"Tweet en clair"])
- ShowList.append([201,2,"Zapping (le)","ZAPPING"]) # 130 207 ?
- # Répertoires (à créer avant)
- #HomeDir = os.path.realpath(sys.argv[0])
- #HomeDir = os.path.abspath(sys.argv[0])
- HomeDir = os.path.abspath(sys.argv[0])[:len(os.path.abspath(sys.argv[0]))-len(sys.argv[0])-1]
- DownloadsDir = HomeDir + "/downloads"
- #print HomeDir
- #print DownloadsDir
- #sys.exit()
- #Fichiers
- LogFile = HomeDir + "/cplus_log"
- HistoryFile = HomeDir + "/cplus_history"
- UnwantedFile = HomeDir + "/cplus_unwanted"
- # Paramètres Web de Canal +
- ShowURL_XML = "http://www.canalplus.fr/rest/bootstrap.php?/bigplayer/getMEAs/"
- VideoURL_XML = "http://www.canalplus.fr/rest/bootstrap.php?/bigplayer/getVideos/"
- # Autres variables
- #Verbose = 1
- Verbose = 0
- #Test = True
- Test = False
- Quality = "SD"
- #Quality = "MD"
- #Quality = "HD"
- # fonction: Affichage de la syntaxe et exit si mauvaise syntaxe
- def Syntax():
- print "cplus.py [--help] [--verbose (1|2)] [--test] [--QUALITY] [--outdir OUTDIR_PATH]" + '\n'
- print "--help: affiche cet écran d'aide" + '\n'
- print "--verbose: affiche les infos à l'écran en + des logs"
- print " 1: verbose minimum"
- print " 2: verbose maximum" + '\n'
- print "--test: ne lance pas les téléchargements (fichier d'historique non mis à jour)" + '\n'
- print "--QUALITY: choix de la qualité"
- print " SD: slow definition"
- print " MD: medium definition"
- print " HD: high definition"
- print "--outdir: désigne le répertoire de téléchargement"
- sys.exit()
- # fonction: Télécharge un XML à partir d'une URL
- def DownloadXML(_URL):
- try:
- _XMLFileSock = urllib.urlopen(_URL)
- _XMLFile = _XMLFileSock.read()
- except Exception, e:
- return 1
- try:
- _XML = minidom.parseString(_XMLFile)
- except Exception, e:
- _XML = 1
- return _XML
- # fonction: Récupère les ID des vidéos en parsant les balises MEA d'un XML
- def ParseMEAs(_XML):
- _IDs = []
- _MEAs = _XML.getElementsByTagName('MEA')
- for i in _MEAs:
- if i.getElementsByTagName('ID')[0].childNodes != []:
- #_ID = i.getElementsByTagName('ID')[0].childNodes[0].nodeValue
- #_IDs.append(_ID)
- _IDs.append(i.getElementsByTagName('ID')[0].childNodes[0].nodeValue)
- return _IDs
- # fonction: Récupère l'URL d'un fichier en parsant un XML
- def GetVideoURL(_XML):
- _FileURL = []
- _Videos = _XML.getElementsByTagName('VIDEO')
- if Quality == "SD":
- _Quality = "BAS_DEBIT"
- if Quality == "MD":
- _Quality = "HAUT_DEBIT"
- if Quality == "HD":
- _Quality = "HD"
- for i in _Videos:
- try:
- _Video = i.getElementsByTagName('MEDIA')[0].getElementsByTagName('VIDEOS')[0]
- except Exception:
- _Video = ""
- try:
- _RTMP = _Video.getElementsByTagName(_Quality)[0].childNodes[0].nodeValue
- except Exception:
- _RTMP = ""
- _FileURL.append(_RTMP)
- return _FileURL[0]
- # fonction: Exécute une commande et log le résultat dans un fichier de sortie
- def Execute(_Params, _File):
- p = subprocess.Popen(_Params,stdout=_File)
- p.wait()
- return p.returncode
- # fonction: Ajoute une vidéo à l'historique
- def AddHistory(_File):
- HistoryFile_ = open(HistoryFile, 'a')
- HistoryFile_.write(_File.encode('utf-8') + '\n')
- HistoryFile_.close()
- # fonction: Vérifie si un nom de fichier (_File) est présent dans un fichier texte (_CheckFile)
- def Check(_CheckFile, _File):
- _Check = 0
- CheckFile_ = open(_CheckFile, 'r')
- for _Line in CheckFile_:
- _Line = _Line[0:len(_Line) - 2]
- if _Line.decode('utf-8') in _File:
- _Check = 1
- CheckFile_.close()
- return _Check
- # fonction: Initiliase les infos globales
- def InitInfos():
- global ShowName; ShowName = "N/A"
- global ShowID; ShowID = "N/A"
- global ShowURL; ShowURL = "N/A"
- global VideoID; VideoID = "N/A"
- global VideoURL; VideoURL = "N/A"
- global FileName; FileName = "N/A"
- global TargetFile; TargetFile = "N/A"
- global FileURL; FileURL = "N/A"
- global Message; Message = ""
- # fonction: Log les infos globales (et les affiche à l'écran selon la valeur de _Verbose)
- def LogInfos(_LogFile, _Verbose):
- LogFile_ = open(_LogFile, "a")
- if _Verbose > 0: os.system('clear')
- if Test == True:
- line = "---Téléchargements inactifs---" + '\n'
- LogFile_.write(line + '\n')
- if _Verbose > 0: print line
- line = "Emission:"
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = " -Nom: "
- LogFile_.write(line + ShowName + '\n')
- if _Verbose == 2: print line + ShowName
- if _Verbose == 1: print "Emission: " + ShowName
- line = " -ID: " + str(ShowID)
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = " -URL: " + ShowURL + '\n'
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = "Video:"
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = " -ID: " + VideoID
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = " -URL: " + VideoURL + '\n'
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = "Fichier:"
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = " -Nom: "
- LogFile_.write(line + FileName + '\n')
- if _Verbose == 2: print line + FileName
- if _Verbose == 1: print "Fichier: " + FileName
- line = " -Cible: "
- LogFile_.write(line + TargetFile + '\n')
- if _Verbose == 2: print line + TargetFile
- if _Verbose == 1: print "Fichier cible: " + TargetFile
- line = " -URL: " + FileURL + '\n'
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = "Infos:"
- LogFile_.write(line + '\n')
- if _Verbose == 2: print line
- line = Message
- LogFile_.write(line + '\n')
- if _Verbose > 0: print line
- line = "--------------------------------------------------------------------------------------------------------------------------------------------------------"
- LogFile_.write(line + '\n')
- if _Verbose > 0: print line
- LogFile_.close()
- #fonction: Classement alphabétique des lignes d'un fichier
- def SortFile(_TextFile):
- f = open(_TextFile, 'r')
- lines = f.readlines()
- lines.sort()
- f.close()
- f = open(_TextFile, 'w')
- f.writelines(lines)
- f.close()
- # MAIN
- if __name__ == "__main__":
- # Teste l'existance des fichiers textes et les crée si besoin
- if os.path.exists(UnwantedFile) == False:
- UnwantedFile_ = open(UnwantedFile, 'w')
- UnwantedFile_.close()
- else:
- # Classement alphabétique du fichier des non voulus
- SortFile(UnwantedFile)
- if os.path.exists(HistoryFile) == False:
- HistoryFile_ = open(HistoryFile, 'w')
- HistoryFile_.close()
- if os.path.exists(LogFile) == False:
- LogFile_ = open(LogFile, "w")
- LogFile_.close()
- # Lecture de la syntaxe
- if len(sys.argv) > 1:
- i = len(sys.argv)
- j = 1
- while j < i:
- WhileLoop = 1
- if WhileLoop == 1 and sys.argv[j] == "--help":
- Syntax()
- WhileLoop = 0
- if WhileLoop == 1 and sys.argv[j] == "--verbose":
- if isinstance(int(sys.argv[j+1]), int) == True and int(sys.argv[j+1]) >= 1 and int(sys.argv[j+1]) <= 2:
- Verbose = int(sys.argv[j+1])
- j = j+1
- else:
- Syntax()
- WhileLoop = 0
- if WhileLoop == 1 and sys.argv[j] == "--outdir":
- if os.path.exists(sys.argv[j+1]) == True:
- DownloadsDir = sys.argv[j+1]
- j = j+1
- else:
- Syntax()
- WhileLoop = 0
- if WhileLoop == 1 and sys.argv[j] == "--test":
- Test = True
- WhileLoop = 0
- if WhileLoop == 1 and sys.argv[j] == "--MD":
- Quality = "MD"
- WhileLoop = 0
- if WhileLoop == 1 and sys.argv[j] == "--HD":
- Quality = "HD"
- WhileLoop = 0
- if WhileLoop == 1:
- Syntax()
- j = j+1
- else:
- Syntax()
- # Début de la log
- LogFile_ = open(LogFile, "a")
- LogFile_.write("-------------------" + '\n' + time.strftime("%Y.%m.%d %H:%M:%S") + '\n' + "-------------------" + '\n')
- LogFile_.close()
- # Traitement émission par émission
- for x in range(len(ShowList)):
- InitInfos()
- ShowName = ShowList[x][2]
- ShowID = ShowList[x][0]
- ShowURL = ShowURL_XML + str(ShowID)
- ShowXML = DownloadXML(ShowURL)
- if ShowXML == 1:
- Message = "ERREUR : IMPOSSIBLE DE TÉLÉCHARGER LE XML DE L'ÉMISSION."
- LogInfos(LogFile, Verbose)
- else:
- # Traitement vidéo par vidéo pour l'émission en cours
- VideosIDsList = ParseMEAs(ShowXML)
- PreviousTargetFile = ""
- # Comptage des parties d'émissions
- count = 1
- for VideoID in VideosIDsList:
- VideoURL = VideoURL_XML + VideoID
- VideoXML = DownloadXML(VideoURL)
- if VideoXML == 1:
- Message = "ERREUR : IMPOSSIBLE DE TÉLÉCHARGER LE XML DE LA VIDÉO."
- LogInfos(LogFile, Verbose)
- else:
- FileURL = GetVideoURL(VideoXML)
- head, FileName = os.path.split(FileURL)
- # Comparaison du nom de fichier avec le nom supposé
- if not ShowList[x][3] in FileName:
- Message = "Fichier hors émisssion."
- LogInfos(LogFile, Verbose)
- else:
- # Comparaison du nom de fichier avec les fichiers non voulus et déjà téléchargées
- Unwanted = Check(UnwantedFile, FileName)
- History = Check(HistoryFile, FileName)
- if Unwanted + History != 0:
- if Unwanted != 0:
- Message = "Vidéo non voulue."
- LogInfos(LogFile, Verbose)
- elif History != 0:
- Message = "Vidéo déjà téléchargée."
- LogInfos(LogFile, Verbose)
- # Nommage simple du fichier en cours
- else:
- basename, extension = os.path.splitext(FileName)
- words = basename.split('_')
- if len(words) <= 1:
- FileName = "N/A"
- FileURL = "N/A"
- Message = "Nom de fichier indeterminable."
- LogInfos(LogFile, Verbose)
- else:
- # Création du répertoire de l'émission s'il n'existe pas
- if not os.path.isdir(DownloadsDir + "/" + ShowName):
- os.makedirs(DownloadsDir + "/" + ShowName)
- # Formattage de la date
- date = words[ShowList[x][1]]
- date = "20" + date[:2] + "." + date[2:4] + "." + date[-2:]
- # Test des émissions en plusieurs parties
- FileSimpleName = date + "_" + Quality
- TargetFile = DownloadsDir + "/" + ShowName + "/" + FileSimpleName
- if TargetFile in PreviousTargetFile:
- if count == 1 and Test == False:
- os.rename(PreviousTargetFile, PreviousTargetFile[:len(PreviousTargetFile)-4] + "-1" + PreviousTargetFile[len(PreviousTargetFile)-4:])
- count += 1
- FileSimpleName += "-" + str(count) + extension
- else:
- count = 1
- FileSimpleName += extension
- TargetFile = DownloadsDir + "/" + ShowName + "/" + date[:4] + "/" + FileSimpleName
- # Téléchargement via flvstreamer si le protocole utilisé dans l'URL est RTMP
- if FileURL.find("rtmp") != -1:
- #params=['flvstreamer', '-q', '-r', FileURL]
- #params=['flvstreamer', '-r', FileURL]
- params=['rtmpdump', '-r', FileURL]
- if Test == True:
- Message = "(téléchargements inactifs)" + '\n' + "Téléchargement via flvstreamer."
- LogInfos(LogFile, Verbose)
- r = 0
- else:
- Message = "Téléchargement via flvstreamer."
- LogInfos(LogFile, Verbose)
- target_ = open(TargetFile, 'w')
- r = Execute(params, target_)
- target_.close()
- # Téléchargement direct dans les autres cas
- else:
- if Test == True:
- Message = "(téléchargements inactifs)" + '\n' + "Téléchargement direct."
- LogInfos(LogFile, Verbose)
- r = 0
- else:
- Message = "Téléchargement direct."
- LogInfos(LogFile, Verbose)
- try:
- urllib.urlretrieve(FileURL, TargetFile)
- r=0
- except Exception:
- r=1
- # Ajout dans l'historique s'il n'y a pas eu d'erreur
- if r == 0:
- Message += '\n' + "Téléchargement terminé, ajout dans l'historique."
- if Test == False:
- AddHistory(FileName)
- LogInfos(LogFile, Verbose)
- # Suppression du fichier s'il y a eu une erreur
- else:
- Message += '\n' + "ERREUR : PROBLÈME DE TÉLÉCHARGEMENT."
- if Test == False:
- if os.path.exists(TargetFile):
- os.remove(TargetFile)
- LogInfos(LogFile, Verbose)
- # Mémorisation du fichier cible avant de passer au suivant
- PreviousTargetFile = TargetFile
- time.sleep(1)
- # Classement alphabétique du fichier d'historique
- SortFile(HistoryFile)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement