Outils pour utilisateurs

Outils du site


issue71:python

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
issue71:python [2013/05/28 21:20] – [9] fredphil91issue71:python [2013/06/07 14:32] (Version actuelle) – [15] auntiee
Ligne 8: Ligne 8:
 Tv.Show.Name.SxxExx.Episode name here if you care.extension** Tv.Show.Name.SxxExx.Episode name here if you care.extension**
  
-Supposons que vous avez décidé de créer un centre multimédia pour votre salle de séjour. Vous avez un ordinateur dédié à l'excellent programme XBMC. Vous avez passé des jours à ripper vos DVD de films et séries TV sur l'ordinateur. Vous avez fait la recherche et nommé les fichiers correctement. Mais disons que l'une de vos séries préférées est « NCIS », et que vous avez tous les épisodes possibles sur DVD. Vous avez aussi trouvé un endroit qui propose les épisodes actuels. Vous voulez savoir quel sera le prochain épisode et quand il sera diffusé. De plus, vous souhaitez créer une liste de tous les épisodes de séries TV que vous avez pour impressionner vos amis.+Supposons que vous avez décidé de créer un centre multimédia pour votre salle de séjour. Vous avez un ordinateur dédié à l'excellent programme XBMC. Vous avez passé des jours à ripper vos DVD de films et séries TV sur l'ordinateur. Vous avez fait la recherche et nommé les fichiers correctement. Mais disons que l'une de vos séries préférées est « NCIS », et que vous avez tous les épisodes possibles sur DVD. Vous avez aussi trouvé un endroit qui propose les épisodes actuels. Vous voulez savoir quel sera le prochain épisode et quand il sera diffusé. De plus, vous souhaitez créer une liste de tous les épisodes de séries TV que vous avez pour épater vos amis.
  
-C'est le projet que nous allons commencer ce mois-ci. Notre première tâche consiste à fouiller dans le dossier contenant vos émissions de télévision, en récupérant le nom de la sérieet chaque épisode - y compris le nom et le numéro de saisonet le numéro de l'épisode. Toutes ces informations iront dans une base de données pour faciliter le stockage.+C'est le projet que nous allons commencer ce mois-ci. Notre première tâche consiste à fouiller dans le dossier contenant vos émissions de télévision, en récupérant le nom de la série et chaque épisode - y compris le nom et le numéro de la saison et le numéro de l'épisode. Toutes ces informations iront dans une base de données pour faciliter le stockage.
  
 D'après XBMC, vous devriez nommer vos fichiers comme ceci pour chaque épisode : D'après XBMC, vous devriez nommer vos fichiers comme ceci pour chaque épisode :
Ligne 60: Ligne 60:
 and so on. Now that we know what we will be looking for and where it will be, let's move on.** and so on. Now that we know what we will be looking for and where it will be, let's move on.**
  
-La structure de répertoires devrait ressembler à ceci :+La structure du répertoire devrait ressembler à ceci :
  
 émissions émissions
Ligne 88: Ligne 88:
 Which are very common extensions for video files in the media PC world.** Which are very common extensions for video files in the media PC world.**
  
-Il y a très longtemps, nous avons créé un programme pour constituer une base de données contenant nos fichiers MP3. C'était dans le n° 35, je crois, au neuvième épisode de cette série. Nous avions utilisé une routine appelée ParcourirChemin pour entrer récursivement dans tous les dossiers à partir d'un chemin de départ, et récupérer les noms de fichiers avec l'extension « .mp3 ». Nous allons réutiliser une grande partie de cette routine et la modifier pour nos besoins. Dans cette version, nous rechercherons des fichiers vidéo qui ont une des extensions suivantes :+Il y a très longtemps, nous avons créé un programme pour constituer une base de données contenant nos fichiers MP3. C'était dans le n° 35, je crois, au neuvième épisode de cette série. Nous avons utilisé une routine appelée ParcourirChemin pour entrer récursivement dans tous les dossiers à partir d'un chemin de départ, et récupérer les noms de fichiers avec l'extension « .mp3 ». Nous allons réutiliser une grande partie de cette routine et la modifier pour nos besoins. Dans cette version, nous rechercherons des fichiers vidéo qui ont une des extensions suivantes :
  
 .avi .avi
Ligne 95: Ligne 95:
 .mp4 .mp4
  
-Ce sont des extensions très communes pour les fichiers vidéo dans le monde des media PC.+Ce sont des extensions très courantes pour les fichiers vidéo dans le monde des média PC.
  
 ====== 5 ====== ====== 5 ======
