PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/Arte.py

https://code.google.com/p/tvdownloader/
Python | 517 lines | 435 code | 15 blank | 67 comment | 8 complexity | c0aad867185eddaa92751fe9b313fe25 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, LGPL-2.1
  1. #!/usr/bin/env python
  2. # -*- coding:Utf-8 -*-
  3. #########################################
  4. # Licence : GPL2 ; voir fichier COPYING #
  5. #########################################
  6. # Ce programme est libre, vous pouvez le redistribuer et/ou le modifier selon les termes de la Licence Publique Générale GNU publiée par la Free Software Foundation (version 2 ou bien toute autre version ultérieure choisie par vous).
  7. # Ce programme est distribué car potentiellement utile, mais SANS AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties de commercialisation ou d'adaptation dans un but spécifique. Reportez-vous à la Licence Publique Générale GNU pour plus de détails.
  8. # Vous devez avoir reçu une copie de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, États-Unis.
  9. ###########
  10. # Modules #
  11. ###########
  12. import os
  13. from Plugin import Plugin
  14. from Fichier import Fichier
  15. from urllib import quote,unquote
  16. import re,unicodedata
  17. import time,rfc822 # for RFC822 datetime format (rss feed)
  18. from datetime import datetime
  19. from htmlentitydefs import name2codepoint
  20. ##########
  21. # Classe #
  22. ##########
  23. class Arte(Plugin):
  24. ##
  25. ## Arte Live Web
  26. ##
  27. configArteLiveWeb = {
  28. 'nom' : "Arte Live Web",
  29. 'qualite' : ['SD', 'HD', 'Live'],
  30. 'regexEmissions' : {
  31. 'url' : "http://liveweb.arte.tv/",
  32. # Attention à bien nommer les zones de recherche "lien" et "nom"
  33. 'pattern' : re.compile("<li><a href=\"http://liveweb.arte.tv/fr/cat/(?P<lien>.*?)\" class=\"accueil\">(?P<nom>.*?)</a></li>", re.DOTALL)
  34. },
  35. 'regexListeFichiers' : {
  36. 0 : {
  37. # %emission% représente l'émission à lister
  38. 'url' : "http://liveweb.arte.tv/fr/cat/%emission%",
  39. 'pattern' : re.compile("<a href=\"(http://download.liveweb.arte.tv/o21/liveweb/rss/home.*?\.rss)\"", re.DOTALL)
  40. },
  41. 1 : {
  42. # %pattern% représente le résultat de l'expression régulière précédente
  43. 'url' : "%pattern%",
  44. # Expression régulière pour extraire les blocs descriptifs de chaque fichier
  45. 'pattern' : re.compile("(<item>.*?</item>)", re.DOTALL)
  46. },
  47. },
  48. 'regexInfosFichiers' : {
  49. 0 : {
  50. # Premère regex, ne se base pas sur une URL mais sur les données extraites par regexListeFichiers
  51. # Liste des informations à récupérer
  52. 'patterns' : {
  53. 'titre' : re.compile("<title>(.*?)</title>", re.DOTALL),
  54. 'lien' : re.compile("<link>(http://liveweb.arte.tv/fr/video/.*?)</link>", re.DOTALL),
  55. 'date' : re.compile("<pubDate>(.*?)</pubDate>", re.DOTALL),
  56. 'description' : re.compile("<description>(.*?)</description>", re.DOTALL),
  57. #'eventid' : re.compile("<enclosure.*?/event/(.*?)/.*?/>", re.DOTALL),
  58. 'eventid' : re.compile("<enclosure.*?/event/.*?/(.*?)-.*?/>", re.DOTALL)
  59. }
  60. },
  61. 1 : {
  62. # Les variables %xxx% sont remplacées par les éléments déjà trouvés via les expressions précédentes
  63. 'url' : "%lien%",
  64. # optional = 1, cette étape n'est pas exécutée en mode TURBO
  65. 'optional' : 1,
  66. # Liste des informations à récupérer
  67. 'patterns' : {
  68. 'eventid_html': re.compile("new LwEvent\('(.*?)', ''\);", re.DOTALL)
  69. },
  70. },
  71. 2 : {
  72. # Les variables %xxx% sont remplacées par les éléments déjà trouvés via les expressions précédentes
  73. 'url' : "http://arte.vo.llnwd.net/o21/liveweb/events/event-%eventid%.xml",
  74. # Liste des informations à récupérer
  75. 'patterns' : {
  76. 'titre' : re.compile("<nameFr>(.*?)</nameFr>", re.DOTALL),
  77. 'lien.HD': re.compile("<urlHd>(.*?)</urlHd>", re.DOTALL),
  78. 'lien.SD': re.compile("<urlSd>(.*?)</urlSd>", re.DOTALL),
  79. 'lien.Live': re.compile("<liveUrl>(.*?)</liveUrl>", re.DOTALL)
  80. },
  81. },
  82. },
  83. 'infosFichier' : {
  84. 'nom' : "[%qualite%] %titre%",
  85. 'date' : "%date%",
  86. 'lien' : "%lien%",
  87. #'nomFichierSortieStd' : "%lien%",
  88. #'nomFichierSortieRen' : "%titre%",
  89. #~ 'urlImage' : "http://download.liveweb.arte.tv/o21/liveweb/media/event/%eventid%/%eventid%-visual-cropcropcrop-small.jpg",
  90. 'urlImage' : "http://download.liveweb.arte.tv/o21/liveweb/media/event/%eventid%/%eventid%-visual.jpg",
  91. 'descriptif' : "%description%"
  92. }
  93. }
  94. ##
  95. ## Arte+7
  96. ##
  97. # En cas de souci, on pourrait utiliser la page RSS de chaque chaine
  98. # Pour récupérer la liste des chaines (càd la liste des flux RSS)
  99. # http://videos.arte.tv/fr/videos/meta/index-3188674-3223978.html
  100. # Pour récupérer la liste des émissions d'une chaine
  101. # http://videos.arte.tv/fr/do_delegate/videos/programmes/360_geo/index-3188704,view,rss.xml
  102. configArtePlusSept = {
  103. 'nom' : "Arte+7",
  104. 'qualite' : ['SD', 'HD'],
  105. 'regexEmissions' : {
  106. 'url' : "http://videos.arte.tv/fr/videos",
  107. # Attention à bien nommer les zones de recherche "lien" et "nom"
  108. 'pattern' : re.compile("<input type=\"checkbox\" value=\"(?P<lien>.*?)\"/>.*?<a href=\"#\">(?P<nom>.*?)</a>", re.DOTALL)
  109. },
  110. 'regexListeFichiers' : {
  111. 0 : {
  112. # %emission% représente l'émission à lister
  113. 'url' : "http://videos.arte.tv/fr/do_delegate/videos/index-%emission%-3188698,view,asList.html?hash=fr/list/date//1/250/",
  114. # Expression régulière pour extraire les blocs descriptifs de chaque vidéo
  115. 'pattern' : re.compile("(<tr.*?>.*?</tr>)", re.DOTALL)
  116. },
  117. },
  118. 'regexInfosFichiers' : {
  119. 0 : {
  120. # Premère regex, ne se base pas sur une URL mais sur les données extraites par regexListeFichiers
  121. # Liste des informations à récupérer
  122. # Les expressions de type texte %xxx% sont remplacées par les options du plugin (choix arbitraire pour l'instant)
  123. 'patterns' : {
  124. 'titre' : re.compile("title=\"(.*?)\|\|", re.DOTALL),
  125. 'lien' : re.compile("<a href=\"/(fr/videos/.*?\.html)\">", re.DOTALL),
  126. 'date' : re.compile("<em>(.*?)</em>", re.DOTALL),
  127. 'description' : re.compile("\|\|(.*?)\">", re.DOTALL),
  128. 'guid' : re.compile("{ajaxUrl:'.*-(.*?).html", re.DOTALL),
  129. 'player_swf' : "%default_playerSWF%",
  130. }
  131. },
  132. 1 : {
  133. # Les variables %xxx% sont remplacées par les éléments déjà trouvés via les expressions précédentes
  134. 'url' : "http://videos.arte.tv/%lien%",
  135. # optional = 1, cette étape n'est pas exécutée en mode TURBO
  136. 'optional' : 1,
  137. # Liste des informations à récupérer
  138. 'patterns' : {
  139. 'player_swf' : re.compile("<param name=\"movie\" value=\"(.*?\.swf)", re.DOTALL),
  140. 'titre' : re.compile("<div class=\"recentTracksMast\">.*?<h3>(.*?)</h3>.*?</div>", re.DOTALL),
  141. 'image' : re.compile("<link rel=\"image_src\" href=\"(.*?)\"/>", re.DOTALL),
  142. 'description' : re.compile("<div class=\"recentTracksCont\">.*?<div>(.*?)</div>", re.DOTALL),
  143. 'guid': re.compile("addToPlaylistOpen {ajaxUrl:'/fr/do_addToPlaylist/videos/.*?-(.*?)\.html'}", re.DOTALL)
  144. },
  145. },
  146. 2 : {
  147. # Les variables %xxx% sont remplacées par les éléments déjà trouvés via les expressions précédentes
  148. 'url' : "http://videos.arte.tv/fr/do_delegate/videos/-%guid%,view,asPlayerXml.xml",
  149. # Liste des informations à récupérer
  150. 'patterns' : {
  151. 'titre' : re.compile("<name>(.*?)</name>", re.DOTALL),
  152. 'date' : re.compile("<dateVideo>(.*?)</dateVideo>", re.DOTALL),
  153. 'image' : re.compile("<firstThumbnailUrl>(.*?)</firstThumbnailUrl>", re.DOTALL),
  154. 'lien.HD': re.compile("<url quality=\"hd\">(.*?)</url>", re.DOTALL),
  155. 'lien.SD': re.compile("<url quality=\"sd\">(.*?)</url>", re.DOTALL),
  156. },
  157. },
  158. },
  159. 'infosFichier' : {
  160. 'nom' : "[%qualite%] %titre%",
  161. 'date' : "%date%",
  162. 'lien' : "%lien% -W %player_swf%",
  163. #'nomFichierSortieStd' : "%lien%.mp4",
  164. #'nomFichierSortieRen' : "%titre%",
  165. 'urlImage' : "%image%",
  166. 'descriptif' : "%description%"
  167. }
  168. }
  169. ##
  170. ## Options du plugin
  171. ##
  172. listeOptions = {
  173. 0: {
  174. # Qualité à rechercher SD ou HD ?
  175. 'type' : "ChoixUnique",
  176. 'nom' : "qualite",
  177. 'description' : "Qualité des vidéos",
  178. 'defaut' : "HD",
  179. 'valeurs' : ["HD", "SD","HD & SD"],
  180. },
  181. 1: {
  182. # Nombre maximum de fichiers à rechercher (0 = aucune limite)
  183. 'type' : "Texte",
  184. 'nom' : "max_files",
  185. 'description' : "Nombre d'enregistrements à analyser\n(0=pas de limite)",
  186. 'defaut' : "20",
  187. },
  188. 2: {
  189. # Renommer les fichiers à partir du titre de l'émission
  190. 'type' : "Bouleen",
  191. 'nom' : "rename_files",
  192. 'description' : "Renommer les fichiers à partir du titre de l'émission\nATTENTION : plusieurs enregistrements peuvent avoir le même nom",
  193. 'defaut' : False,
  194. },
  195. 3: {
  196. # Mode turbo : charge moins de pages, donc plus rapide, mais moins de détails
  197. 'type' : "Bouleen",
  198. 'nom' : "turbo_mode",
  199. 'description' : "Mode TURBO\nChargement plus rapide mais informations moins détaillées",
  200. 'defaut' : False,
  201. },
  202. 4: {
  203. # PlayerSWF par default pour Arte+7
  204. 'type' : "Texte",
  205. 'nom' : "default_playerSWF",
  206. 'description' : "Player Arte+7 à utiliser par défaut (en mode TURBO)\nATTENTION : Réservé aux utilisateurs avancés",
  207. 'defaut' : "http://videos.arte.tv/blob/web/i18n/view/player_11-3188338-data-4785094.swf",
  208. }
  209. }
  210. nom = "Arte"
  211. url = "http://www.arte.tv/"
  212. listeChaines = {} # Clef = Nom Chaine, Valeur = { Nom emission : Lien }
  213. # Supprime les caractères spéciaux HTML du tyle &#nn;
  214. # http://www.w3.org/QA/2008/04/unescape-html-entities-python.html
  215. # http://bytes.com/topic/python/answers/21074-unescaping-xml-escape-codes
  216. def htmlent2chr(self, s):
  217. def ent2chr(m):
  218. code = m.group(1)
  219. if code.isdigit(): code = int(code)
  220. else: code = int(code[1:], 16)
  221. if code<256: return chr(code)
  222. else: return '?' #XXX unichr(code).encode('utf-16le') ??
  223. return re.sub(r'\&\#(x?[0-9a-fA-F]+);', ent2chr, s)
  224. # Supprime les caractères spéciaux HTML
  225. # http://wiki.python.org/moin/EscapingHtml
  226. def htmlentitydecode(self, s):
  227. return re.sub('&(%s);' % '|'.join(name2codepoint),
  228. lambda m: unichr(name2codepoint[m.group(1)]), s)
  229. # Supprime les caractères spéciaux pour obtenir un nom de fichier correct
  230. def cleanup_filename (self, s):
  231. nouvNom = s
  232. nouvNom = nouvNom.replace(" ","_")
  233. nouvNom = nouvNom.replace(":","_")
  234. nouvNom = nouvNom.replace("/","_")
  235. nouvNom = nouvNom.replace("\\","_")
  236. nouvNom = nouvNom.replace("?","_")
  237. return nouvNom
  238. # Fonction parse_date recopiée de l'application arte+7recorder
  239. # Permet de convertir une date issue d'Arte+7 (hier, aujourd'hui...) en vrai date
  240. def parse_date(self, date_str):
  241. time_re = re.compile("^\d\d[h:]\d\d$")
  242. fr_monthesL = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"]
  243. fr_monthesC = ["janv.", "fevr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."]
  244. de_monthes = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]
  245. date_array = date_str.split(",")
  246. if time_re.search(date_array[-1].strip()) is None:
  247. return ""
  248. time_ = date_array[-1].strip()
  249. if date_array[0].strip() in ("Aujourd'hui", "Heute"):
  250. date_ = time.strftime("%Y/%m/%d")
  251. elif date_array[0].strip() in ("Hier", "Gestern"):
  252. date_ = time.strftime("%Y/%m/%d", time.localtime(time.time() - (24*60*60)))
  253. else:
  254. array = date_array[1].split()
  255. day = array[0].strip(".")
  256. month = array[1]
  257. for arr in (fr_monthesL, fr_monthesC, de_monthes):
  258. if array[1] in arr:
  259. month = "%02d" % (arr.index(array[1])+1)
  260. year = array[2]
  261. date_ = "%s/%s/%s" % (year, month, day)
  262. return date_ + ", " + time_
  263. def __init__(self):
  264. Plugin.__init__(self, self.nom, self.url, 7) #7 = fréquence de rafraichissement
  265. if os.path.exists(self.fichierCache):
  266. self.listeChaines = self.chargerCache()
  267. def debug_savefile (self, buffer):
  268. path = os.path.expanduser( "~" )
  269. fichierDebug = path+"/.tvdownloader/"+self.nom.replace( " ", "_" )+".log"
  270. file = open(fichierDebug, "w")
  271. file.write (buffer)
  272. file.close()
  273. def debug_print (self, variable):
  274. #~ print str(variable).replace("},", "},\n\n").replace("',", "',\n").replace("\",", "\",\n")
  275. print str(variable).replace("{", "\n\n{").replace(", ", ",\n")
  276. def listerOptions(self):
  277. for option in self.listeOptions.values():
  278. if option['type']=="ChoixUnique":
  279. self.optionChoixUnique(option['nom'], option['description'], option['defaut'], option['valeurs'])
  280. elif option['type']=="ChoixMultiple":
  281. self.optionChoixMultiple(option['nom'], option['description'], option['defaut'], option['valeurs'])
  282. elif option['type']=="Texte":
  283. self.optionTexte(option['nom'], option['description'], option['defaut'])
  284. elif option['type']=="Bouleen":
  285. self.optionBouleen(option['nom'], option['description'], option['defaut'])
  286. def rafraichir(self):
  287. self.afficher("Global : Création de la liste des chaines...")
  288. # On remet a 0 la liste des chaines
  289. self.listeChaines.clear()
  290. # On boucle sur chaque "chaine" à analyser
  291. for chaineActuelle in [self.configArteLiveWeb, self.configArtePlusSept]:
  292. self.afficher (chaineActuelle['nom']+" Récupération de la liste des catégories "+chaineActuelle['nom']+"...")
  293. listeEmissions = {}
  294. # On recherche toutes les catégories
  295. for item in re.finditer(chaineActuelle['regexEmissions']['pattern'], self.API.getPage(chaineActuelle['regexEmissions']['url'])):
  296. self.afficher (chaineActuelle['nom']+" ... Catégorie "+item.group('nom')+" : "+item.group('lien')+".")
  297. listeEmissions[item.group('nom')]=item.group('lien')
  298. self.listeChaines[chaineActuelle['nom']] = listeEmissions
  299. # On sauvegarde les chaines trouvées
  300. self.listerOptions()
  301. self.sauvegarderCache(self.listeChaines)
  302. self.afficher("Global : Emissions conservées.")
  303. def listerChaines(self):
  304. liste = self.listeChaines.keys()
  305. liste.sort()
  306. for chaine in liste:
  307. self.ajouterChaine(chaine)
  308. def listerEmissions(self, chaine):
  309. if(self.listeChaines.has_key(chaine)):
  310. self.derniereChaine = chaine
  311. liste = self.listeChaines[chaine].keys()
  312. liste.sort()
  313. for emission in liste:
  314. self.ajouterEmission(chaine, emission)
  315. def getLienEmission(self, emission):
  316. # Cherche dans quelle chaine se trouve l'émission
  317. if(self.listeChaines.has_key(self.derniereChaine)):
  318. listeEmissions = self.listeChaines[ self.derniereChaine ]
  319. if(listeEmissions.has_key(emission)):
  320. return listeEmissions[ emission ]
  321. def chargeListeEnregistrements(self, emission, chaineActuelle):
  322. emissionID = self.getLienEmission(emission)
  323. if emissionID == None:
  324. self.afficher (chaineActuelle['nom']+" Erreur de recherche du lien pour \""+emission+"\"")
  325. return None
  326. else:
  327. self.afficher (chaineActuelle['nom']+" Liste des enregistrements pour \""+emission+"\"...")
  328. pattern = ""
  329. for unItem in chaineActuelle['regexListeFichiers'].values():
  330. #~ print str(chaineActuelle['regexListeFichiers'])
  331. # Construction du lien contenant toutes les émissions de cette catégorie
  332. lienPage = unItem['url'].replace("%emission%", emissionID).replace("%pattern%", pattern)
  333. self.afficher (chaineActuelle['nom']+" ... lecture de la page "+lienPage)
  334. laPage = self.API.getPage(lienPage)
  335. if len(laPage)>0:
  336. foundItems = re.findall(unItem['pattern'], laPage)
  337. pattern = foundItems[0]
  338. self.afficher (chaineActuelle['nom']+" On a listé " + str(len(foundItems)) + " enregistrements.")
  339. else:
  340. self.afficher (chaineActuelle['nom']+" Impossible de charger la page. Aucun enregistrement trouvé !")
  341. foundItems = None
  342. return foundItems
  343. def ajouteFichiers (self, emission, listeEnregistrement, chaineActuelle):
  344. self.afficher (chaineActuelle['nom']+" On ajoute les enregitrements trouvés.")
  345. opt_renameFiles = self.getOption("rename_files")
  346. opt_qual = self.getOption("qualite")
  347. nbLiens = 0
  348. for keyEnregistrement in listeEnregistrement.keys():
  349. # on supprime l'enregistrement avec son index actuel
  350. unEnregistrement = listeEnregistrement.copy()[keyEnregistrement]
  351. for infosQualite in chaineActuelle['qualite']:
  352. infosFichier = {}
  353. if opt_qual.find(infosQualite)>=0:
  354. # Lien dans la qualité voulue
  355. unEnregistrement['lien'] = unEnregistrement.get('lien.'+infosQualite, None)
  356. if unEnregistrement['lien'] == None:
  357. self.afficher (chaineActuelle['nom']+" ... Pas de lien "+infosQualite+" trouvé.")
  358. continue
  359. # Date, mise en forme
  360. rfc_date = rfc822.parsedate(unEnregistrement['date'])
  361. # Format année/mois/jour hh:mm, mieux pour effectuer un tri
  362. unEnregistrement['date'] = time.strftime("%Y/%m/%d %H:%M", rfc_date)
  363. lesInfos = {}
  364. for keyInfo in chaineActuelle['infosFichier'].keys():
  365. uneInfo = chaineActuelle['infosFichier'][keyInfo]
  366. # On effectue les remplacements selon les informations collectées
  367. for unTag in unEnregistrement.keys():
  368. if unEnregistrement[unTag] != None:
  369. uneInfo = uneInfo.replace("%"+unTag+"%", unEnregistrement[unTag])
  370. else:
  371. uneInfo = uneInfo.replace("%"+unTag+"%", "")
  372. # Qualité de la video
  373. uneInfo = uneInfo.replace("%qualite%", infosQualite)
  374. lesInfos[keyInfo] = uneInfo
  375. # Nom fichier
  376. if opt_renameFiles:
  377. nomFichierSortie = self.cleanup_filename(unEnregistrement['titre'])
  378. else:
  379. nomFichierSortie = unEnregistrement['lien'].split('/')[-1]
  380. if nomFichierSortie.find('?')>0:
  381. nomFichierSortie = nomFichierSortie.split('?')[0]
  382. if not re.match(".*\.mp4", nomFichierSortie):
  383. nomFichierSortie = nomFichierSortie+".mp4"
  384. # Ajout du fichier
  385. nbLiens += 1
  386. self.afficher (chaineActuelle['nom']+" Ajoute dans la liste...")
  387. self.afficher (chaineActuelle['nom']+" ... Date : "+ lesInfos['date'])
  388. self.afficher (chaineActuelle['nom']+" ... Nom : "+ lesInfos['nom'])
  389. self.afficher (chaineActuelle['nom']+" ... Lien : " + lesInfos['lien'])
  390. self.afficher (chaineActuelle['nom']+" ... Image : " + lesInfos['urlImage'])
  391. self.afficher (chaineActuelle['nom']+" ... Nom fichier : " + nomFichierSortie)
  392. leFichier = Fichier(
  393. lesInfos['nom'],
  394. lesInfos['date'],
  395. lesInfos['lien'],
  396. nomFichierSortie,
  397. lesInfos['urlImage'],
  398. lesInfos['descriptif']
  399. )
  400. self.ajouterFichier(emission, leFichier)
  401. return nbLiens
  402. def listerEnregistrements(self, emission, chaineActuelle):
  403. opt_maxFiles = int(self.getOption("max_files"))
  404. opt_turbo = self.getOption("turbo_mode")
  405. nbLiens = 0
  406. # Charge la page contenant la liste des émissions
  407. videosList = self.chargeListeEnregistrements(emission, chaineActuelle)
  408. # A-t-on une liste d'enregistrements ?
  409. if videosList != None:
  410. listeEnregistrement = {}
  411. # Boucle sur chaque traitement de recherche
  412. for unItem in chaineActuelle['regexInfosFichiers'].values():
  413. optional = unItem.get('optional',0)
  414. if not (opt_turbo and optional):
  415. if unItem.get('url', None) == None:
  416. # On n'a pas d'url, on travaille sur videoList
  417. # C'est la première passe
  418. nbFichiers = 0
  419. lesPages = {}
  420. for infosVideo in videosList:
  421. lesPages[nbFichiers] = infosVideo
  422. # On crée, et on indexe listeEnregistrement en phase avec videosList
  423. listeEnregistrement[nbFichiers] = {}
  424. nbFichiers += 1
  425. if (opt_maxFiles>0 and nbFichiers>=opt_maxFiles):
  426. break
  427. else:
  428. # Chargement des pages HTML sur lesquelles on va devoir travailler
  429. self.afficher (chaineActuelle['nom']+" Chargement des pages nécessaires...")
  430. listeURL = []
  431. # On boucle sur chaque enregistrement à travailler
  432. for keyEnregistrement in listeEnregistrement.keys():
  433. # on supprime l'enregistrement avec son index actuel
  434. unEnregistrement = listeEnregistrement.pop (keyEnregistrement)
  435. lienHTML = unItem['url']
  436. # On effectue les remplacements des paramètres dans l'url
  437. for unTag in unEnregistrement.keys():
  438. if unEnregistrement[unTag] != None:
  439. lienHTML = lienHTML.replace("%"+unTag+"%", unEnregistrement[unTag])
  440. else:
  441. lienHTML = lienHTML.replace("%"+unTag+"%", "")
  442. listeURL.append(lienHTML)
  443. # on recrée l'enregistrement avec son nouvel index
  444. listeEnregistrement[lienHTML] = unEnregistrement
  445. # On charge les pages désirées
  446. lesPages = self.API.getPages(listeURL)
  447. # On boucle et exécute les expressions régulières
  448. for pageNum in lesPages.keys():
  449. unePage = lesPages[pageNum]
  450. if len(unePage)==0:
  451. self.afficher (chaineActuelle['nom']+" ERREUR : La page "+pageNum+" n'a pas été chargée !")
  452. #~ print "Page : "+repr(unePage)
  453. unEnregistrement = listeEnregistrement[pageNum]
  454. for unTag in unItem['patterns'].keys():
  455. if type(unItem['patterns'][unTag]).__name__==type(re.compile("foo")).__name__:
  456. reFound = re.search(unItem['patterns'][unTag], unePage)
  457. if reFound != None:
  458. unEnregistrement[unTag] = reFound.group(1)
  459. else:
  460. unEnregistrement[unTag] = None
  461. else:
  462. texte = unItem['patterns'][unTag]
  463. for option in self.listeOptions.values():
  464. texte = texte.replace("%"+option['nom']+"%", str(self.getOption(option['nom'])))
  465. unEnregistrement[unTag] = texte
  466. # On ajoute enfin la liste des fichiers à télécharger
  467. nbLiens = self.ajouteFichiers(emission, listeEnregistrement, chaineActuelle)
  468. def listerFichiers(self, emission):
  469. for chaineActuelle in [self.configArteLiveWeb, self.configArtePlusSept]:
  470. if (self.derniereChaine == chaineActuelle['nom']):
  471. self.listerEnregistrements (emission, chaineActuelle)