Script ad hoc

Inserire valori specifici in ciascuna voce

A volte capita di dover popolare con dei dati una serie di voci. Essendo questi parametri diversi da voce a voce, una classica sostituzione con replace.py è impossibile. Si usa allora uno script ad hoc che verifica il nome della voce in una collezione di dati e inserisce i valori corrispondenti. Il primo passo è trasformare mediante semplici sostituzioni di testo i dati forniti (di solito in CSV) in un array bidimensionale. Poi si crea un ciclo for che confronta il nome della voce con il corrispondente campo nell'array. Se viene trovata la corrispondenza si valorizzano le variabili e quindi si procede all'aggiornamento della voce.

Esempi
#!/usr/bin/python
# -*- coding: utf-8  -*-
"""
The following parameters are supported:

&params;

-dry              If given, doesn't do any real changes, but only shows
                  what would have been changed.

All other parameters will be regarded as part of the title of a single page,
and the bot will only work on that single page.
"""
__version__ = '$Id: basic.py 7845 2009-12-30 17:02:05Z xqt $'
import wikipedia as pywikibot
import wikipedia, time
import pagegenerators
import re
import string

# This is required for the text that is shown when you run this script
# with the parameter -help.
docuReplacements = {
    '&params;': pagegenerators.parameterHelp
}

def annotaproblema(pag, errore=""):
    try:
        log = open("log_navboxcomuni.txt", 'a')
    except:
        print "qualche problema ad annotare il problema"
        return -1
    messaggio = u"* "+pag+" "+errore+u"\r\n"
    log.write(messaggio.encode('utf-8'))
    log.close()
    print "problema annotato"

class BasicBot:
    msg = { # oggetto della modifica
        'it': u"Bot: inserimento [[Template:Navbox comuni italiani per provincia]] come da [[Discussioni progetto:Amministrazioni#Anomalie template]]",
        'en': u"Bot: test",
    }

    def __init__(self, generator, dry):
        """
        Constructor. Parameters:
            * generator - The page generator that determines on which pages
                          to work on.
            * dry       - If True, doesn't do any real changes, but only shows
                          what would have been changed.
        """
        self.generator = generator
        self.dry = dry
        # Set the edit summary /*message
        self.summary = pywikibot.translate(pywikibot.getSite(), self.msg)

    def run(self):
        for page in self.generator:
            self.treat(page)

    def treat(self, page):
        print ""
        confirmation = False
        try:
            text = page.get()
        except pywikibot.NoPage:
            pywikibot.output(u"Page %s does not exist; skipping." % page.aslink())
            return
        except pywikibot.IsRedirectPage:
            pywikibot.output(u"%s e' un redirect" % page.aslink())
