#-*- coding: utf-8 -*-
#################################################################
# Σκοπός: αλλαγή των κατηγοριών προτύπων του λόγου
# με αυτόματη κατηγοριοποίηση χάρη στα πρότυπα τίτλων τομέα
# στο ελληνικό Βικιλεξικό
#
# Χρησιμοποιούνται ASCII για το ελληνικό και λατινικό αλφάβητο
#
# Το bot χρειάζεται την pywikipedia
# Σημείωση: μερικά κομμάτια του κώδικα προέρχονται
# από το replace.py της pywikipedia
# (run της class LectureRemplacement και main),
# αλλά έχουν τροποποιηθεί ελαφρά.
#
#---------------------
# Παράμετροι:
#---------------------
# - show : εάν 'true', οι τίτλοι παρουσιάζονται
# (αλλά το script γίνεται πιο αργό)
show = True
#
commentaire = u"Αυτόματη κατηγοριοποίηση των προτύπων των τίτλων"
#
##################################################################
# Τα scripts τοποθετούνται σε διαφορετικό directory
# από την pywikipedia
# Οι πληροφορίες χωρίζονται σε πολλά directory
# 1 directory ΒΛ στο ίδιο directory με την pywikipedia
# περιέχει τα directory data, temp, logs, scripts
from __future__ import generators
import sys, re
sys.path.append('../pywikipedia')
sys.path.append('../data')
import os
import time
# Ανάκτηση των δεδομένων
os.chdir('../data')
from lists import majASCII, asciis, asciisation, ponctascii, ex_lang, exceptions, types, nom_types
# Το αρχείο lists πρέπει να είναι παρόν στο directory data
# Ανάκτηση αρχής και τέλους
# Αρχείο stop
st = open('stop', 'r')
stop = unicode(st.read(), 'utf-8')
stop = stop[:-1]
st.close
# Αρχείο start_page
st = open('start_page', 'r')
start_page = unicode(st.read(), 'utf-8')
st.close
os.chdir("..")
# Εισαγωγή των modules της pywikipedia
os.chdir('../pywikipedia')
import wikipedia, pagegenerators, catlib, config, watchlist
os.chdir('../wiktio')
# Directory εργασίας
os.chdir('temp')
#-----------------------------------------------------------
class LectureRemplacement:
"""
Ρομπότ που κάνει αντικατάσταση κειμένου
"""
def __init__(self, generator, acceptall = False):
"""
Παράμετροι:
* generator - Γεννήτρια που φέρνει τις σελίδες
* acceptall - Εάν "True", δεν ρωτά επιβεβαίωση σε κάθε αλλαγή
"""
self.generator = generator
self.acceptall = acceptall
def ChangeArticles(self, text, titre):
"""
1) Προσθέτει τη γλώσσα στους τίτλους μερών του λόγου
2) Προσθέτει το ASCII στους τίτλους μερών του λόγου
3) Αφαιρεί τις κατηγορίες που δημιουργήθηκαν αυτόματα από τους τίτλους
"""
cat = False # Επαληθεύει την παρουσία κατηγοριών
# Αναζητεί και απομονώνει τις κατηγορίες, εάν αυτές υπάρχουν
try:
text = repl(text, u"[[κατηγορία:",u"[[Κατηγορία:") # εναρμονίζει
category_start = re.search(u"\[\[Κατηγορία:([^\]]*)\]\]", text).start()
text = text[:category_start]+ u"{{=:cat:=}}\n" + text[category_start:]
cat = True # Υπάρχουν κατηγορίες
except:
#Affiche(u"Δεν υπάρχουν κατηγορίες σε αυτή τη σελίδα")
0
# Διαχωρισμός τομέων γλώσσας
parties = text.split("{{=")
selection = u""
langues = {} # λίστα τομέων γλωσσών
text_final = "" # θα περιέχει το τελικό άρθρο
valeur = {} # τύπος του τομέα
nombre_titre = 0 # μετρά τους τίτλους τομέων
n = 0 # μετρά τις κατηγορίες
difference = 0 # διαφορά ανάμεσα στις δύο μετρήσεις
titrascii = '' # μετάφραση του τίτλου σε ASCII
askiwi = ''
error = ''
titrascii_commun = ''
askiwi_commun = ''
error_commun = ''
# τομείς γλωσσών στο άρθρο
for i, p in enumerate(parties):
p = replex(p, u"^[^\{](.+?=)\|.*?(\}\})", r"\1\2")
trouve = re.search("=}}", p)
if trouve:
fin = trouve.start()
nom = p[:fin]
langues[nom] = "{{=" + p
valeur[n] = nom
else:
langues["0"] = p
valeur[n] = "0"
n+=1
# τύποι σε κάθε τομέα γλώσσας
for z, i in enumerate(langues):
if i == "conv" or i == "ine":
continue
if i <> ":cat:" and i<>"0":
# Cas particuliers ?
if i in ex_lang.keys():
titrascii, askiwi, error = self.NormASCII(titre, i)
elif not titrascii_commun:
titrascii_commun, askiwi_commun, error_commun = self.NormASCII(titre, 0)
titrascii = titrascii_commun
askiwi = askiwi_commun
error = error_commun
else:
titrascii = titrascii_commun
askiwi = askiwi_commun
error = error_commun
typesec = langues[i].split("{{-")
for m, sec in enumerate(typesec):
if m<>0:
sec = "{{-" + sec
trouve = re.search("-.*?\}\}", sec)
tit = ""
if trouve:
tit = sec[:trouve.end()]
# D'une part s'il y a besoin d'ajouter l'ASCII
if askiwi:
for section in types:
# τομέας με γλώσσα και ASCII (αντικαθιστά το ASCII)
tit = replex(tit, "(\{\{-" + section +"-\|)"+i+"\|[^}\|=]+(\}\}|num=[0-9]\}\})", r"\1"+i+"|"+titrascii+r"\2")
# τομέας με γλώσσα χωρίς ASCII (προσθέτει το ASCII)
tit = replex(tit, "(\{\{-" + section +"-\|)"+i+"(\}\}|num=[0-9]\}\})", r"\1"+i+"|"+titrascii+r"\2")
# τομέας χωρίς γλώσσα αλλά με ASCII (προσθέτει τη γλώσσα, αντικαθιστά το ASCII)
tit = replex(tit, "(\{\{-" + section +"-\|)\|[^}\|=]+(\}\}|num=[0-9]\}\})", r"\1"+i+"|"+titrascii+r"\2")
# τομέας χωρίς γλώσσα ούτε ASCII (προσθέτει γλώσσα και ASCII)
tit = replex(tit, "(\{\{-" + section +"-)(\}\}|\|num=[0-9]\}\})", r"\1|"+i+"|"+titrascii+r"\2")
# Διαφορετικά, εάν δεν χρειάζεται ASCII
else:
for section in types:
# τομέας με γλώσσα και ASCII (αφαιρεί το ASCII)
tit = replex(tit, "(\{\{-" + section +"-\|)"+i+"\|[^}\|=]+(\}\}|\|num=[0-9]\}\})", r"\1"+i+r"\2")
# τομέας με γλώσσα χωρίς ASCII (προσθέτει τη γλώσσα)
tit = replex(tit, "(\{\{-" + section +"-\|)"+i+"(\}\}|\|num=[0-9]\}\})", r"\1"+i+r"\2")
# τομέας χωρίς γλώσσα αλλά με ASCII (προσθέτει γλώσσα, αφαιρεί ASCII)
tit = replex(tit, "(\{\{-" + section +"-\|)\|[^}\|=]+(\}\}|\|num=[0-9]\}\})", r"\1"+i+r"\2")
# τομέας χωρίς γλώσσα ούτε ASCII (προσθέτει τη γλώσσα)
tit = replex(tit, "(\{\{-" + section +"-)(\}\}|\|num=[0-9]\}\})", r"\1|"+i+r"\2")
typesec[m] = tit + sec[trouve.end():]
else:
typesec[m] = sec
langues[i] = '' ;
for n in range(len(typesec)):
langues[i] += typesec[n]
if i == ":cat:": # εάν υπάρχουν κατηγορίες
langues[i] = replex(langues[i], '^.+?:cat:=\}\}', '')
langues[i] = replex(langues[i], '\n\n+', '')
# Συγκεντρώνει τους τομείς γλώσσας
for z, i in enumerate(valeur):
text_final += langues[valeur[i]]
# Αφαιρεί τις γραμματικές κατηγορίες που γίνονται πια αυτόματα
for ty in nom_types:
text_final = replex(text_final, u"(\r\n+)?\[\[Κατηγορία:" + ty + " en .+?\]\]\n?", "")
# Suppression des catégories langues seules (=seul rôle ASCII), prises en compte dans les modèles
# {{Προσοχή! Δεν ισχύει παρά στα κανονικά άρθρα με τουλάχιστον έναν κανονικό τίτλο
# Note : toutes les catégories contenant une minuscule sont considérées comme des langues
text_final = replex(text_final, u"(\r\n+)?\[\[Κατηγορία:[a-zéèà].+?\|(.+?)\]\]\n?", "")
# Άχρηστες και παρασιτικές κατηγορίες
text_final = replex(text_final, u"(\r\n+)?\[\[Κατηγορία:[a-zéèà].+?\]\]\n?", "")
# Καθαρίζει τα πρόσθετα κενά
text_final = replex(text_final, u"\r?\n\r?\n\r?\n\r?\n?\r?\n?", "\r\n\r\n\r\n")
return text_final, titrascii, error
def NormASCII(self, expression, langue):
"""
Μεταγράφει τον όρο (όνομα του άρθρου) σε ASCII
για μια σωστή κατηγοριοποίηση
"""
expressionA = expression
# Στίξη
for s, t in ponctascii:
expressionA = replex(expressionA, s, t)
# Μεταγραφή σε ASCII
if langue:
for s, t in ex_lang[langue]:
expressionA = replex(expressionA, s, t)
else:
for s, t in asciisation:
expressionA = replex(expressionA, s, t)
expressionA = self.minusASCII(expressionA)
expressionB = self.minusASCII(expression)
error = False
askiwi = False
# Επαληθεύει εάν ο τίτλος είναι ήδη σε ASCII (άρα δεν χρειάζεται αντικατάσταση)
if expressionA == expressionB:
askiwi = False
error = False
print "Titre déjà en ascii :", expressionA
# Επαληθεύει εάν ο νέος τίτλος είναι ολόκληρος σε ascii
elif not self.isASCII(expressionA) and not langue:
askiwi = False
error = True
print "Μη ASCII αλλαγμένος τίτλος: ", expressionA
else:
askiwi = True
error = False
return expressionA, askiwi, error
def minusASCII(self, terme):
"""
Μετατρέπει μόνο τα ASCII σε πεζά γράμματα
"""
for s, t in majASCII:
terme = repl(terme, s, t)
return terme
def isASCII(self, text):
"""
Επαληθεύει εάν το κείμενο περιέχει τους επιτρεπόμενους χαρακτήρες ascii
"""
isasc = True
for i in range(len(text)):
ascok = False
for a in asciis:
if a == text[i]:
ascok = True
break
if ascok == False:
isasc = False
break
return isasc
def run(self):
"""
Κάνει τη δουλειά
"""
Affiche(u"Άντε να δουλέψουμε και λίγο!!")
ancien= ""
for page in self.generator:
if page.title() == stop:
Affiche(u""+stop+u" έγινε, σταματώ το bot.")
break
st = open('../data/start_page', 'w')
st.write(page.title().encode('utf-8'))
st.close
try:
ancien = page.get()
if not page.canBeEdited():
wikipedia.output(u'Αφήνω την προστατευμένη σελίδα %s' % page.title())
except wikipedia.NoPage:
wikipedia.output(u'Η σελίδα %s δεν υπάρχει' % page.title())
except wikipedia.IsRedirectPage:
wikipedia.output(u'Η σελίδα %s είναι ανακατεύθυνση' % page.title())
continue
titre = page.title()
continuer = True
for sauf in exceptions:
try:
if re.search(sauf, titre):
continuer = False
break
except:
Affiche("Λάθος στο " + titre + " με " + sauf)
wikipedia.output("Λάθος στο " + titre + " με " + sauf)
continue
nouveau, ascii, error = self.ChangeArticles(ancien, titre)
if error:
wikipedia.output(u"Η σελίδα περιέχει χαρακτήρες που δεν αναγνωρίζονται: %s | %s" % (titre, ascii))
#conterror = wikipedia.input(u'Να συνεχίσω; (y/n)')
#if (conterror == 'n' or conterror == 'N'):
# break
if replex(nouveau, "\r|\n", "") == replex(ancien, "\r|\n", "") or not continuer:
Affiche(u"Δεν χρειάζονται αλλαγές στο %s" % titre)
else:
wikipedia.output('>>> %s <<<' % (titre))
Affiche('%s -> %s' % (titre, ascii))
wikipedia.output(unicode(time.strftime("%Hh%M | %D"), 'utf8'))
wikipedia.showDiff(ancien, nouveau)
# if difference > 0:
# if difference == 1:
# Affiche(u">> Προσοχή: φαίνεται πως 1 κατηγορία σβήστηκε χωρίς αντιστάθμισμα!\n")
# else:
# Affiche(u">> Προσοχή: φαίνεται πως %s κατηγορίες σβήστηκαν χωρίς αντιστάθμισμα!\n" % difference)
# if difference < 0:
# difference = -difference
# if difference == 1:
# Affiche(u">> Σημείωση: φαίνεται πως έλειπε 1 κατηγορία.\n")
# else:
# Affiche(u">> Σημείωση: φαίνεται πως έλειπαν %s κατηγορίες.\n" % difference)
if not self.acceptall:
choice = wikipedia.inputChoice(u'Δέχεστε τις αλλαγές?', ['Yes', 'No', 'All'], ['y', 'N', 'a'], 'N')
if choice in ['a', 'A']:
self.acceptall = True
if self.acceptall or choice in ['y', 'Y']:
page.put(nouveau, comment = commentaire, minorEdit = True)
Affiche(u"Bien joué !\n")
Affiche(u"Τελειώσαμε κιόλας;")
def repl(original_text, old, new):
"""
Εργαλεία ανταλλαγής απλού κειμένου (χωρίς regular expressions)
"""
try:
new_text = old.sub(new, original_text)
except:
new_text = original_text.replace(old, new)
return new_text
def replex(texte, avant, apres):
"""
Εργαλεία ανταλλαγής κειμένου με regular expressions
"""
avant = re.compile(avant, re.UNICODE)
texte = avant.sub(apres, texte)
return texte
def Affiche(texte):
"""
Δεν εμφανίζει τα σχόλια παρά εάν "Σχόλια" είναι ενεργοποιημένο
"""
if show:
try:
print unicode(texte, 'utf-8')
except:
print texte
# wikipedia.output(texte)
return
def compte(texte, motif):
"""
Μετρά τον αριθμό μοτίβων στο κείμενο
"""
occurence = 0
n=0
while n<len(texte)-len(motif):
x=0
mot = u""
while x<len(motif):
mot += texte[n+x]
x += 1
if mot == motif:
occurence +=1
n +=1
return occurence
def main():
"""
Μπορούν να χρησιμοποιηθούν οι εξής παράμετροι:
-start
-page
-ref
-cat
-from
και:
-all
"""
acceptall = False
namespaces=["0"]
gen = None
PageTitles = []
for arg in sys.argv[1:]:
arg = wikipedia.argHandler(arg, 'catauto')
if arg:
if arg.startswith('-start'):
if len(arg) == 6:
firstPageTitle = wikipedia.input(u'Από ποια σελίδα να αρχίσω;')
else:
firstPageTitle = arg[7:]
namespace = wikipedia.Page(wikipedia.getSite(), firstPageTitle).namespace()
gen = pagegenerators.AllpagesPageGenerator(firstPageTitle, namespace)
elif arg.startswith('-from'):
firstPageTitle = start_page
namespace = wikipedia.Page(wikipedia.getSite(), firstPageTitle).namespace()
gen = pagegenerators.AllpagesPageGenerator(firstPageTitle, namespace)
elif arg.startswith('-page'):
if len(arg) == 5:
PageTitles.append(wikipedia.input(u'Ποια σελίδα να αλλάξω;'))
else:
PageTitles.append(arg[6:])
pages = [wikipedia.Page(wikipedia.getSite(), PageTitle) for PageTitle in PageTitles]
gen = iter(pages)
elif arg.startswith('-ref'):
if len(arg) == 4:
referredPageTitle = wikipedia.input(u'Ποια σελίδα χρησιμεύει ως αναφορά;')
else:
referredPageTitle = arg[5:]
referredPage = wikipedia.Page(wikipedia.getSite(), referredPageTitle)
gen = pagegenerators.ReferringPageGenerator(referredPage)
elif arg.startswith('-cat'):
if len(arg) == 4:
categoryname = wikipedia.input(u'Όνομα της κατηγορίας: ')
else:
categoryname = arg[5:]
cat = catlib.Category(wikipedia.getSite(), 'Category:%s' % categoryname)
gen = pagegenerators.CategorizedPageGenerator(cat)
if arg.startswith('-all'):
acceptall = True
if not gen:
firstPageTitle = start_page
namespace = wikipedia.Page(wikipedia.getSite(), firstPageTitle).namespace()
gen = pagegenerators.AllpagesPageGenerator(firstPageTitle, namespace)
# syntax error, show help text from the top of this file
#wikipedia.output(__doc__, 'utf-8')
#wikipedia.stopme()
#sys.exit()
preloadingGen = pagegenerators.PreloadingGenerator(gen, pageNumber = 10)
bot = LectureRemplacement(preloadingGen, acceptall)
bot.run()
if __name__ == "__main__":
try:
main()
finally:
wikipedia.output(u"\nΤέλος της διαδικασίας.\n")
wikipedia.stopme()