#!/usr/bin/env python
# -*- coding: latin-1 -*-
##
# makeWikiIndex
# Génère une page 'index.htm' de liens vers les pages HTML du répertoire courant
# (pages reconnues si elles proviennent des sites
# everything-list, MathWorld, OEIS, PlanetMath,
# Wikibooks, Wikipedia, Wikiquote ou Wikisource)
# (c) Olivier Pirson --- DragonSoft
# http://www.opimedia.be/DS/
# Débuté le 7 août 2006
# v.01.00 --- 10 août 2006
# v.01.01 --- 17 août 2006
# v.01.02 --- 24 août 2006
# --- 21 septembre 2006
# v.01.03 --- 30 novembre 2006
# v.01.04 --- 7 octobre 2007
# --- 2 mars 2008
# v.01.05 --- 19 mars 2008
# --- 26 mars 2008
# v.01.06 --- 7 avril 2008
# v.01.07 --- 21 mai 2008
# v.01.08 --- 24 juillet 2008 : correction
# v.01.09 --- 12 novembre 2008 : prépare Python 3
# v.01.10 --- 3 mars 2009 : changé regexp Wikipédia
# v.01.11 --- 13 mars 2009 : target="_blank"
# v.01.12 --- 3 avril 2009 : Wikipédia: discussion
# v.01.13 --- 27 septembre 2009 : nouveau site web
# v.01.30 --- 5 novembre 2009 : Python 3
# v.01.31 --- 30 décembre 2009 : (...)
# nb_files et progression *
# signale les "doublons"
# --- 15 mars 2010 : nouveau site web
# --- 2 janvier 2012 : nouveau site web
###########################################################
VERSION = 'v.01.31 --- 2012 January 2'
import codecs
import glob
import os
import re
import sys
import time
assert sys.version_info[0] >= 3, ('DSPython require Python 3 or better', sys.version)
try:
if not 'profile' in dir():
import psyco
psyco.full()
except ImportError:
pass
##############
# Constantes #
##############
RE_ENDHEAD = re.compile('', re.I) # regexp pour la fin de l'en-tête HTML
RE_FORMAT = re.compile(r'', re.I)
# regexp pour le format en lecture du fichier
RE_SITE = re.compile(r'\s*(.+?)\s*', re.I) # regexp pour identifier le site
RE_SITE_EVERYTHING = re.compile('(everything-list)@eskimo.com', re.I)
# regexp pour identifier le site everything-list
RE_SITE_WIKIQUOTE = re.compile('title="wikiquote\s*\((\w\w)\)', re.I)
# regexp pour identifier le site Wikiquote
RE_TITLE = {} # dictionnaire de regexps pour le titre
RE_DATE = {} # dictionnaire de regexps pour la date de dernière modification
RE_AUTHOR = {} # dictionnaire de regexps pour l'auteur
RE_TITLE[None] = re.compile('(.*?)', re.I)
RE_DATE[None] = re.compile(
'', re.I)
RE_AUTHOR[None] = None
# everything-list
RE_TITLE['everything-list'] = RE_TITLE[None]
RE_DATE['everything-list'] = re.compile(
r'\s*\S+?\s+(\d{2}.*?\d{4}).*?', re.I)
RE_AUTHOR['everything-list'] = re.compile(
r'\s*(?:"|")*(.*?)(?:"|")*\s*', re.I)
# MathWorld
RE_TITLE['MathWorld'] = re.compile(
r'(.*?)\s*--\s*?from.+?(?:MathWorld|Eric Weisstein).*?',
re.I)
RE_DATE['MathWorld'] = RE_DATE[None]
RE_AUTHOR['MathWorld'] = None
# OEIS
RE_TITLE['OEIS'] = re.compile('.*PlanetMath:\s*(.*?)', re.I)
RE_DATE['PlanetMath'] = re.compile(r'This is.+?born.+?modified.*?(\d{4}-\d{2}-\d{2})', re.I)
RE_AUTHOR['PlanetMath'] = None
# Wiki...
RE_TITLE['Wikibooks'] = RE_TITLE['Wikipedia.en'] = RE_TITLE['Wikipedia.fr'] \
= RE_TITLE['Wikiquote.en'] = RE_TITLE['Wikiquote.fr'] \
= RE_TITLE['Wikisource'] \
= re.compile(r'.*?([^<>]*).*?', re.I)
RE_DATE['Wikibooks'] = RE_DATE['Wikipedia.en'] = RE_DATE['Wikipedia.fr'] \
= RE_DATE['Wikiquote.en'] = RE_DATE['Wikiquote.fr'] \
= RE_DATE['Wikisource'] \
= re.compile(r'.*?(\d{1,2}\D+\d{4}).*?', re.I)
RE_AUTHOR['Wikibooks'] = RE_AUTHOR['Wikipedia.en'] = RE_AUTHOR['Wikipedia.fr'] \
= RE_AUTHOR['Wikiquote.en'] = RE_AUTHOR['Wikiquote.fr'] \
= RE_AUTHOR['Wikisource'] = None
#############
# Fonctions #
#############
def extract_infos(filename, quiet=False, verbose=False):
"""Renvoie un tuple (nom du site, titre, date, auteur).
Si verbose
alors envoie le nom des fichiers traités sur la sortie standard
pre: filename: nom du fichier"""
if verbose:
print(filename.replace('\u2013', '-'), end=' - ')
sys.stdout.flush()
site, format = identify(filename, quiet)
if verbose:
print(site, end='')
if format != None:
print('-', end='')
try:
print(format, end='')
except:
print('?', end='')
else:
print('-', end='')
sys.stdout.flush()
title = date = author = None
site_str = ('' if site == None
else site)
if site not in RE_TITLE.keys():
site = None
try:
f = codecs.open(filename, 'r', format, 'replace')
except IOError:
print('Failed open %r for reading!!!' % filename, file=sys.stderr)
sys.stderr.flush()
return (None, None, None, None)
# Parcours le fichier à la recherche du titre et de la date
try:
for l in f:
if title == None:
r = RE_TITLE[site].search(l)
if r != None:
title = r.group(1)
if date == None:
r = RE_DATE[site].search(l)
if r != None:
date = r.group(1)
if (author == None) and (RE_AUTHOR[site] != None):
r = RE_AUTHOR[site].search(l)
if r != None:
author = r.group(1)
elif (title != None) and (date != None):
break
except:
print('Failed reading %r!!!' % filename, file=sys.stderr)
sys.stderr.flush()
return (site_str,
title if title != None
else filename,
date, author)
f.close()
if title == None:
title = '[%s]' % filename
if date == None:
date = ''
if verbose:
print('-', end='')
try:
print(title, end='')
except:
print('?', end='')
print('-', end='')
try:
print(date, end='')
except:
print('?', end='')
if author != None:
print('-', end='')
try:
print(author, end='')
except:
print('?', end='')
print()
sys.stdout.flush()
return (site_str, title, date, author)
def help_msg():
"""Affiche le message d'aide sur la sortie des erreurs
et termine le programme par un code d'erreur 1"""
print("""makeWikiIndex [-s] [-h] [-q] [-v] [title]
Make a 'index.htm' file
with links to the '*.htm*' files of the current directory
(pages recognized if came from sites everything-list,
MathWorld, OEIS, PlanetMath,
Wikibooks, Wikipedia, Wikiquote or Wikisource)
(c) Olivier Pirson --- DragonSoft --- http://www.opimedia.be/DS/
%s
-s: print namesite at the begining of each line
title: title of the HTML file 'index.htm'
-h: help
-q: quiet (no print 'Unknow site...' on standard output)
-v: verbose (print filename and infos on error ouptut)""" % VERSION, file=sys.stderr)
sys.exit(1)
def identify(filename, quiet=False):
"""Renvoie (site, format)
où site correspond aux sites
'everything-list', 'MathWorld', 'OEIS', 'PlanetMath',
'Wikibooks', 'Wikipedia.en', 'Wikipedia.fr', 'Wikiquote.en', 'Wikiquote.fr', 'Wikisource'
ou le champ ...
trouvé dans le fichier, ou None si pas trouvé
et format est le format référencé par un "charset=..." dans le fichier
ou None si pas trouvé
Si not quiet
alors envoie les fichiers non reconnus parmi les sites gérés
sont indiquées sur la sortie standard
pre: filename: nom du fichier"""
site = format = None
try:
f = codecs.open(filename, 'r', 'UTF-8', 'replace')
except IOError:
print('Failed open %r for reading!!!' % filename, file=sys.stderr)
sys.stderr.flush()
return (None, None)
# Parcours le fichier
try:
for l in f:
if site == None:
r = RE_SITE.search(l)
if r != None:
site = r.group(1)
else:
r = RE_SITE_WIKIQUOTE.search(l)
if r != None:
site = 'wikiquote.%s' % r.group(1)
else:
r = RE_SITE_EVERYTHING.search(l)
if r != None:
site = r.group(1)
if format == None:
r = RE_FORMAT.search(l)
if r != None:
format = r.group(1)
if RE_ENDHEAD.search(l) != None:
break
except:
print('Failed reading %r!!!' % filename, file=sys.stderr)
sys.stderr.flush()
return (filename, None)
f.close()
# Fixe les résultats pour les 4 sites identifiés par le programme
if site != None:
site_lower = site.lower()
if 'wikipedia' in site_lower:
site = 'Wikipedia.en'
elif 'wikipédia' in site_lower:
site = 'Wikipedia.fr'
elif 'everything-list' == site_lower:
site = 'everything-list'
elif ('mathworld' in site_lower) or ('eric weisstein' in site_lower):
site = 'MathWorld'
elif 'planetmath' in site_lower:
site = 'PlanetMath'
elif 'wikibooks' in site_lower:
site = 'Wikibooks'
elif 'wikiquote.en' == site_lower:
site = 'Wikiquote.en'
elif 'wikiquote.fr' == site_lower:
site = 'Wikiquote.fr'
elif 'wikisource' in site_lower:
site = 'Wikisource'
elif (('encyclopedia of integer sequences' in site_lower) or ('oeis' in site_lower)
or (('encyclo' in site_lower) and ('suites de nombres entiers' in site_lower))):
site = 'OEIS'
elif not quiet:
try:
print('Unknow site of %s: %s!!!' % (filename, site))
except:
print('Unknow site!!!')
sys.stdout.flush()
return (site, format)
########
# Main #
########
if __name__ == '__main__':
if os.path.isfile('index.htm'):
print("'index.htm' file already exist!!! Delete it to execute this script.\n", file=sys.stderr)
help_msg()
# Gestion des options
title_index = None # titre de la page HTML 'index.htm'
opt_namesite = False # mode affiche le nom du site pour chaque ligne
opt_quiet = False # mode silencieux
opt_verbose = False # mode verbeux
for i in range(1, len(sys.argv)):
if sys.argv[i] == '-h':
help_msg()
elif sys.argv[i] == '-q':
opt_quiet = True
elif sys.argv[i] == '-s':
opt_namesite = True
elif sys.argv[i] == '-v':
opt_verbose = True
elif title_index == None and sys.argv[i][0] != '-':
title_index = sys.argv[i]
else:
help_msg()
if title_index == None:
title_index = 'makeWikiIndex --- ' + VERSION
d = {} # dictionnaire dont les clés seront des tuples (nom du site, titre)
# et les éléments une liste de tuple (titre, date, nom du fichier, auteur)
# Parcours les fichiers '*.htm*' du répertoire courant
print('Walk files...', file=sys.stderr, end='')
sys.stderr.flush()
nb_files = 0
for f in glob.glob('*.htm*'):
nb_files += 1
if nb_files%100 == 0:
print('*', file=sys.stderr, end='')
sys.stderr.flush()
site, title, date, author = extract_infos(f, quiet=opt_quiet, verbose=opt_verbose)
if site == 'everything-list':
r = re.search(r'^Re:\s*(.*)', title, re.I)
if r != None:
title = 'Re:'
elif (site == 'Wikipedia.en') or (site == 'Wikiquote.en'):
r = re.search(r'^Talk:\s*(.*)', title, re.I)
if r != None:
title = 'Talk:'
else:
r = re.search(r'^Image:\s*(.*)', title, re.I)
if r != None:
title = 'Image:'
elif ((site == 'Wikipedia.fr') or (site == 'Wikiquote.fr')
or (site == 'Wikibooks') or (site == 'Wikisource')):
r = re.search(r'^Discu(?:ter|ssion):?\s*(.*)', title, re.I)
if r != None:
title = 'Discuter:'
else:
r = re.search(r'^Image:\s*(.*)', title, re.I)
if r != None:
title = 'Image:'
else:
r = None
title_key = (title.lower() if r == None
else r.group(1).lower())
if (site, title_key) in d: # déjà rencontré un fichier du même site et de "même" titre
if title_key == title.lower(): # le lien à ajouter est "primaire"
d[(site, title_key)].insert(0, (title, date, f, author))
else: # le lien à ajouter est "secondaire"
d[(site, title_key)].append((title, date, f, author))
else: # c'est le premier fichier de ce site avec ce titre
d[(site, title_key)] = [(title, date, f, author)]
# Clés de d triées
print('\nSort...', file=sys.stderr)
sys.stderr.flush()
keys = sorted(d, key=lambda t: (t[0].lower(), t[1].lower()))
# Création du fichier 'index.htm'
print('Make "index.htm"...', file=sys.stderr)
sys.stderr.flush()
try:
fout = codecs.open('index.htm', 'w', 'latin-1', 'replace')
except IOError:
sys.exit("Failed open 'index.htm' for writing!!!")
# En-tête HTML
print("""
%s
%s
(%u files)
""" % (VERSION, time.strftime('%Y%m%d'), title_index, title_index, nb_files),
file=fout)
# Parcours d dans l'ordre
for k in keys:
print(('%s | ' % k[0]) if opt_namesite # site
else '
',
file=fout)
(title, date, filename, author) = d[k][0]
if k[1].lower() != title.lower():
# le premier élément de la ligne est "secondaire"
print(' | %s | ' % k[1], file=fout) # title
# Vérifie les "doublons"
if len(d[k]) > 2:
print('%r: ' % repr(k[1]), file=sys.stderr, end='')
lt = []
for t in d[k]:
lt.append(repr(t[2]))
print('%s !' % ', '.join(lt), file=sys.stderr)
sys.stderr.flush()
# Parcours les éléments de la ligne
for (title, date, filename, author) in d[k]:
if author == None:
print((' | %s'
+ ' %s | ')
% (filename, title, date),
file=fout)
else:
print((' | %s'
+ ' (%s) %s | ')
% (filename, title, author, date),
file=fout)
print('
\n', file=fout)
# Fin HTML
print("""
""", file=fout)
fout.close()