##            text = page.get(get_redirect=True)
##            redirect = True

        dati = [
        [u"Template:Provincia di Agrigento", u"33439066", u"2010-07-09T20:28:05Z", u"", u"", u"Sicilia", u"", u"Agrigento", u"Provincia di Agrigento-Stemma.png", u"[[Agrigento]] · [[Alessandria della Rocca]] · [[Aragona (Italia)|Aragona]] · [[Bivona]] · [[Burgio]] · [[Calamonaci]] · [[Caltabellotta]] · [[Camastra]] · [[Cammarata]] · [[Campobello di Licata]] · [[Canicattì]] · [[Casteltermini]] · [[Castrofilippo]] · [[Cattolica Eraclea]] · [[Cianciana]] · [[Comitini]] · [[Favara]] · [[Grotte]] · [[Joppolo Giancaxio]] · [[Lampedusa e Linosa]] · [[Licata]] · [[Lucca Sicula]] · [[Menfi]] · [[Montallegro]] · [[Montevago]] · [[Naro]] · [[Palma di Montechiaro]] · [[Porto Empedocle]] · [[Racalmuto]] · [[Raffadali]] · [[Ravanusa]] · [[Realmonte]] · [[Ribera]] · [[Sambuca di Sicilia]] · [[San Biagio Platani]] · [[San Giovanni Gemini]] · [[Sant'Angelo Muxaro]] · [[Santa Elisabetta (Italia)|Santa Elisabetta]] · [[Santa Margherita di Belice]] · [[Santo Stefano Quisquina]] · [[Sciacca]] · [[Siculiana]] · [[Villafranca Sicula]]"],

# [ omessa lista abbastanza lunga ]

        [u"Template:Provincia di Viterbo", u"33448500", u"2010-07-10T08:35:54Z", u"", u"", u"Lazio", u"", u"Viterbo", u"Provincia di Viterbo-Stemma.png", u"[[Acquapendente]] · [[Arlena di Castro]] · [[Bagnoregio]] · [[Barbarano Romano]] · [[Bassano Romano]] · [[Bassano in Teverina]] · [[Blera]] · [[Bolsena]] · [[Bomarzo]] · [[Calcata]] · [[Canepina]] · [[Canino]] · [[Capodimonte]] · [[Capranica]] · [[Caprarola]] · [[Carbognano]] · [[Castel Sant'Elia]] · [[Castiglione in Teverina]] · [[Celleno]] · [[Cellere]] · [[Civita Castellana]] · [[Civitella d'Agliano]] · [[Corchiano]] · [[Fabrica di Roma]] · [[Faleria]] · [[Farnese]] · [[Gallese (Italia)|Gallese]] · [[Gradoli]] · [[Graffignano]] · [[Grotte di Castro]] · [[Ischia di Castro]] · [[Latera]] · [[Lubriano]] · [[Marta (Italia)|Marta]] · [[Montalto di Castro]] · [[Monte Romano]] · [[Montefiascone]] · [[Monterosi]] · [[Nepi]] · [[Onano]] · [[Oriolo Romano]] · [[Orte]] · [[Piansano]] · [[Proceno]] · [[Ronciglione]] · [[San Lorenzo Nuovo]] · [[Soriano nel Cimino]] · [[Sutri]] · [[Tarquinia]] · [[Tessennano]] · [[Tuscania]] · [[Valentano]] · [[Vallerano]] · [[Vasanello]] · [[Vejano]] · [[Vetralla]] · [[Vignanello]] · [[Villa San Giovanni in Tuscia]] · [[Viterbo]] · [[Vitorchiano]]"]]
        # "template", "revisionId", "revisionTimestamp", "pagina", "titolo", "regione", "preposizioneProvincia", "provincia", "stemma", "lista"

        trovata_corrispondenza = False    
        for i in (range (len(dati))):
            if page.title() == dati[i][0]:
                pywikibot.output(page.title())
                revision = int(dati[i][1])
                pagina = dati[i][3]
                titolo = dati[i][4]
                regione = dati[i][5]
                preposizioneProvincia = dati[i][6]
                provincia = dati[i][7]
                stemma = dati[i][8]
                lista = dati[i][9]
                trovata_corrispondenza = True

        if not trovata_corrispondenza:
            return

        m = re.search('<noinclude>[\W\w]+?</noinclude>', text)
        if m:
            noinclude = m.group(0)
        else:
            pywikibot.output("Non trovato noinclude!")
            annotaproblema(page.aslink(), "noinclude")
            return

        if page.latestRevision() != revision:
            pywikibot.output("RevisionId non corrispondente, la voce è stata modificata!")
            pywikibot.output("%d vs. %d" % (page.latestRevision(), revision))
            annotaproblema(page.aslink(), "revision")
            return

        nuovocodice = "{{Navbox comuni italiani per provincia"
        if pagina != "":
            nuovocodice += "\n|pagina = {{subst:PAGENAME}}"
            if titolo != "":
                nuovocodice += "\n|titolo = " + titolo
        nuovocodice += "\n|regione = " + regione
        if preposizioneProvincia != "":
            nuovocodice += "\n|preposizioneProvincia = " + preposizioneProvincia
        nuovocodice += "\n|provincia = " + provincia
        nuovocodice += "\n|stemma = " + stemma
        nuovocodice += "\n|lista = " + lista
        nuovocodice += "\n}}" + noinclude
        text = nuovocodice
        if text != page.get():
            pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<" % page.title())
            pywikibot.showDiff(page.get(), text)
            if not self.dry:
                if not confirmation:
                    choice = 's'   ## AUTO!!
                else:
                    choice = pywikibot.inputChoice(u'Applicare i cambiamenti?', ['Si', 'No'], ['s', 'N'], 'N')
                if choice == 's':
                    try:
                        esito = page.put(text, comment=self.summary)
                        if esito[2]['result'] == 'Success':
                            print "OK"
                        else:
                            print esito
                            annotaproblema(page.aslink(), "failure")
                    except pywikibot.LockedPage:
                        pywikibot.output(u"Page %s is locked; skipping." % page.aslink())
                    except pywikibot.EditConflict:
                        pywikibot.output(u'Skipping %s because of edit conflict' % (page.title()))
                    except pywikibot.SpamfilterError, error:
                        pywikibot.output(u'Cannot change %s because of spam blacklist entry %s' % (page.title(), error.url))
                    except:
                        print "spam?"
                        annotaproblema(page.aslink(), "failure (spam?)")

