Edit 23/04/2012 : Modification du script pour télécharger via http au lieu de rtmp
Mieux vaut tard que jamais, j’ai découvert la série Bref ce week-end.
Cette série diffusé durant le grand-journal fait le buzz et est surtout très drôle, rythmé, bref superbe.
Par contre la regarder en direct pendant le grand journal, ce n’est pas possible pour moi, la regarder en différé sur le site de Canal+ non plus, il me fallait donc trouver un moyen pour la télécharger automatiquement et pouvoir la regarder tranquillement sur mon HTPC.
Il existe divers scripts et programmes pour télécharger les émissions de Canal+, je devais en trouver un qui fonctionne, qui puisse être planifié (exécuté tous les jours et qui garde en mémoire les épisode déjà téléchargés) et surtout headless (en ligne de commande).
Mon point de départ, ce thread d’Ubuntu-fr.org et j’ai trouvé mon bonheur en page 16 avec le script de vincentp010 (recopié en fin d’article)
Ce script en Python se base sur un tableau des ids des émissions à télécharger :
emissions=[ 48, # GUIGNOLS 252, # SAV 254, # GROLAND 201, # ZAPPING 104, # GRAND JOURNAL 249, # PETIT JOURNAL 37, # ACTION DISCRETE 39, # LA MATINALE 47, # PEPITES DU NET 62, # LE BOUCAN DU JOUR 215, # LE MEILLEUR DU HIER ]
Restait à trouver l’id de l’émission Bref.
Après quelques recherches infructueuses je suis tombé sur cette URL qui liste toutes les émissions de Canal+.
Bref à l’id 627, j’ai donc modifié le tableau émission ainsi :
emissions=[ 627, # BREF ]
Paramétré les chemins (penser à créer les répertoires) et nom de fichier :
homedir = os.path.expanduser('~/bin') HISTORIQUE = homedir + "/.cplus_hist" output_dir = "/data/downloads/videos/canalplus"
Installé flvstreamer :
sudo aptitude install flvstreamer
Pour finir le script est planifié en crontab et le boulot est fait….
Script de téléchargement des séries Canal+ de vincentp010 :
#!/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/>. # ########################################################################### # #Script pour telecharger les emission du site canalplus.fr #Fonctionne en theorie sur tous les OS # #Changelog: #V 0.1 #21-12-2010 : Creation #V 0.2 #22-12-2010 : Reglage probleme encodage dans fichier log #V 0.3 #23-12-2010 : Ajout d'une option "--log" et prise en compte de l'absence du tag sous-titre import os, urllib, subprocess, time, sys from xml.dom import minidom # Numeros des emissions a telecharger, commentez celles que vous ne voulez pas emissions=[ 627, # BREF #48, # GUIGNOLS #252, # SAV #254, # GROLAND #201, # ZAPPING #104, # GRAND JOURNAL #249, # PETIT JOURNAL #37, # ACTION DISCRETE #39, # LA MATINALE #47, # PEPITES DU NET #62, # LE BOUCAN DU JOUR #215, # LE MEILLEUR DU HIER ] # Qualite de la video #qualite = "BAS_DEBIT" #qualite = "HAUT_DEBIT" qualite = "HD" # Repertoires (pensez a les creer avant) homedir = os.path.expanduser('~/bin') HISTORIQUE = homedir + "/.cplus_hist" output_dir = "/data/downloads/videos/canalplus" # Ne rien modifier sous cette ligne # Sauf pour ameliorer le fonctionnement ;) logfile = os.path.join(homedir, "canal.log") urlXMLEmissions = "http://www.canalplus.fr/rest/bootstrap.php?/bigplayer/getMEAs/" urlXMLVid = "http://www.canalplus.fr/rest/bootstrap.php?/bigplayer/getVideos/" # Parse Mea file to get videos id def ParseMeas(xmldoc): ids = [] meas = xmldoc.getElementsByTagName('MEA') for i in meas: if i.getElementsByTagName('ID')[0].childNodes != []: id = i.getElementsByTagName('ID')[0].childNodes[0].nodeValue ids.append(id) return ids # Parse video file to get name and url def ParseVid(xmldoc): names = [] urlVids = [] videos = xmldoc.getElementsByTagName('VIDEO') for i in videos: titrage = i.getElementsByTagName('INFOS')[0].getElementsByTagName('TITRAGE')[0] if titrage.getElementsByTagName('TITRE')[0].childNodes != []: titre = titrage.getElementsByTagName('TITRE')[0].childNodes[0].nodeValue if titrage.getElementsByTagName('SOUS_TITRE')[0].childNodes != []: stitre = titrage.getElementsByTagName('SOUS_TITRE')[0].childNodes[0].nodeValue date = "_" + stitre else: date = "" name = titre + date name = name.replace(' ', '.').replace('/', '-') videos = i.getElementsByTagName('MEDIA')[0].getElementsByTagName('VIDEOS')[0] rtmp= videos.getElementsByTagName(qualite)[0].childNodes[0].nodeValue names.append(name) urlVids.append(rtmp) return names, urlVids # Execute command and write stdout in file var def execute(params, file): p = subprocess.Popen(params,stdout=file) p.wait() return p.returncode def addHistory(name): file = open(HISTORIQUE, 'a') file.write(name.encode('utf-8') + '\n') file.close() def checkHistory(name): findvalue = 0 file = open(HISTORIQUE, 'r') for line in file: if line.decode('utf-8') == name + '\n': findvalue = 1 file.close() return findvalue def downXml(url): try: xmlFileSock=urllib.urlopen(url) xmlFile = xmlFileSock.read() except Exception, e: return 1 try: xmldoc = minidom.parseString(xmlFile) except Exception, e: xmldoc = 1 return xmldoc if __name__ == "__main__": debug = False if len(sys.argv) == 2: if sys.argv[1] == "--log": debug = True print "Debug ON" logf = open(logfile, "w") if os.path.exists(HISTORIQUE) == False: file = open(HISTORIQUE, 'w') file.close() for num in emissions: url = urlXMLEmissions + str(num) if debug: logf.write(time.strftime("%Y-%m-%d %H:%M:%S") + '\n') logf.write("Downloading " + url + '\n') xmldoc = downXml(url) if xmldoc == 1: print "Erreur durant la recuperation de la liste " + str(num) if debug: logf.write(url + " download error" + '\n') else: id = ParseMeas(xmldoc) if debug: logf.write("-> Ids " + str(id) + '\n') for vid in id: url2 = urlXMLVid + vid if debug: logf.write("Downloading " + url2 + '\n') xmldoc2 = downXml(url2) if xmldoc2 == 1: if debug: logf.write(url2 + " download error" + '\n') else: names, urlVids = ParseVid(xmldoc2) if debug: logf.write("--> names " + str(names) + '\n') logf.write("---> urlvid " + str(urlVids) + '\n') i = 0 loop = 0 while i < len(names): check = checkHistory(names[i]) if check == 0: if debug: logf.write("Try to download file ") basename, extension = os.path.splitext(urlVids[i]) flvFile = os.path.join(output_dir , names[i] + extension) if urlVids[i].find("rtmp")!=-1: if debug: logf.write("with flvstreamer" + '\n') params=['flvstreamer', '-r', urlVids[i]] file = open(flvFile, 'w') r = execute(params, file) file.close() else: if debug: logf.write("direct download" + '\n') try: urllib.urlretrieve(urlVids[i], flvFile) r=0 except Exception: r=1 # If returncode OK, next file if r == 0: if debug: logf.write("Download finished, add file to history " + '\n') addHistory(names[i]) loop = 0 i += 1 else: if os.path.exists(flvFile): os.remove(flvFile) loop += 1 # After 5 retry abord file if loop == 5: if debug: logf.write("Download aborded" + '\n') i += 1 loop = 0 else: if debug: logf.write("Download error" + '\n') print "Download error, retry in 30 seconds" time.sleep(30) else: print "File already downloaded" if debug: logf.write("File already downloaded" + '\n') i += 1 if debug: logf.close()
PS : si vous cherchez un programme avec une interface graphique qui fait la même chose et bien plus encore, il existe tvdownloader qui est parfait
if urlVids[i].find(« rtmp »)!=-1:
if debug:
logf.write(« with flvstreamer » + ‘\n’)
params=['flvstreamer', '-r', urlVids[i]]
file = open(flvFile, ‘w’)
r = execute(params, file)
file.close()
else:
if debug:
logf.write(« direct download » + ‘\n’)
try:
urllib.urlretrieve(urlVids[i], flvFile)
r=0
except Exception:
r=1