Ligne 110: Ligne 110:
 As you can see, we are importing the os, sys and apsw libraries. We've used them all before. We are also importing the re library to support Regular Expressions. We'll touch on that quickly this time, but more in the next article.** As you can see, we are importing the os, sys and apsw libraries. We've used them all before. We are also importing the re library to support Regular Expressions. We'll touch on that quickly this time, but more in the next article.**
  
-Nous allons maintenant commencer avec la première partie de notre projet. Créez un fichier appelé "cherche_fichiers_tv.py​​". Veillez à bien l'enregistrer quand nous avons fini ce mois-ci, parce que nous allons repartir de là le mois prochain.+Nous allons maintenant commencer avec la première partie de notre projet. Créez un fichier appelé "cherche_fichiers_tv.py​​". Veillez à bien l'enregistrer quand nous aurons fini ce mois-ci, parce que nous allons repartir de là le mois prochain.
  
 Commençons avec nos importations : Commençons avec nos importations :
Ligne 120: Ligne 120:
 import re import re
  
-Comme vous pouvez le voir, nous importons les bibliothèques os, sys et apsw. Nous les avons toutes déjà utilisées avant. Nous importons aussi la bibliothèque re pour le support des expressions régulières. Nous allons en parler rapidement cette fois-ci, nous approfondirons dans le prochain article.+Comme vous pouvez le voir, nous importons les bibliothèques os, sys et apsw. Nous les avons toutes déjà utilisées. Nous importons aussi la bibliothèque re pour le support des expressions régulières. Nous allons en parler rapidement cette fois-ci, nous approfondirons dans le prochain article.
  
 ====== 6 ====== ====== 6 ======
Ligne 145: Ligne 145:
 Now all the dull stuff is done, so we can move on the the meat and potatoes of our project. We'll start with the MakeDataBase routine (middle right). Put it right after the imports.** Now all the dull stuff is done, so we can move on the the meat and potatoes of our project. We'll start with the MakeDataBase routine (middle right). Put it right after the imports.**
  
-Mes fichiers TV sont situés sur deux disques durs. J'ai donc créé une liste pour contenir les chemins. Si vous avez un seul endroit, vous pouvez modifier les trois lignes comme suit :+Mes fichiers TV se trouvent sur deux disques durs. J'ai donc créé une liste pour contenir les chemins. Si vous avez un seul endroit, vous pouvez modifier les trois lignes comme suit :
  
     dossierDepart = "/chemin/dossier/"     dossierDepart = "/chemin/dossier/"
Ligne 167: Ligne 167:
 for file in [f for f in files if f.endswith <nowiki>(('.avi','mkv','mp4','m4v'))]:</nowiki>** for file in [f for f in files if f.endswith <nowiki>(('.avi','mkv','mp4','m4v'))]:</nowiki>**
  
-Nous avons déjà discuté de cette routine lorsque nous avons traité le scanner MP3, donc je vais juste vous rappeler que, dans cette routine, nous vérifions pour voir si la table existeet sinon nous la créons.+Nous avons déjà discuté de cette routine lorsque nous avons traité le scanner MP3, donc je vais juste vous rappeler que, dans cette routine, nous vérifions pour voir si la table existe etsinonnous la créons.
  
 Maintenant, nous allons créer la routine ParcourirChemin (à droite, deuxième à partir du bas). Maintenant, nous allons créer la routine ParcourirChemin (à droite, deuxième à partir du bas).
  
-Lorsque nous entrons dans la routine (comme nous l'avons expliqué à l'époque), nous indiquons le chemin que nous allons parcourir. Nous vidons la variable nomEmission, que nous utiliserons plus tard, et ouvrons un fichier de log d'erreur. Ensuite, nous laissons la routine faire son boulot. Nous récupérons de l'appel (os.walk) un triplet (chemin du répertoire, noms de répertoires, noms de fichiers). Chemin du répertoire est une chaîne contenant le chemin vers le répertoire, noms de répertoire est une liste des noms des sous-répertoires dans le chemin, et noms de fichiers est une liste de noms des non-répertoires. Nous analysons ensuite la liste des noms de fichiers, pour vérifier si le nom se termine par une de nos extensions cibles.+Lorsque nous entrons dans la routine (comme nous l'avons expliqué à l'époque), nous indiquons le chemin que nous allons parcourir. Nous vidons la variable nomEmission, que nous utiliserons plus tard, et ouvrons un fichier de log d'erreur. Ensuite, nous laissons la routine faire son boulot. Nous récupérons de l'appel (os.walk) un triplet (chemin du répertoire, noms de répertoires, noms de fichiers). Chemin du répertoire est une chaîne contenant le chemin vers le répertoire, noms de répertoires est une liste des noms des sous-répertoires dans le chemin, et noms de fichiers est une liste de noms des non-répertoires. Nous analysons ensuite la liste des noms de fichiers, pour vérifier si le nom se termine par une de nos extensions cibles.
  
 for fic in [f for f in fichiers if f.endswith <nowiki>(('.avi','mkv','mp4','m4v'))]:</nowiki> for fic in [f for f in fichiers if f.endswith <nowiki>(('.avi','mkv','mp4','m4v'))]:</nowiki>