def main():
    genFactory = pagegenerators.GeneratorFactory()
    gen = None
    pageTitleParts = []
    dry = False
    for arg in pywikibot.handleArgs():
        if arg.startswith("-dry"):
            dry = True
        else:
            # check if a standard argument like
            # -start:XYZ or -ref:Asdf was given.
            if not genFactory.handleArg(arg):
                pageTitleParts.append(arg)

    if pageTitleParts != []:
        # We will only work on a single page.
        pageTitle = ' '.join(pageTitleParts)
        page = pywikibot.Page(pywikibot.getSite(), pageTitle)
        gen = iter([page])

    if not gen:
        gen = genFactory.getCombinedGenerator()
    if gen:
        # The preloading generator is responsible for downloading multiple
        # pages from the wiki simultaneously.
        gen = pagegenerators.PreloadingGenerator(gen)
        bot = BasicBot(gen, dry)
        bot.run()
    else:
        pywikibot.showHelp()

if __name__ == "__main__":
    try:
        main()
    finally:
        pywikibot.stopme()
#!/usr/bin/python
# -*- coding: utf-8  -*-
"""
The following parameters are supported:

&params;

-dry              If given, doesn't do any real changes, but only shows
                  what would have been changed.

All other parameters will be regarded as part of the title of a single page,
and the bot will only work on that single page.
"""
__version__ = '$Id: basic.py 7845 2009-12-30 17:02:05Z xqt $'
import wikipedia as pywikibot
import wikipedia, time
import pagegenerators
import re
import string

# This is required for the text that is shown when you run this script
# with the parameter -help.
docuReplacements = {
    '&params;': pagegenerators.parameterHelp
}

def annotaproblema(pag, errore=""):
    try:
        log = open("log_roids.txt", 'a')
    except:
        print "qualche problema ad annotare il problema"
        return -1
    messaggio = u"* "+pag+" "+errore+u"\r\n"
    log.write(messaggio.encode('utf-8'))
    log.close()
    print "problema annotato"

class BasicBot:
    msg = { # oggetto della modifica
        'it': u"Bot: inserimento parametro par_Tisserand_J",
        'en': u"Bot: test",
    }

    def __init__(self, generator, dry):
        """
        Constructor. Parameters:
            * generator - The page generator that determines on which pages
                          to work on.
            * dry       - If True, doesn't do any real changes, but only shows
                          what would have been changed.
        """
        self.generator = generator
        self.dry = dry
        # Set the edit summary /*message
        self.summary = pywikibot.translate(pywikibot.getSite(), self.msg)

    def run(self):
        for page in self.generator:
            self.treat(page)

    def treat(self, page):
        print ""
        confirmation = True
        try:
            text = page.get()
        except pywikibot.NoPage:
            pywikibot.output(u"Page %s does not exist; skipping." % page.aslink())
            return
        except pywikibot.IsRedirectPage:
            pywikibot.output(u"%s e' un redirect" % page.aslink())
