# -*- coding: utf-8 -*-
#
# (C) Daniel Herding, 2004
#
# Distributed under the terms of the MIT license.
#
####################################################################################
#
# Version pas mal modifiée pour formater les articles du Wiktionnaire fr
# BUT PRINCIPAL : ranger les sections des articles dans l'ordre conventionnel
# Peut être éventuellement utilisé pour formater une section ciblée
# (par exemple : seulement l'étymologie, seulement les traductions, etc.)
#
####################################################################################
__version__='$Id'
from __future__ import generators
import sys, re
import wikipedia, pagegenerators, catlib, config
from liste_langues import langues
# Liste des messages
msg = {
'fr':u'Robot : structure des articles',
}
# Log des différences (nécessite la déf difflog de wikipedia personnalisé) :
dossier_log = u"log xml/format/"
fichierlog = dossier_log + u"log.txt"
# Attribution des clés pour les langues (dont fr, conv et car) :
c=0
cl= "0000"
langues2 ={}
for lang in langues:
langues2[cl] = lang
c+=1
cl=str(c)
if c<10: cl = "0" + cl
if c<100: cl = "0" + cl
if c<1000: cl = "0" + cl
clesl = langues2.keys()
clesl.sort()
#for c in clesl:
# print c, langues2[c], u" ; ",
types_de_mot0 = ("nom", "loc-nom",
"nom-pr",
"adj", "loc-adj", "adj-dem", "adj-indef", "adj-num", "adj-pos",
"adv", "loc-adv",
"verb", "loc-verb",
"pronom", "pronom-def", "pronom-indef", "pronom-int", "pronom-pos", "pronom-pers", "pronom-rel",
"art", "art-def", "art-indef", "art-part",
"conj", "loc-conj",
"prep", "loc-prep",
"onoma",
"loc", "locution", "prov", "abr",
"symb",
"class",
"part", "post", "suf", "pref", "aff")
section_langue = (
(u"etym", "01"),
(u"pron", "z2" ),
(u"voir", "z5"),
(u"réf", "z6"),
(u"homo", "z3"),
(u"paro", "z4")
)
# Pas encore utilisé car pas décidé (et il en manque quelques uns)
# Ne pas oublier de donner une clef !
# Voir format_type
section_type0 = ("ortho-alt", "syn", "ant", "hyper", "hypo", "hyper", "holo", "mero", "trad", "drv", "apr", "exp", "drv-int", "apr-int")
############################################################
# Deux fonctions utiles de remplacement (dont regex) #
############################################################
def my_repl(original_text, old, new):
new_text = original_text
try:
new_text = old.sub(new, new_text)
except:
new_text = new_text.replace(old, new)
return new_text
def my_replex(text0, old, new):
old = re.compile(old, re.UNICODE)
# changement :
new_text = old.sub(new, text0)
return new_text
def balisage(text, titre):
################################################
# Cette déf balise les sections d'articles #
################################################
# I) BALISAGE DES SECTIONS DE LANGUES
# A) Sections générales, langues particulières, etc.
text = my_repl(text, u"{{-car-}}", u"{{=:car:=}}")
#text = my_repl(text, u"{{=conv=}}", u"{{=:00002conv:=}}")
#text = my_repl(text, u"{{=fr=}}", u"{{=:00003fr:=}}")
# Autres langues
#text = my_replex(text, u"{{=([^:]+?)=}}", r"{{=:\1:=}}")
for lang in langues:
text = my_repl(text, u"{{="+ lang + u"=}}", u"{{=:"+ lang + u":=}}")
# Les catégories aussi :
text = my_repl(text, u"[[catégorie:",u"[[Catégorie:")
try:
categorie_start = re.search(u"\[\[Catégorie\:([^\]]*)\]\]", text).start()
text = text[:categorie_start]+ u"{{=:zz3:cat:=}}" + text[categorie_start:]
# Si pas de catégories :
except:
try:
interwiki_start = re.search(u"\[\[...?:.+?\]\]", text).start()
text = text[:interwiki_start]+ u"{{=:zz3:cat:=}}" + text[interwiki_start:]
except:
text += u"\n{{=:zz3:cat:=}}"
print "Pas de catégorie ni d'interwikis"
# B) BALISAGE DES SECTIONS INTRA-LANGUES
text = my_repl(text, u"{{-etym-}}", u"{{--:etym:--}}")
text = my_repl(text, u"{{-pron-}}", u"{{--:pron:--}}")
text = my_repl(text, u"{{-homo-}}", u"{{--:homo:--}}")
text = my_repl(text, u"{{-paro-}}", u"{{--:paro:--}}")
text = my_repl(text, u"{{-voir-}}", u"{{--:voir:--}}")
text = my_repl(text, u"{{-réf-}}", u"{{--:réf:--}}")
# Attention : types numérotés !
text = my_replex(text, u"-\|([1-9]+?)\}\}", r"-}}___num_\1__")
# Et types
for typ in types_de_mot0:
text = my_repl(text, u"{{-"+ typ + u"-}}", u"{{--:"+ typ + u":.-}}")
# C) Sections intra-type (à faire)
return text
def debalisage(text, titre):
############################################################
# Cette déf enlève les balises des sections d'articles #
############################################################
# Sections générales
text = my_repl(text, u"{{=:car:=}}", u"{{-car-}}")
#text = my_repl(text, u"{{=:00002conv:=}}", u"{{=conv=}}")
#text = my_repl(text, u"{{=:00003fr:=}}", u"{{=fr=}}")
text = my_replex(text, u"{{=:([^:]+?):=}}", r"{{=\1=}}")
# Catégories
text = my_repl(text, u"\n{{=:zz3:cat:=}}__rien__", u"")
text = my_repl(text, u"{{=:zz3:cat:=}}", u"")
# Sections intra-langues
text = my_repl(text, u"{{--:etym:--}}", u"{{-etym-}}")
text = my_repl(text, u"{{--:ron:--}}", u"{{-pron-}}")
text = my_repl(text, u"{{--:homo:--}}", u"{{-homo-}}")
text = my_repl(text, u"{{--:paro:--}}", u"{{-paro-}}")
text = my_repl(text, u"{{--:voir:--}}", u"{{-voir-}}")
text = my_repl(text, u"{{--:réf:--}}", u"{{-réf-}}")
# Plus celle de la fusion des types, déf format_langue
text = my_replex(text, u"{{--:(.+?):.-}}", r"{{-\1-}}")
text = my_replex(text, u"{{--:(.+?):--}}", r"{{-\1-}}")
# Attention : types numérotés !
text = my_replex(text,u"-}}___num_([1-9][1-9]?)__", r"-|\1}}")
return text
# C) Sections intra-type (à faire)
def format_article(text, titre):
############################################################
# Cette déf formate la structure générale des articles #
############################################################
articles = {}
catentro = {}
itwentro = {}
categories = u''
# Préboulot lourd : rapatrier les catégories qui trainent partout et qui font tout planter mon bot...
text, catentro, itwentro = rapatri_cat(text)
# I) Séparation de l'article en morceaux
parties = text.split(u"{{=:")
# Vérification de la teneur des sections séparées
for i, p in enumerate(parties):
search = re.search(u":=}}", p)
# S'il le trouve : c'est une section
if search:
end = search.start()
cle = p[:end]
article = u"{{=:" + p
# Si cette section n'est pas une section de catégorie :
if cle <>"zz3:cat":
article = format_langue(article, cle, titre)
# Vérification que c'est une langue enregistrée, et dans ce cas on lui donne sa valeur
for clf in clesl:
if cle == langues2[clf]:
cle = clf
# Puis enregitrement
articles[cle] = article
if cle == "zz3:cat":
categories = my_repl(article, u"{{=:zz3:cat:=}}", u"")
# Sinon c'est le début (normalement)
else:
articles["0"] = p
# Ajout à la section catégorie des éléments cat et int en trop
articles["zz3:cat"] = format_cat(categories, titre, catentro, itwentro)
resultat = u""
cles = articles.keys()
cles.sort()
print "\nOrdre : ",
for clf in cles:
if clf=="0":
print "DEBUT",
else:
try:
print langues2[clf],
except:
print clf,
print "\n"
# Recommposition de l'article fragmenté ordre simple
for c in cles:
#print "Tri=", repr(c)
resultat += articles[c]
return resultat
def format_langue(text, lang, titre):
##################################################################
# Cette déf formate la structure dans les sections de langue #
##################################################################
# Sachant que text est une section de langue bien isolée
text = my_replex(text, "\n+", "\n")
# Recherche des sous-sections
print "\nFormatage de la partie " + lang + " : "
parties = text.split(u"{{--:")
articles2 = {}
# Vérification de la teneur des sections séparées
types = u""
for i, n in enumerate(parties):
# Types de mot ?
search2 = None
search2 = re.search(u":\.-}}", n)
# S'il le trouve : c'est une section de type de mot
if search2 <> None:
finom = search2.start()
nom = n[:finom]
print nom, u"est une section de type"
ntyp = format_type(n, lang, titre)
types += (u"{{--:" + ntyp)
else:
#Autres sections
search3 = 0
search3 = re.search(u":--}}", n)
# S'il le trouve : c'est une section
if search3 <> None:
end2 = search3.start()
cle2 = n[:end2]
print cle2, u"est une section non-type, clé = ",
for nom, clef in section_langue:
if nom == cle2:
articles2[clef] = u"{{--:" + n
print clef
if cle2 == "pron":
articles2[clef] = format_pron(articles2[clef], lang, titre)
elif cle2 == "etym":
articles2[clef] = format_etym(articles2[clef], lang, titre)
# Sinon c'est le début (normalement)
else:
if n <> u"" :
cle2 = u"%i" % i
articles2[cle2] = n
print cle2, u" est le début de la section"
# Ajout dans l'articles2
articles2["02"] = types
resultat2 = u""
cles2 = articles2.keys()
cles2.sort()
# Donne le nouvel ordre des clés
#print articles2.keys()
# Recommposition de l'article fragmenté ordre simple
for c in cles2:
#print "Tri2=", repr(c)
resultat2 += articles2[c]
return resultat2
def format_type(text, lang, titre):
##################################################################
# Cette déf formate la structure de la section de type de mot #
# beta : juste les déf pour le moment, en attendant qu'une #
# décision soit prise sur l'ordre des sous-sections. #
##################################################################
print u" * Formatage des définitions :\n -> ",
text0 = text
# Format probablement à refaire à la main
if re.search(u"\n##", text):
chemf = open(u"log xml/format/bug.txt", "a")
titre = u"\n" + text + u"\n"
chemf.write(titre.encode('utf8'))
chemf.close()
text = my_replex(text, u"\n##", r"\n__dou__\n#")
text = my_replex(text, u"\n#:", r"\n___ex___")
# Boucle pour protéger les term
num=0
while num<40:
text = my_replex(text, u"\n# \{\{ébauche-déf\|(...?)\}\}", r"\n# Eb_\1__\n")
text = my_replex(text, u"\n# ?\{\{(.+?)\}\}", r"\n___term_\1___\n# ")
num +=1
# S'il n'y a rien sur la ligne
text = my_replex(text, u"\n# ?…\n", u"\n# {{ébauche-déf|" + lang + u"}}\n")
# Points en fin de phrase...
# D'abord : éviter les espaces en fin de ligne
text = my_replex(text, u"(\n.+?) +?(\r)", r"\1\2")
text = my_replex(text, u"(\n# [^\r^\n]+?) (\n)", r"\1\2")
#text = my_replex(text, u"(\n# ?)(.+?)([^\.^,^:^;^…^\r^\n^'^!^?^>])\r", r"\1\2\3.\n")
text = my_replex(text, u"(\n# ?)(.+?[^\.^,^:^;^…^\r^\n^'^!^?^>^\}]) ?\n", r"\1\2.\n")
text = my_replex(text, u"(\n# ?)(.+?[^\.^,^:^;^…^\r^\n^'^!^?^>^\}]) ?\n", r"\1\2.\n")
# Majuscule en début de phrase...
text = my_replex(text, u"(\n# ?)\[\[([^\|^A-Z]+?)\]\]", r"\1[[\2|{{subst:UCFIRST:\2}}]]")
text = my_replex(text, u"(\n# ?)'''([^'^A-Z]+?)'''", r"\1'''{{subst:UCFIRST:\2}}'''")
text = my_replex(text, u"(\n# ?)([^ ^\[^\{^A-Z^'^(])", r"\1{{subst:UC:\2}}")
# Boucle pour déprotéger les term
num=0
while num<40:
text = my_replex(text, u"\n# Eb_(...?)__\.?\n", u"\n# {{ébauche-déf|" + r"\1}}\n",)
text = my_replex(text, u"___term_(.+?)___\.?\n# ", r"# {{\1}}")
num +=1
text = my_replex(text, u"___ex___", r"#:")
text = my_replex(text, u"\n__dou__\n#", r"\n##")
if text0 == text:
print "aucun changement"
else:
print u"changements effectués"
return text
def format_etym(text, lang, titre):
############################################################
# pour formater la typo de la section d'étymologie #
# * format des lignes (ajout point en fin de phrase #
# * Ajout d'ébauche #
############################################################
print u" * Formatage de l'étymologie :\n -> ",
text0 = text
text = my_replex(text, u"(etym:--\}\})\r\n: ?…?\r\n", r"\1" + u"\n: {{ébauche-étym|" + lang + "}}\n")
text = my_replex(text, u"(etym:--\}\})\n: ?…?\n", r"\1" + u"\n: {{ébauche-étym|" + lang + "}}\n")
# Points en fin de phrase...
# D'abord : éviter les espaces en fin de ligne
text = my_replex(text, u"(\n.+?) +?(\r)", r"\1\2")
# Ensuite : éviter les ébauches
if not re.search("ébauche", text):
text = my_replex(text, u"(\n: ?)(.+?)([^\.^,^;^…^\r^\n^!^?^>^}]) ?\r", r"\1\2\3.\n")
if text0 == text:
print "aucun changement"
else:
print u"changements effectués"
return text
def format_pron(text, lang, titre):
###############################################################
# pour formater la typo de la section de prononciation : #
# * format des API / SAMPA #
# * Ajout d'ébauche, ou des lignes API/SAMPA si manquantes #
# (même si elles sont vides #
###############################################################
print u" * Formatage de la prononciation :\n -> ",
text0 = text
text = my_replex(text, u"\n\*? ?(\{\{API\}\}|\[\[API\]\]|\[\[w:API\|API\]\]) ?:? ?/?([^/]*?)/? ?\n", r"\n* {{API}} : /\2/\n")
text = my_replex(text, u"\n\*? ?(\{\{SAMPA\}\}|\[\[SAMPA\]\]|\[\[w:SAMPA\|SAMPA\]\]) ?:? ?/?([^/]*?)/? ?\n", r"\n* {{SAMPA}} : /\2/\n")
API = re.search(u"API", text)
SAMPA = re.search("SAMPA", text)
ebauche = re.search(u"ébauche-pron", text)
if not API and not SAMPA:
print "Vide : ajouts ébauche-API-SAMPA ; ",
if ebauche:
text = my_replex(text, u"(pron:--\}\}\r\n\{\{ébauche-pron\|...?\}\})", r"\1" + u"\n* {{API}} : //\r\n* {{SAMPA}} : //\r\n")
else:
text = my_replex(text, u"(pron:--\}\}\n)", r"\1" + u"{{ébauche-pron|" + lang + "}}\n* {{API}} : //\r\n* {{SAMPA}} : //\r\n")
print u"+ ébauche, ",
# S'il y a API mais pas de contenu : ajout ébauche
if API and re.search(u"\{\{API\}\} : //|\{\{API\}\} : ?\r", text) and not ebauche:
print u"ajout d'ébauche : ",
#text = my_replex(text, u"(pron:--\}\}\n\* \{\{API\}\} )(: //|:)(\r\n)", r"\1\2\3" + u"{{ébauche-pron|" + lang + u"\}\}\n" + r"\2")
text = my_replex(text, u"(pron:--\}\}\n)", r"\1" + u"{{ébauche-pron|" + lang + u"}}\n")
# S'il y a déjà API mais pas SAMPA : ajout SAMPA
if API and not SAMPA:
print "ajout SAMPA ; "
text = my_replex(text, u"(pron:--\}\}\n\{\{ébauche-pron\|...?\}\}\n\* \{\{API\}\} : /)([a-z]*?|[a-z]*?\.[a-z]*?|[a-z]*?\.[a-z]*?\.[a-z]*?)(/)", r"\1\2\3" + u"\n* {{SAMPA}} : " + r"/\2/")
if not re.search("SAMPA", text):
text = my_replex(text, u"(pron:--\}\}\n\{\{ébauche-pron\|...?\}\}\n\* \{\{API\}\} : /.*?/)", r"\1" + u"\n* {{SAMPA}} : //")
if not ebauche:
if not re.search("SAMPA", text):
text = my_replex(text, u"(\* \{\{API\}\} : /)([a-z]*?|[a-z]*?\.[a-z]*?|[a-z]*?\.[a-z]*?\.[a-z]*?)(/)", r"\1\2\3" + u"\n* {{SAMPA}} : " + r"/\2/")
if not re.search("SAMPA", text):
text = my_replex(text, u"(\* \{\{API\}\} : /.*?/)", r"\1" + u"\n* {{SAMPA}} : //")
# S'il y a une ébauche mais pas d'API / SAMPA :
if ebauche and not API and not SAMPA:
text = my_replex(text, u"(\{\{ébauche-pron\|...?\}\})", r"\1" + u"\n* {{API}} : //\n* {{SAMPA}} : //")
if text0 == text:
print "aucun changement"
else:
print u"changements effectués"
return text
def rapatri_cat(text):
##############################################################
# pour rapatrier les cat qui se baladent... #
##############################################################
print u"Recherche de catégories qui trainent :\n -> ",
text0 = text
# Repérage : y a-t-il des catégories qui trainent ?
catbal = True
catentro = []
while catbal:
catbal = re.search(u"\[\[Catégorie:", text)
if catbal:
# Cat repérée ! Découpage, muolinage et relancé jusqu'à vidange complète
debutcat = catbal.start()
contenucat = text[debutcat:]
fincat = re.search("\]\]", contenucat).start()
contenucat = contenucat[:fincat] + "]]"
catentro.append(contenucat)
text = my_repl(text, contenucat, "")
text = my_repl(text, "\n\n", "\n")
elif catentro:
print u"Catégories repêchées, ",
else:
print u"Pas de cat, ",
# Repérage : y a-t-il des interwikis qui trainent ?
itwbal = True
itwentro = []
while itwbal:
itwbal = re.search(u"\[\[[a-z]{2,3}:", text)
if itwbal:
# interwiki repérée ! Découpage, muolinage et relancé jusqu'à vidange complète
debutitw = itwbal.start()
contenuitw = text[debutitw:]
finitw = re.search("\]\]", contenuitw).start()
contenuitw = contenuitw[:finitw] + "]]"
itwentro.append(contenuitw)
text = my_repl(text, contenuitw, "")
text = my_repl(text, "\n\n", "\n")
elif itwentro:
print u"Interwikis repêchées. ",
else:
print u"Pas d'interwiki. ",
if catentro:
print "cat : ", catentro,
if itwentro:
print "itw : ", itwentro,
# A faire ci-dessus
if text0 == text:
print "aucun changement"
else:
print u"changements effectués"
return text, catentro, itwentro
def format_cat(text, titre, catentro, itwentro):
##############################################################
# pour formater la liste des catégories et des interwikis #
##############################################################
print u"\nFormatage des catégories :\n -> ",
# Ajout des catégories et interwikis qui trainaient
#Réunion des cat et interwikis :
catot = u''
itot = u''
for cati in catentro:
catot += cati
for it in itwentro:
itot += it
text = text + catot + itot
text0 = text
text = my_replex(text, u"\[\[(C|c)at(e|é)gor(ie|y):([^]]+?)\]\]", r"[[-cat:\4:tac-]]")
parties = text.split(u"[[")
list_cat = u''
list_itw = u''
ncat=0
nitw=0
for i, p in enumerate(parties):
# Nettoyage éventuel
p2 = my_replex(p, u"(\n|\r|\n )", r"")
# S'il le trouve : c'est une catégorie
if re.search(u"-cat:", p2):
ncat +=1
list_cat += u"\n[[" + p2
# Sinon : c'est un interwiki
elif (p2 <> u""):
nitw +=1
list_itw += u"\n[[" + p2
#print "\nlistcat : \n", list_cat
#print "\nlistitw : \n", list_itw
# Reconstruction des cat et itw
text = "\n"
if list_cat <> u'':
text = text + list_cat
if list_itw <> u'':
text = text + "\n" + list_itw
elif list_itw <> u'':
text = text + list_itw
text = my_replex(text, u"\[\[-cat:(.+?):tac-\]\]", u"[[Catégorie:" + r"\1]]")
print ncat, " cat et ", nitw, "interwikis ; ",
if text0 == text:
print "aucun changement"
else:
print u"changements effectués"
#print "CAT : \n------\n", text, "\n------\n"
return text
def corrections(text, titre):
############################################################
# Optionnel, pour corriger toutes sortes d'erreurs #
############################################################
# Un peu de typo complémentaire
text = my_repl(text, u"\n{{-", u"\n\n{{-")
text = my_repl(text, u"\n\n{{-}}", u"\n{{-}}")
# Pour les liens définitions -> synonymes etc.
text = my_replex(text, u"\n ?\* ?'?'?'?(.+?)'?'?'? ?\(sens (..?|..?|..?,..?|..?,..?,..?)\) :", r"\n\n'''\1''' (\2) :")
text = my_replex(text, u"\n'?'?'?(.+?)'?'?'? ?\(sens (..?|..?|..?,..?|..?,..?,..?)\) :", r"\n\n'''\1''' (\2) :")
text = my_replex(text, u"(-\}\})\n+('''.+?''')", r"\1\n\2")
text = my_repl(text, u"\n{{=", u"\n\n{{=")
text = my_repl(text, u"=}}\n\n{{-", u"=}}\n{{-")
text = my_replex(text, u"(\{\{ébauche\|[^\}]+?\}\}\n)\n", r"\1")
return text
def corrections2(text, titre):
######################################################################
# Optionnel, autres corrections sans rapport avec la structure #
######################################################################
# Lien Wikipédia
text = my_replex(text, u"\* \[\[w:(.+?)\|(.+?)]] sur Wikipédia", r"{{WP|\1|\2}}")
text = my_replex(text, u"\* \[\[w:(.+?)]] sur Wikipédia", r"{{WP|\1|\1}}")
text = my_replex(text, u"\n\*? ?\{\{Wikipé?e?dia\}\}", r"\n{{WP}}")
# Tableau modèle simple
text = my_replex(text, u'\{\| border=0 width=100%\n\|-\n\|bgcolor=.+? valign=top width=48% style="border:1px solid #aaaaaa; padding:5px;" \|\n\{\|',
r'{{(}}')
text = my_replex(text, u'\|\}\n\| width=1% \|\n\|bgcolor=.+? valign=top width=48% style="border:1px solid #aaaaaa; padding:5px;" \|\n\{\|',
r'{{-}}')
text = my_repl(text, u'|}\n|}', r'{{)}}')
# Correction import allemand raté
text = my_repl(text, u"/}}, ''Plural:'' {{Lauʦchrift|/", u"//")
text = my_repl(text, u"/}}, ''Plural:'' {{Lauts)chrift|/", u"//")
text = my_repl(text, u"/}}, {{Pl./", u"//")
return text
def post_corrections(text, titre):
######################################################################
# Correction pour que le bot fonctionne mieux #
######################################################################
# élimination de tous les espaces
text = my_replex(text, u"[\r\n]+", u"\n")
# Modèles de sections standards
text = my_replex(text, u"\{\{-locution-\| ?adverbiale? ?\}\}", "{{-loc-adv-}}")
text = my_replex(text, u"\{\{-locution-\| ?\}\}", "{{-loc-}}")
text = my_replex(text, u"\{\{-article-\|indéfini\}\}", "{{-art-indef-}}")
text = my_repl(text, u"{{-article-|indéfini}}", "{{-art-indef-}}")
text = my_repl(text, u"{{-article-|indéfini}}", "{{-art-indef-}}")
text = my_replex(text, u"\{\{-article-\|défini\}\}", "{{-art-def-}}")
text = my_replex(text, u"\{\{-article-\|partitif\}\}", "{{-art-part-}}")
text = my_replex(text, u"===?=? ?(v|V)oir aussi ?===?=?", r"{{-voir-}}")
# Divers
text = my_replex(text, u"(\{\{ébauche-[^\}]+?\}\}) ?(\{\{-)", r"\1\n\2")
return text
def processus(resultat, titre):
#############################
# Processus complet #
#############################
resultat = post_corrections(resultat, titre)
resultat = balisage(resultat, titre)
print "\n\n" + 100*"=" + "\n\n"
resultat = format_article(resultat, titre)
resultat = debalisage(resultat, titre)
resultat = corrections(resultat, titre)
resultat = corrections2(resultat, titre)
# Affiche a page complète pour vérifier la mise en page
titre = "\r\n" + 100*"-" + "\r\n" + resultat + "\r\n" + 100*"-" + "\r\n"
wikipedia.output(titre)
#print titre
return resultat
##################################################################
# Vérifie que le titre est bien normal (hors annexe surtout) #
##################################################################
def check_titre(titre):
saute = False
excep = ["Annexe:", "Utilisateur:", "Discussion Utilisateur:"]
for sau in excep:
if re.search(sau, titre):
saute = True
return saute
##################################################################
# Vérifie que le texte est réellement modifié (problème avec #
# les regex observé) #
##################################################################
def check_diff(avant, apres):
saute = False
avant = my_replex(avant, "\r|\n", "")
apres = my_replex(apres, "\r|\n", "")
if avant == apres:
saute = True
return saute
#---------------------------------------------------------------
# Suite : normal
#---------------------------------------------------------------
class ReplaceRobot:
def __init__(self, generator, replacements, exceptions = [], regex = False, acceptall = False):
self.generator = generator
self.replacements = replacements
self.exceptions = exceptions
self.regex = regex
self.acceptall = acceptall
def checkExceptions(self, original_text):
"""
If one of the exceptions applies for the given text, returns the
substring which matches the exception. Otherwise it returns None.
"""
for exception in self.exceptions:
if self.regex:
hit = exception.search(original_text)
if hit:
return hit.group(0)
else:
hit = original_text.find(exception)
if hit != -1:
return original_text[hit:hit + len(exception)]
def doReplacements(self, original_text):
"""
Returns the text which is generated by applying all replacements to the
given text.
"""
new_text = original_text
for old, new in self.replacements:
if self.regex:
new_text = old.sub(new, new_text)
else:
new_text = new_text.replace(old, new)
return new_text
def run(self):
"""
Lance le robot.
"""
# Run the generator which will yield Pages which might need to be
# changed.
for page in self.generator:
try:
# Chargement depuis le wiki
original_text = page.get()
match = self.checkExceptions(original_text)
if not page.canBeEdited():
wikipedia.output(u'Je saute la page protégée %s' % page.title())
continue
except wikipedia.NoPage:
wikipedia.output(u'Je n\'ai pas trouvé la page %s' % page.title())
continue
except wikipedia.IsRedirectPage:
continue
match2 = check_titre(page.title())
# test
match2 = False
# SAute les pages qui ont des exceptions de contenu, de titre ou des <!-- (difficile à gérer par bot)
if not re.search(u"pron", original_text):
wikipedia.output(u' %s sautée car ne contient pas de prononciation' % (page.title()))
chemin = open("log xml/format/nopron-.txt", "a")
chemin.write("\n* [[" + page.title().encode('utf8') + "]]")
chemin.close()
elif match:
wikipedia.output(u' %s sautée car exception' % (page.title()))
elif match2:
wikipedia.output(u' %s sautée car le titre n\'est pas dans le namespace général' % (page.title()))
elif re.search(u"<!--", original_text):
wikipedia.output(u' %s sautée car le texte contient des <!-- (logué)' % (page.title()))
chemin = open("log xml/format/bug-.txt", "a")
titre = page.title().encode('utf8')
chemin.write("\n* [[" + titre + "]]")
chemin.close()
else:
#################################################################
# Processus de formatage :
new_text = processus(original_text, page.title())
#################################################################
if new_text == original_text:
wikipedia.output(u'Aucun changements nécessaires dans %s' % page.title())
if check_diff(original_text, new_text):
wikipedia.output(u'Aucun changements nécessaires dans %s (vérification de deuxième ordre)' % page.title())
else:
wikipedia.output(u'<<<>>> %s <<<>>>>' % page.title())
wikipedia.showDiff(original_text, new_text)
textdiff = wikipedia.textDiff(original_text, new_text, page.title())
pronoui = re.search("pron", textdiff)
if not pronoui:
for typ in types_de_mot0:
pron1 = re.search(typ, textdiff)
if pron1:
pronoui = True
if not pronoui:
if not self.acceptall:
choice = wikipedia.inputChoice(u'Pas de prononciation changée, loguer ou continuer ?', ['Log', 'Cont', 'All'], ['l', 'c', 'a'], 'N')
if choice in ['c', 'C']:
print "Passé sans changé ni logé"
if choice in ['a', 'A']:
self.acceptall = True
if self.acceptall or choice in ['l', 'L']:
chemin = open("log xml/format/paspron.txt", "a")
titre = page.title().encode('utf8')
chemin.write("\n* [[" + titre + "]]")
chemin.close()
elif not self.acceptall and pronoui:
choice = wikipedia.inputChoice(u'Accepter les changements ?', ['Yes', 'No', 'All'], ['y', 'N', 'a'], 'N')
if choice in ['a', 'A']:
self.acceptall = True
if pronoui:
if self.acceptall or choice in ['y', 'Y']:
page.put(new_text)
wikipedia.logDiff(original_text, new_text, page.title(), fichierlog)
def main():
gen = None
# Choix de l'origine de la liste des pages à changer
source = None
# Un tableau qui reçoit les paramètres de la ligne de commande directement :
# Le premier est le texte à changer, le second le remplacement
# INUTILE POUR UNE UTILISATION AVANCEE
commandline_replacements = []
# Liste de remplacements (et non pas seulement deux)
replacements = []
# Textes d'exceptions
exceptions = []
# Choix d'utilisation des expressions régulières pour les remplacements et les exceptions : oui/non
regex = False
# Remplacements prédéfinis : oui/non
fix = None
# the dump's path, either absolute or relative, which will be used when source
# is 'xmldump'.
textfilename = None
# Nom de la catégorie si la liste des changements en est une
categoryname = None
# pages données à modifier via la ligne de commande
pageNames = []
# Page de référence via sa liste de suivi
referredPageName = None
# Oui quand always: ou quand on demande a
acceptall = False
# quel namespace ? Rien par défaut pour : tous
namespaces = []
# Page de départ pour le paramètre start
startpage = None
# Résumé par défaut msg (début de prog)
wikipedia.setAction(wikipedia.translate(wikipedia.getSite(), msg))
# Lecture de la ligne de commande à la recherche d'arguments
for arg in sys.argv[1:]:
arg = wikipedia.argHandler(arg, 'replace')
# Y a-t-il des paramètres ?
if arg:
# Si expressions régulières
if arg == '-regex':
regex = True
# un fichier de texte donné
elif arg.startswith('-file'):
if len(arg) == 5:
textfilename = wikipedia.input(u'Please enter the filename:')
else:
textfilename = dossier_log + arg[6:]
source = 'textfile'
# Une catégorie donnée
elif arg.startswith('-cat'):
if len(arg) == 4:
categoryname = wikipedia.input(u'Please enter the category name:')
else:
categoryname = arg[5:]
source = 'category'
# Une page donnée
elif arg.startswith('-page'):
if len(arg) == 5:
pageNames.append(wikipedia.input(u'Which page do you want to chage?'))
else:
pageNames.append(arg[6:])
source = 'singlepage'
# Liste de suivi d'une page donnée
elif arg.startswith('-ref'):
if len(arg) == 4:
referredPageName = wikipedia.input(u'Links to which page should be processed?')
else:
referredPageName = arg[5:]
source = 'ref'
# Pour faire toutes les pages à partir de...
elif arg.startswith('-start'):
if len(arg) == 6:
firstPageTitle = wikipedia.input(u'Which page do you want to chage?')
else:
firstPageTitle = arg[7:]
source = 'allpages'
# Donner une exception
elif arg.startswith('-except:'):
exceptions.append(arg[8:])
# Pour faire un remplacement pré-défini
elif arg.startswith('-fix:'):
fix = arg[5:]
# Ne pas demander s'il faut changer
elif arg == '-always':
acceptall = True
# ne remplacer que dans un namespace spécifique
elif arg.startswith('-namespace:'):
namespaces.append(int(arg[11:]))
# SINON le paramètre est enregistré dans commandline_replacements
else:
commandline_replacements.append(arg)
# Si on a bien deux paramètres jouant le rôle de texte à remplacer et de texte de remplacement, alors on les met dans les changements à effectuer
if (len(commandline_replacements) == 2 and fix == None):
replacements.append((commandline_replacements[0], commandline_replacements[1]))
# Fabrication d'un message automatique dans ce cas-là -... +...
wikipedia.setAction(wikipedia.translate(wikipedia.getSite(), msg ) % ' (-' + commandline_replacements[0] + ' +' + commandline_replacements[1] + ')')
# Si aucune source n'est donnée, on les demande
#elif fix == None:
# old = wikipedia.input(u'Texte à remplacer :')
# new = wikipedia.input(u'Texte de remplacement :')
# change = '(-' + old + ' +' + new
# replacements.append((old, new))
# while True:
# old = wikipedia.input(u'Tapez un nouveau texte ou bien entré pour continuer :')
# if old == '':
# change = change + ')'
# break
# new = wikipedia.input(u'Nouveau texte :')
# change = change + ' & -' + old + ' +' + new
# replacements.append((old, new))
# default_summary_message = wikipedia.translate(wikipedia.getSite(), msg) % change
# wikipedia.output(u'Résumé par défaut : %s' % default_summary_message)
# summary_message = wikipedia.input(u'Message par défaut ou taper un message personnalisé :')
# if summary_message == '':
# summary_message = default_summary_message
# wikipedia.setAction(summary_message)
#else:
# Compilation des expressions pour gagner du temps
if regex:
for i in range(len(replacements)):
old, new = replacements[i]
oldR = re.compile(old, re.UNICODE)
replacements[i] = oldR, new
for i in range(len(exceptions)):
exception = exceptions[i]
exceptionR = re.compile(exception, re.UNICODE)
replacements[i] = exceptionR
# Création des listes des pages à changer à partir des sources
# fichier texte
if source == 'textfile':
gen = pagegenerators.TextfilePageGenerator(textfilename)
# Catégorie
elif source == 'category':
cat = catlib.Category(wikipedia.getSite(), categoryname)
gen = pagegenerators.CategorizedPageGenerator(cat)
# Une page
elif source == 'singlepage':
pages = [wikipedia.Page(wikipedia.getSite(), pageName) for pageName in pageNames]
gen = iter(pages)
# Toutes les pages
elif source == 'allpages':
namespace = wikipedia.Page(wikipedia.getSite(), firstPageTitle).namespace()
gen = pagegenerators.AllpagesPageGenerator(firstPageTitle, namespace)
# Une référence
elif source == 'ref':
referredPage = wikipedia.Page(wikipedia.getSite(), referredPageName)
gen = pagegenerators.AllReferringPageGenerator(referredPage)
# S'il n'y a aucune source : montrer l'aide
elif source == None or len(commandline_replacements) not in [0, 2]:
# syntax error, show help text from the top of this file
wikipedia.output(__doc__, 'utf-8')
wikipedia.stopme()
sys.exit()
# Si l'on donne un namespace, on restreint alors la liste générée avec un filtre
if namespaces != []:
gen = pagegenerators.NamespaceFilterPageGenerator(gen, namespaces)
# On charge la liste gen, avec un nombre de...
preloadingGen = pagegenerators.PreloadingGenerator(gen, pageNumber = 20)
# Mise en place du robot à partir de tous les éléments donnés
bot = ReplaceRobot(preloadingGen, replacements, exceptions, regex, acceptall)
# Lancement !
bot.run()
if __name__ == "__main__":
try:
main()
finally:
wikipedia.stopme()