Ligne 187: Ligne 187:
 Maintenant, nous découpons le nom de fichier en séparant l'extension et le nom du fichier (sans l'extension). Ensuite, nous appelons la routine RecupereSaisonEpisode pour avoir l'information de saison/épisode qui se trouve dans le nom du fichier, en supposant qu'il est correctement formaté. Maintenant, nous découpons le nom de fichier en séparant l'extension et le nom du fichier (sans l'extension). Ensuite, nous appelons la routine RecupereSaisonEpisode pour avoir l'information de saison/épisode qui se trouve dans le nom du fichier, en supposant qu'il est correctement formaté.
  
-ONomFicOriginal,ext = os.path.splitext(fic)+NomFicOriginal,ext = os.path.splitext(fic)
  
 fl = fic fl = fic
Ligne 196: Ligne 196:
  
 ====== 10 ====== ====== 10 ======
-Next (middle  right), we will check to see if the file is in the database. If so, we don't want to duplicate it. We simply check for the filename. We could go deeper and make sure the path is the same as well, but for this time, this is enough.+**Next (middle  right), we will check to see if the file is in the database. If so, we don't want to duplicate it. We simply check for the filename. We could go deeper and make sure the path is the same as well, but for this time, this is enough.
  
-If everything works as it should, the response from the query should only be a 1 or a 0. If it's a 0, then it's not there, and we will write the information to the database. If it is, we just move past. Notice the Try Except commands above and below. If something goes wrong, like some character that the database doesn't like, it will keep the program from aborting. We will, however, log the error so we can check it out later on.+If everything works as it should, the response from the query should only be a 1 or a 0. If it's a 0, then it's not there, and we will write the information to the database. If it is, we just move past. Notice the Try Except commands above and below. If something goes wrong, like some character that the database doesn't like, it will keep the program from aborting. We will, however, log the error so we can check it out later on.** 
 + 
 +Ensuite (au milieu à droite), nous vérifions si le fichier est dans la base de données. Si c'est le cas, il ne faut pas le dupliquer. Nous vérifions simplement le nom du fichier. Nous pourrions aller plus loin et vérifier que le chemin est aussi le même, mais pour cette fois, c'est assez. 
 + 
 +Si tout fonctionne correctement, la réponse de la requête ne devrait être que 1 ou 0. Si c'est 0, alors il n'est pas présent et nous allons écrire l'information dans la base de données. Sinon, nous passons à la suite. Remarquez la commande try/except au-dessus et en-dessous. Si quelque chose va mal, comme un caractère que la base n'aime pas, cela empêchera le programme de s'arrêter. Cependant, nous enregistrerons l'erreur afin de pouvoir vérifier plus tard.
  
 ====== 11 ====== ====== 11 ======
-We are simply inserting a new record into the database or writing to the error file.+**We are simply inserting a new record into the database or writing to the error file.
  
             # Close the log file             # Close the log file
Ligne 212: Ligne 216:
 def GetSeasonEpisode(filename): def GetSeasonEpisode(filename):
     filename = filename.upper()     filename = filename.upper()
-    resp = re.search(r'(.*).S\d\dE\d\d(\.*)', filename, re.M|re.I)+    resp = re.search(r'(.*).S\d\dE\d\d(\.*)', filename, re.M|re.I)** 
 + 
 +Nous insérons simplement un nouvel enregistrement dans la base de données ou écrivons dans le fichier d'erreur. 
 + 
 +             # ferme le fichier de log 
 +             ficerr.close 
 +      # Fin de ParcourirChemin 
 + 
 +Maintenant, regardons la routine RecupereSaisonEpisode. 
 + 
 +  # ========================================= 
 +  def RecupereSaisonEpisode(nomfic): 
 +    nomfic = nomfic.upper() 
 +    resp = re.search(r'(.*).S\d\dE\d\d(\.*)', nomfic, re.M|re.I)  
  
 ====== 12 ====== ====== 12 ======