##            text = page.get(get_redirect=True)
            redirect = True
            annotaproblema(page.aslink(), "redirect")
            return

        dati = [
[u"1 Ceres",
u"|par_Tisserand_J = 3,310"],
[u"2 Pallas",
u"|par_Tisserand_J = 3,043"],
[u"3 Juno",
u"|par_Tisserand_J = 3,299"],
[u"4 Vesta",
u"|par_Tisserand_J = 3,535"],

# [ omessa lista infinita ]

u"|par_Tisserand_J = 3,537"],
[u"64974 Savaria",
u"|par_Tisserand_J = 3,179"],
[u"64975 Gianrix",
u"|par_Tisserand_J = 3,217"]
]

        trovata_corrispondenza = False    
        for i in (range (len(dati))):
            if page.title() == dati[i][0]:
                pywikibot.output(page.title())
                par_Tisserand_J = dati[i][1]
                trovata_corrispondenza = True
        if not trovata_corrispondenza:
            return

        m = re.search('\| *par_Tisserand_J *=[^\n\r\|]+', text)
        if m:
            print "c'e' gia' par_Tisserand_J"
            if m.group(0) != par_Tisserand_J:
                annotaproblema(page.aslink(), "par_Tisserand_J diverso")
                print "e tra l'altro e' diverso!"
            else:
                return

        m = re.search('\| *magn_ass *=', text)
        if m:
            text = re.sub(ur'(\| *magn_ass *=)', par_Tisserand_J + ur'\n\1', text)
        else:
            print "non c'è magn_ass"
            text = re.sub(ur'({{ *[cC]orpo[ _]+celeste[^{}])}}', ur'\1' + par_Tisserand_J + ur'\n}}', text)            

        if text != page.get():
            pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<" % page.title())
            pywikibot.showDiff(page.get(), text)
            if not self.dry:
                if not confirmation:
                    choice = 's'   ## AUTO!!
                else:
                    choice = pywikibot.inputChoice(u'Applicare i cambiamenti?', ['Si', 'No'], ['s', 'N'], 'N')
                if choice == 's':
                    try:
                        esito = page.put(text, comment=self.summary)
                        if esito[2]['result'] == 'Success':
                            print "OK"
                        else:
                            print esito
                            annotaproblema(page.aslink(), "failure")
                    except pywikibot.LockedPage:
                        pywikibot.output(u"Page %s is locked; skipping." % page.aslink())
                    except pywikibot.EditConflict:
                        pywikibot.output(u'Skipping %s because of edit conflict' % (page.title()))
                    except pywikibot.SpamfilterError, error:
                        pywikibot.output(u'Cannot change %s because of spam blacklist entry %s' % (page.title(), error.url))
                    except:
                        print "spam?"
                        annotaproblema(page.aslink(), "failure (spam?)")

def main():
    genFactory = pagegenerators.GeneratorFactory()
    gen = None
    pageTitleParts = []
    dry = False
    for arg in pywikibot.handleArgs():
        if arg.startswith("-dry"):
            dry = True
        else:
            if not genFactory.handleArg(arg):
                pageTitleParts.append(arg)

    if pageTitleParts != []:
        pageTitle = ' '.join(pageTitleParts)
        page = pywikibot.Page(pywikibot.getSite(), pageTitle)
        gen = iter([page])

    if not gen:
        gen = genFactory.getCombinedGenerator()
    if gen:
        gen = pagegenerators.PreloadingGenerator(gen)
        bot = BasicBot(gen, dry)
        bot.run()
    else:
        pywikibot.showHelp()
if __name__ == "__main__":
    try:
        main()
    finally:
        pywikibot.stopme()

Raccolte di regex da inserire in userfixes.py

  Lo stesso argomento in dettaglio: Utente:FrescoBot/FAQ § User-fixes.py.

Categorizzare

       'categorizzare': {
       'regex': True,
       'recursive': False,
       'msg': {
              'it':u"Bot: solo categorie nascoste -> categorizzare",
             },
       'replacements': [

(u'({{ *[EePpCcTt] *\|[^=\|\[}]+\|)([^=\|\[}]+)([\|}]([\W\w]+)$)', ur'\1\2\3\n{{categorizzare|\2}}'),
(u'({{ *[EePpCcTt] *\|[^\|\[}]+\| *argomento *= *)([^=\|\[}]+)([\|}]([\W\w]+)$)', ur'\1\2\3\n{{categorizzare|\2}}'),
(u'({{ *[OoFfSs] *\|)([^=\|\[}]+)([\|}]([\W\w]+)$)', ur'\1\2\3\n{{categorizzare|\2}}'),
(u'({{categorizzare\|([\W\w](?!{{categorizzare))+?[\W\w]){{categorizzare\|[^}]+}}\s*', ur'\1'),
(u'^([\W\w]+)$', ur'\1\n{{categorizzare}}'),
(u'({{categorizzare[^}]*}})\s*{{categorizzare[^}]*}}', ur'\1'),

      ],
        'exceptions': {
                    'inside-tags': [
##                                'hyperlink',    
##                                'link',
##                                'comment',
##                                'template',
##                                'timeline',
##                                'gallery',
##                                'math',
##                                'pre',
##                                'startspace',
##                                'source', 
##                                'nowiki'
                        ],
                    'text-contains': [
                                ur'{{([Bb]io\s|[Ss]portivo|[Aa]lbum|[Aa]rtista musicale)',
                                ur'{{ *[AWaw] *[\|}]',
                                ur'{{ *[cC]ategorizzare',
                                ur'\[\[[Cc]ategoria:(?![Ss]tub|[Aa]iutare|[Cc]ontrollare|[Cc]orreggere|[Vv]oci |[Dd]a )',
                                ur'{{[tT]rasferimento',
                                ur'#([Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]|[Rr][Ii][Nn][Vv][Ii][Aa])',
                                ]                    
        }
   },