#!/usr/bin/python # Getmynews.py # Copyright (c) 2001 Florian Hatat # 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 # (at your option) 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, write to the Free Software # Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. """Getmynews.py Crée un arbre à partir des fichiers XML passés sur la ligne de commande à l'aide du module xmllib (Python 1.5.2). """ ################## Quelques paramètres configurables ################## # Mettre à zéro pour désactiver # Options de génération de la section "Quoi d'neuf ?" MAX_NEWS_AGE = 7 # Ne pas afficher les nouvelles plus vieilles de 7 jours MAX_NEWS_DISPLAY = 10 # Nombre maximum de nouvelles à afficher # Options pour les sorties "HTML" et "XML" DATE_RANGE_MAX = 0 # Ces deux options permettent de sélectionner les DATE_RANGE_MIN = 0 # nouvelles dans un intervalle donné ################################# Fin ################################# PROGRAM_USAGE = """Ce script est libre, voir la source pour plus d'informations Usage: getmynews [options] fichier1 fichier2 ... Options: --xml | --html | --neuf format des données générées par le script -v, --debug mode "debug", le script est plus bavard -h, --help affiche ce message Options du format "Neuf" : -a age, --max-news-age=age définit l'âge maximal des nouvelles à afficher -d num, --max-news-display=num nombre maximum de nouvelles à afficher Options des formats "XML" et "HTML" : -s date, --depuis=date sélectionne les nouvelles plus récente que la date "date" -j date, --jusque=date sélectionne les nouvelles plus anciennces que la date "date" utilisez ces options en même temps pour définir un intervalle de temps """ import xmllib import string import sys import random import time import getopt class XMLNews (xmllib.XMLParser): def __init__(self): xmllib.XMLParser.__init__(self) self.mon_arbre = {"children": []} self.actuel, self.pile = self.mon_arbre, [] def handle_xml(self, encoding, standalone): self.mon_arbre["encoding"] = encoding self.mon_arbre["standalone"] = standalone def unknown_starttag(self, tag, attributes): n_element = {"tag" : tag, "attributes" : attributes, "children" : []} self.actuel["children"].append(n_element) self.pile.append(self.actuel) self.actuel = n_element def unknown_endtag(self, tag): self.actuel = self.pile.pop() def handle_data(self, data): if string.lstrip(data) != '': self.actuel["children"].append({"tag" : None, "data" : data}) def output_tag(element, output_my_tag = 0, output_children_tags = 1): """output_tag(elem, output_my_tag = 0, output_children_tags = 1) Retourne la chaîne représentant l'élément "element" passé en argument.""" sortie = '' if element["tag"] == None: return element["data"] if output_my_tag: sortie = "<" + element["tag"] for attribute in element["attributes"].keys(): sortie = sortie + " " + attribute + '="' + \ element["attributes"][attribute] + '"' sortie = sortie + ">" for child in element["children"]: sortie = sortie + output_tag(child, output_children_tags, \ output_children_tags) if output_my_tag: sortie = sortie + "" return sortie NewsList, NewsListFormattee = [], {} options = {} try: optlist, filelist = getopt.getopt(sys.argv[1:], "d:a:vhj:s:", ["max-news-display=", "max-news-age=", "jusque=", "depuis=", "help", "debug", "xml", "html", "neuf"]) for option in optlist: options[option[0]] = option[1] if options.has_key("--help") or options.has_key("-h"): print PROGRAM_USAGE sys.exit(0) if (options.has_key("--xml") + options.has_key("--neuf") + options.has_key("--html")) != 1: raise getopt.error, "précisez un et un seul format de sortie" if options.has_key("--debug") or options.has_key("-v"): def debug_message(message): # sys.stderr.write(message) return else: def debug_message(message): return OUTPUT_FORMAT = options.has_key("--xml") + \ 2 * options.has_key("--html") + \ 3 * options.has_key("--neuf") if options.has_key("-d"): MAX_NEWS_DISPLAY = string.atoi(options["-d"]) if options.has_key("--max-news-display"): MAX_NEWS_DISPLAY = string.atoi(options["--max-news-display"]) if options.has_key("-a"): MAX_NEWS_AGE = string.atoi(options["-a"]) if options.has_key("--max-news-age"): MAX_NEWS_AGE = string.atoi(options["--max-news-age"]) if options.has_key("-j"): DATE_RANGE_MAX = string.atoi(options["-j"]) if options.has_key("--jusque"): DATE_RANGE_MAX = string.atoi(options["--jusque"]) if options.has_key("-s"): DATE_RANGE_MIN = string.atoi(options["-s"]) if options.has_key("--depuis"): DATE_RANGE_MIN = string.atoi(options["--depuis"]) except getopt.error, message: # sys.stderr.write(sys.argv[0] + ": " + message + "\n" + PROGRAM_USAGE) sys.exit(1) except ValueError, message: # sys.stderr.write(sys.argv[0] + ": " + message + "\n" + PROGRAM_USAGE) sys.exit(1) debug_message("Lecture des fichiers\n") for fichier in filelist: debug_message(fichier + ": ouverture ") try: a, f = XMLNews(), open(fichier, "r") debug_message("(ok), analyse ") a.feed(f.read()) debug_message("(ok), fermeture ") f.close() debug_message("(ok)\n") NewsList = NewsList + a.mon_arbre["children"][0]["children"] except RuntimeError, message: debug_message("(erreur), fichier ignoré\n") # sys.stderr.write(sys.argv[0] + ": " + fichier + ": " + \ # "caprice à l'analyse\n") except IOError: debug_message("(erreur), fichier ignoré\n") # sys.stderr.write(sys.argv[0] + ": " + fichier + ": " \ # "caprice à l'ouverture\n") debug_message("Tri des nouvelles\n") t = time.localtime(time.time()) today = t[0] * 10000 + t[1] * 100 + t[2] if MAX_NEWS_AGE: maxold = today - MAX_NEWS_AGE else: maxold = 0 if not DATE_RANGE_MAX: DATE_RANGE_MAX = today for nouvelle in NewsList: # Plusieurs nouvelles peuvent être postées le même jour # Éviter les conflits en ajoutant un suffixe aléatoire # à la date # Passage par string.atoi() pour n'ajouter que la partie # décimale du nombre aléatoire, pour ne pas augmenter la date # ce qui fausserait les comparaisons plus bas if not nouvelle["attributes"].has_key("date"): # sys.stderr.write('Aïe ! nouvelle sans attribut "date" :\n') # sys.stderr.write('"' + string.strip(output_tag(nouvelle)) + # '"\n') continue date_nouvelle = string.atoi(nouvelle["attributes"]["date"]) if date_nouvelle > today: # sys.stderr.write("Aïe ! date future :\n") # sys.stderr.write('"' + string.strip(output_tag(nouvelle)) + # '"\n') continue if NewsListFormattee.has_key(nouvelle["attributes"]["date"]): cle = `date_nouvelle + random.random()` while(NewsListFormattee.has_key(cle)): cle = `date_nouvelle + random.random()` else: cle = nouvelle["attributes"]["date"] # Il peut arriver que des espaces indésirables pour l'esthétique # du document se glissent NewsListFormattee[cle] = string.strip(output_tag(nouvelle)) L = NewsListFormattee.keys() L.sort(); L.reverse() if OUTPUT_FORMAT == 1: # XML debug_message('Génération au format "XML"\n') TXT_HEAD = '\n' TXT_BOTTOM = "" def afficher_nouvelle(date, nouvelle): if DATE_RANGE_MIN <= string.atoi(date) <= DATE_RANGE_MAX: print '\n%s\n' % \ (date, nouvelle) return elif OUTPUT_FORMAT == 2: # HTML debug_message('Génération au format "HTML"\n') TXT_HEAD = """ Nouvelles publiées sur Linux-France