-The re.search portion of the code is part of the re library. It uses a pattern string, and, in this case, the filename that we want to parse. The re.M|re.I are parameters that say that we want to use a multiline type search (re.M) combined with an ignore-case (re.I). As I said earlier, we'll deal with the regular expressions more next month, since our routine will match only one type of series|episode string. As for the search pattern we are looking for: ".S", followed by two decimal numbers, followed by an uppercase "E", then two more numbers, then a period. If our filename looked like "tvshow.S01E03.avi", this would match. However, some people encode their shows like this "tvshow.s01e03.avi", or "tvshow.103.avi", which makes it harder to deal with. We'll modify this routine next month to cover the majority of the instances. The "r'" allows for a raw string to be used within the search.+**The re.search portion of the code is part of the re library. It uses a pattern string, and, in this case, the filename that we want to parse. The re.M|re.I are parameters that say that we want to use a multiline type search (re.M) combined with an ignore-case (re.I). As I said earlier, we'll deal with the regular expressions more next month, since our routine will match only one type of series|episode string. As for the search pattern we are looking for: ".S", followed by two decimal numbers, followed by an uppercase "E", then two more numbers, then a period. If our filename looked like "tvshow.S01E03.avi", this would match. However, some people encode their shows like this "tvshow.s01e03.avi", or "tvshow.103.avi", which makes it harder to deal with. We'll modify this routine next month to cover the majority of the instances. The "r'" allows for a raw string to be used within the search.
  
 Continuing on, the search returns a match object that we can look at. "resp" is a response that is empty if there is no match, and, in this case, two groups of returned information. The first one will give us the characters up to the match, and the second including the match. So, in the case above, group(1) would be "tvshow", and the second group would be "tvshow.S01E03.". This is specified by the parens in the search "(.*)" and "(\.*)". Continuing on, the search returns a match object that we can look at. "resp" is a response that is empty if there is no match, and, in this case, two groups of returned information. The first one will give us the characters up to the match, and the second including the match. So, in the case above, group(1) would be "tvshow", and the second group would be "tvshow.S01E03.". This is specified by the parens in the search "(.*)" and "(\.*)".
  
     if resp:     if resp:
-        showname = resp.group(1)+        showname = resp.group(1)** 
 + 
 +La partie re.search du code vient de la bibliothèque re. Elle utilise un modèle de chaîne et, dans ce cas, le nom du fichier que l'on veut analyser. re.M|re.I sont des paramètres qui disent que nous voulons utiliser une recherche de type multiligne (re.M) indépendante de la casse (re.I). Comme je l'ai dit précédemment, nous parlerons plus des expressions régulières le mois prochain, car notre routine correspondra à un seul type de chaîne de série/épisode. En ce qui concerne le modèle de recherche, nous recherchons : « .S » suivi de deux chiffres, suivis par « E » puis deux autres chiffres, puis un point. Si notre nom de fichier ressemblait à « tvshow.S01E03.avi », cela correspondrait. Cependant, certaines personnes codent leurs émissions ainsi : «tvshow.s01e03.avi », ou « tvshow.103.avi », ce qui rend la recherche plus difficile. Nous allons modifier cette routine le mois prochain pour couvrir la majorité des cas. Le « r' » permet qu'une chaîne brute soit utilisée pour la recherche. 
 + 
 +Ensuite, la recherche retourne un objet correspondant que nous pouvons regarder. « rep » est une réponse qui est vide si aucune correspondance n'est trouvée, et, dans ce cas, deux morceaux d'information retournés. Le premier va nous donner les caractères jusqu'à la chaîne recherchée, et le second contiendra cette chaîne. Ainsi, dans le cas ci-dessus, group(1) serait « tvshow » et le second groupe serait « tvshow.S01E03. ». Ceci est spécifié par les parenthèses de la recherche « (.*) » et « (\.*) ». 
 + 
 +    si rep : 
 +        nomEmission = rep.group(1)
  
 ====== 13 ====== ====== 13 ======
-We take the show name from group number one. Then we get the length of that so we can grab the series and episode string with a substring command.+**We take the show name from group number one. Then we get the length of that so we can grab the series and episode string with a substring command.
  
         shownamelength = len(showname) + 1         shownamelength = len(showname) + 1
Ligne 232: Ligne 256:
 Next, we replace any periods in the showname with a space – to be more "Human Readable". Next, we replace any periods in the showname with a space – to be more "Human Readable".
  
-        showname = showname.replace("."," ")+        showname = showname.replace("."," ")** 
 + 
 +Nous récupérons le nom de l'émission dans le premier groupe. Puis nous calculons sa longueur de façon à pouvoir récupérer la série et l'épisode avec une commande de sous-chaîne. 
 + 
 +        longueurNomEmission = len(nomEmission) + 1 
 +        se = nomfic[longueurNomEmission:longueurNomEmission+6] 
 +        saison = se[1:3] 
 +        episode = se[4:6] 
 + 
 +Ensuite, nous remplaçons tous les points de nomEmission par une espace, pour les rendre plus « lisibles par l'utilisateur ». 
 + 
 +         nomEmission = nomEmission.replace("."," ")
  
 ====== 14 ====== ====== 14 ======
-We create a list to include the show name, season and episode, and return it along with the True boolean to say things went well.+**We create a list to include the show name, season and episode, and return it along with the True boolean to say things went well.
  
         ret = [showname,season,episode]         ret = [showname,season,episode]
Ligne 241: Ligne 276:
  
 Otherwise, if we didn't find a match, we create our list containing no show name and two "-1" numbers, and this gets returned with a boolean False. Otherwise, if we didn't find a match, we create our list containing no show name and two "-1" numbers, and this gets returned with a boolean False.
 +
 +    else:
 +        ret = ["",-1,-1]
 +        return False,ret**
 +
 +Nous créons une liste contenant le nom de l'émission, la saison et l'épisode, et la retournons avec le booléen True pour dire que les choses se sont bien passées.
 +
 +        ret = [nomEmission,saison,episode]
 +        return True,ret
 +
 +Sinon, si nous n'avons pas trouvé de correspondance, nous créons notre liste avec aucun nom de spectacle et deux « -1 », et la renvoyons avec un booléen False.
  
     else:     else:
Ligne 247: Ligne 293:
  
 ====== 15 ====== ====== 15 ======
-That's all the code. Now let's see what the output would look like. Assuming your file structures are exactly like mine, some of the output on the screen would look like this...+**That's all the code. Now let's see what the output would look like. Assuming your file structures are exactly like mine, some of the output on the screen would look like this...
  
 Season 02 Episode 04 Season 02 Episode 04
Ligne 265: Ligne 311:
 Next time, we will deal with more Season|Episode formats, and do some other things to flesh out our program. Next time, we will deal with more Season|Episode formats, and do some other things to flesh out our program.
  
-See you soon.+See you soon.** 
 + 
 +Voilà tout le code. Maintenant, regardons à quoi le résultat devrait ressembler. En supposant que votre structure de fichier est exactement comme la mienne, une partie de l'affichage devrait ressembler à ceci : 
 + 
 +Saison 02 Episode 04 
 +SELECT count(pkid) as nbLignes from EmissionsTV where NomFichier = "InSecurity.S02E04.avi"; 
 +Serie - INSECURITY Fichier - InSecurity.S02E04.avi 
 +Saison 01 Episode 08 
 +SELECT count(pkid) as nbLignes from EmissionsTV where NomFichier = "Prime.Suspect.US.S01E08.Underwater.avi"; 
 +Serie - PRIME SUSPECT US Fichier - Prime.Suspect.US.S01E08.Underwater.avi 
 + 
 +et ainsi de suite. Vous pouvez raccourcir la sortie si vous voulez pour éviter que l'écran ne vous rende fou. Comme nous le disions plus haut, chaque élément que nous trouvons sera placé dans la base de données. Quelque chose comme ceci : 
 + 
 +pkID | Serie | Chemin Racine                    | Nom du fichier              | Saison | Episode 
 +2526 | NCIS   | /extramedia/tv_files/NCIS/Season 7|NCIS.S07E04.Good.Cop.Bad.Cop.avi | 7  | 4 
 + 
 +Comme toujours, l'intégralité du code est disponible sur PasteBin.com à http://pastebin.com/p25nwCZM
  
 +La prochaine fois, nous traiterons un peu plus les formats de saison/épisode et ferons d'autres choses pour étoffer notre programme.
  
-code en français +À bientôt.
-http://pastebin.com/g0EaGUsq+
  
issue71/python.1369768827.txt.gz · Dernière modification : 2013/05/28 21:20 de fredphil91