Archive des nouvelles

Généré le """ +`t[2]`+"/"+`t[1]`+"/"+`t[0]`+ """


""" TXT_BOTTOM = "
Date
Nouvelle
\n\n" def afficher_nouvelle(date, nouvelle): mois = (" janvier ", " février ", " mars ", " avril ", " mai ", " juin ", " juillet ", " août ", "septembre", " octobre ", "novembre ", "décembre ") if DATE_RANGE_MIN <= string.atoi(date) <= DATE_RANGE_MAX: date_formattee = date[6:8] + " " + \ mois[string.atoi(date[4:6])-1] + " " +\ date[0:4] print " \n
%s
\n %s\n " % \ (date_formattee, nouvelle) return elif OUTPUT_FORMAT == 3: # Neuf debug_message('Génération au format "Neuf"\n') TXT_HEAD = "" CURRENT_NEWS_NUMBER = 1 def afficher_nouvelle(date, nouvelle): global CURRENT_NEWS_NUMBER if string.atoi(date) < maxold and \ CURRENT_NEWS_NUMBER > MAX_NEWS_DISPLAY and MAX_NEWS_DISPLAY: return print "
  • %s" % (nouvelle) CURRENT_NEWS_NUMBER = CURRENT_NEWS_NUMBER + 1 return print TXT_HEAD for date in L: afficher_nouvelle(date[0:8], NewsListFormattee[date]) print TXT_BOTTOM debug_message("Terminé !\n") sys.exit(0)