Vés al contingut

Usuari:RRHGbot/munic cat taules.py

De la Viquipèdia, l'enciclopèdia lliure

script per canviar les taules HTML dels municipis de Catalunya a templates (Template:taucatCapBE, Template:capentcat) segons Viquiprojecte Municipis de Catalunya

fa servir meta:Using_the_python_wikipediabot pyWikipedia Framework(anglès)

# -*- coding: utf-8  -*-
"""
 munic_cat_taules.py 
 versió: 0.6 - - Localització (des|dels) ...
         0.5 - - entcat: canvi condició del bucle per un cas que no es contemplava
               - cas de municipis que començen per "el"
         0.4 - - determinar tipus de taucat a partir de l'existència de links a imatges o de 
                 links a detalls
               - comprovació i avisos de possibles errors 
                 en noms d'imatges i entitats de població
               - revertida la supressió d'articles inicials... afegida comprovació de nom
         0.3 - entcat: pot aparèixer un nucli amb el mateix nom de l'article sense enllaç
         0.2 - un munt de canvis

 script per convertir alguns articles de municipis de Catalunya,
 que en comptes de {{taucat}} i {{entcat}} fan servir taules HTML
 hi havien 737 abans de començar

 Ús: munic_cat_taules.py "nom_article" [-e:"inici_entcat"] [-t:"inici_taulacat"] 

    * "nom_article" el nom de l'article com: "Ribera d'Ondara"
    * -e:"inici_entcat" OPCIONAL inici taula entcat, per defecte: "<TABLE WIDTH"
    * -t:"inici_taucat" OPCIONAL inici taula taucat, per defecte: "<table border"

 NOTES: - aquest script s'ha de fer servir amb el pyWikipediaFramework
        - si el programa peta és possible que no hagi trobat alguna taula en el format necessari 
"""

import sys
import re
import wikipedia

# en alguns casos els caràcters especials s'han traduït a la forma &aaa; ...
def trn_chars_especials (text):
    canvis = [
        ( u"Á", u"Á"),
        ( u"À", u"À"),
        ( u"Ç", u"Ç"),
        ( u"É", u"É"),
        ( u"È", u"È"),
        ( u"Ë", u"Ë"),
        ( u"Í", u"Í"),
        ( u"Ï", u"Ï"),
        ( u"Ó", u"Ó"),
        ( u"Ò", u"Ò"),
        ( u"Ö", u"Ö"),
        ( u"Ú", u"Ú"),
        ( u"Ù", u"Ù"),
        ( u"Ü", u"Ü"),
        ( u"á", u"á"),
        ( u"à", u"à"),
        ( u"ç", u"ç"),
        ( u"é", u"é"),
        ( u"è", u"è"),
        ( u"ë", u"ë"),
        ( u"í", u"í"),
        ( u"ï", u"ï"),
        ( u"ó", u"ó"),
        ( u"ò", u"ò"),
        ( u"ö", u"ö"),
        ( u"ú", u"ú"),
        ( u"ù", u"ù"),
        ( u"ü", u"ü")
        ]
    for canvi in canvis:
        a, b = canvi
        text = re.sub(a, b, text)
    return text


def extreure_taula (inici, text_origen, rep):
    resultat = []

    ini = re.compile ( inici )                    # re del text_inici_taula a cercar
    if rep == 1:
        fi = re.compile ( r'</TABLE>', re.IGNORECASE )      # re fi de taula 1
    elif rep == 2:
        fi = re.compile ( '</TABLE>.*?</TABLE>', re.DOTALL|re.IGNORECASE )      # re fi de taula 2
    m = ini.search ( text_origen )
    if not m :                                          # no es troba la taula
        return ("", 0, 0)
    pos_ini = m.start()                                 # posició inicial de la taula
    text = text_origen[pos_ini:]                        # prenem part final del text
    n = fi.search ( text )
    pos_relativa_fi = n.end()                           # posició relativa final
    taula = text[:pos_relativa_fi]                      # extreiem la taula
    pos_fi = pos_ini + pos_relativa_fi                  # posició final (absoluta)

    taula = trn_chars_especials(taula)                  # convertir objectes HTML &aaa; de la taula

    resultat = (taula, pos_ini, pos_fi)
    return resultat


def taula_a_entcat ( inici_taula, text_origen, article, num_ents ):

    # comprovar que no hi sigui ja 
    cond_hi_es = re.compile ( u'\{\{capentcat' )
    m = cond_hi_es.search ( text_origen )
    if m :
        return text_origen

    taula, pos_ini, pos_fi = extreure_taula ( inici_taula, text_origen, 1 )

    if pos_ini == pos_fi :                              # no s'ha trobat la taula
        return text_origen

    # tots els elements de la primera columna son enllaços [[ ]]
    # els de la segona estan tots entre <B></B>
    # és possible que alguna fila no tingui segon element
    # la taula acaba en </table>

    cond_segueix = re.compile ( u'(?:(?:\]\])|(?:' + article + u'</FONT>)).*(?:</TABLE>)', re.IGNORECASE|re.DOTALL )
    #antiga (cal u"" per unicode...):
    #cond_fila = re.compile ( '(\[\[.*?\]\]).*?(?:<B>(.*?)</B>|\[)', re.IGNORECASE|re.DOTALL )

    re_text = u'((?:\[\[.*?\]\])|(?:' + article + u')).*?(?:<B>(.*?)</B>|\[)'
    cond_fila = re.compile ( re_text, re.IGNORECASE|re.DOTALL )

    sortida = "{{capentcat|center}}\n"

    n_entt = 0

    while cond_segueix.search ( taula ):
        n_entt = int(n_entt) + 1
        m = cond_fila.search ( taula )
        col_1 = m.group(1)
        col_2 = m.group(2)
        if not col_2 :                      #si no hi ha segon element es deixa buit
            col_2 = ""
        sortida = sortida + "{{entcat|" + col_1 + "|" + col_2 + "}}\n"

        pos = m.end() - 1
        taula = taula[pos:]

    sortida = sortida + "{{fientcat}}"
    text_modificat = text_origen[:pos_ini] + sortida + text_origen[pos_fi:]

    if int(num_ents) != n_entt :
        print "\nATENCIÓ: Num. d'entitats de població no coincideix, caldrà edició manual\n"

    return text_modificat


def taula_a_taucat ( inici_taula, text_origen, article ):

    # comprovar que no hi sigui ja 
    cond_hi_es = re.compile ( u'\{\{taucatCap' )
    m = cond_hi_es.search ( text_origen )
    if m :
        text_i_ent = (text_origen, 0)
        return text_i_ent

    taula, pos_ini, pos_fi = extreure_taula ( inici_taula, text_origen, 2 )

    if pos_ini == pos_fi :                              # no s'ha trobat la taula
        return (text_origen, 0)

    #NOTA:  hi han 2 taules, 2x</table> ...                             ^
    #afegeixo paràmetre "rep"etició a extreure_taula()    --------------|

    # treiem les dades del primer camp de la descripció
    # de la imatge de localització
    # [[Imatge:Localització_de_Ribera d'Ondara.png|Localització de Ribera d'Ondara respecte la Segarra]]
    # [[Imatge:Localització_d'Igualada.png|Localització d'Igualada respecte l'Anoia]]
    # [[Imatge:Localització_de_Llívia.png|Localització_de_Llívia respecte la Baixa Cerdanya]]
    cond_imatge = re.compile ( u"Imatge:.*?\|Localització[ _](.*?[ _'])(.*?) respecte (.*?[ '])(.*?)\]\]" )
    # Osona no porta article (sigh...) el cas general és a dins del proper else
    cond_osona = re.compile ( u"Imatge:.*?\|Localització[ _](.*?[ _'])(.*?) respecte Osona\]\]" )
    # condició "del" per a municipis que comencin per "El" -> "del"
    # [[Imatge:Localització del Masnou.png|Localització del Masnou respecte el Maresme]]
    # [Imatge:Localització des Bòrdes.png|Localització des Bòrdes respecte la Vall d'Aran]]
    # [[Imatge:Localització_dels Hostalets de Pierola.png|Localització dels Hostalets de Pierola respecte a l'Anoia]]
    cond_del = re.compile ( u"Imatge:.*?\|Localització[ _]d((?:el)|(?:es)|(?:els))[ _](.*?) respecte (.*?[ '])(.*?)\]\]" )
    
    m = cond_osona.search ( taula )
    n = cond_del.search ( taula )
    if m :                                              #som a Osona
        cap_1 = m.group(1)
        cap_1 = re.sub("_", " ", cap_1)                 #canvi de "de_Lli" a "de Lli"
        cap_2 = m.group(2)
        cap_3 = ""                                      #sense article
        cap_4 = "Osona"
    elif n :
        cap_1 = "d"
        cap_2 = n.group(1) + " " + n.group(2)
        cap_3 = n.group(3)
        cap_4 = n.group(4)
    else :
        m = cond_imatge.search ( taula )
        cap_1 = m.group(1)
        cap_1 = re.sub("_", " ", cap_1)                 #canvi de "de_Lli" a "de Lli"
        cap_2 = m.group(2)
        cap_3 = m.group(3)
        cap_4 = m.group(4)

    #comprovar si el nom de l'article és igual al grup (2)
    #si no ho és quelcom no està be
    if not re.search( article, cap_2, re.IGNORECASE ) :
        sys.exit( "ERROR: Nom d'article i nom esmentat a localització no coincideixen!" )

    #comprovar el tipus de taula, amb o sense bandera o escut
    # si hi ha imatges o links a altres articles detallats sobre els símbols
    ##[[Bandera {{{1}}}{{{2}}}|En detall]]
    bandera_nom_pag = "Bandera " + cap_1 + cap_2
    escut_nom_pag = "Escut " + cap_1 + cap_2
    te_bandera = re.search ( u"Imatge:Bandera", taula )
    te_escut = re.search ( u"Imatge:Escut", taula )
    
    pag_ban = wikipedia.Page(wikipedia.getSite(), bandera_nom_pag)
    pag_esc = wikipedia.Page(wikipedia.getSite(), escut_nom_pag)
    
    existeix_b = pag_ban.exists()
    existeix_e = pag_esc.exists()
    
    #comprovacions manuals
    if existeix_b : print "existeix pàg bandera"
    if existeix_e : print "existeix pàg escut"
    if te_bandera : print "existeix img bandera"
    if te_escut : print "existeix img escut"
     
    tipus = ""
    if te_bandera or pag_ban.exists():
        tipus = tipus + "B"
    if te_escut or pag_esc.exists():
        tipus = tipus + "E"


    sortida = "{{taucatCap" + tipus + "|" + cap_1 + "|" + cap_2 + "|" + cap_3 + "|" + cap_4 + "}}\n"

    # gentilici
    # <tr><td>[[Gentilici]]</td><td>XXXXX</td></tr>
    cond_gentilici = re.compile ( '\[\[Gentilici\]\].*?<td>(.*?)</td>' )
    m = cond_gentilici.search ( taula )
    gen = m.group(1)
    sortida = sortida + "{{taucatGen|" + gen + "}}\n"

    # població
    # <tr><td>[[Població]] ([[2001]])</td><td>486 hab.</td></tr>
    # <tr><td>[[Població]] ([[2001]])</td><td>586</td></tr>
    cond_pobl = re.compile ( u'\[\[Població\]\] \(\[\[(.*?)\]\]\).*?<td>(.*?)((?: hab\.)|(?:</td>))' )
    m = cond_pobl.search ( taula )
    any = m.group(1)
    pob = m.group(2)
    sortida = sortida + "{{taucatPob|" + str(any) + "|" + str(pob) + "}}\n"

    # superfície
    # <tr><td>[[Superfície]]</td><td>54'5 Km<sup>2</sup></td></tr>
    #<tr><td>[[Àrea]]</td><td>15,44 Km<sup>2</sup></td></tr>
    #<tr><td>[[Superfície]]</td><td>14'0 Km<sup>2</sup></td></tr>
    #<tr><td>[[Superfície]]</td><td>8,23 km<sup>2</sup></td></tr>
    cond_sup = re.compile ( u'(?:(?:\[\[Superfície\]\])|(?:\[\[Àrea\]\])).*?<td>(.*?)(?: )+[kK]m' )
    m = cond_sup.search ( taula )
    sup = m.group(1)
    sup = re.sub("\'", ",", sup)                 #canvi de 54'5 a 54,5
    sortida = sortida + "{{taucatSup|" + sup + "}}\n"

    # densitat de població
    # <tr><td>[[Densitat de població|Densitat]] ([[2001]])</td><td>8'9</td></tr>
    #<tr><td>[[Densitat de població|Densitat]] ([[2005]])</td><td>15.868,86 hab/Km<sup>2</sup></td></tr>
    cond_dens = re.compile ( '\|Densitat\]\] \(\[\[(.*?)\]\]\).*?<td>(.*?)(?: hab.*</sup>)*</td>' )
    m = cond_dens.search ( taula )
    any = m.group(1)
    den = m.group(2)
    den = re.sub("'", ",", den)                 #canvi de 8'9 a 8,9
    sortida = sortida + "{{taucatDen|" + any + "|" + den + "}}\n"

    # altitud
    # <tr><td>[[Altitud]]</td><td>581 [[metre|m]]</td></tr>
    cond_alt = re.compile ( '\[\[Altitud\]\].*?<td>(.*?)(?: )+\[\[me' )
    m = cond_alt.search ( taula )
    alt = m.group(1)
    sortida = sortida + "{{taucatAlt|" + alt + "}}\n"

    # entitats
    # <tr><td>Entitats de població</td><td>13</td></tr>
    cond_ent = re.compile ( u'Entitats de població.*?<td>(.*?)</td>' )
    m = cond_ent.search ( taula )
    ent = m.group(1)
    sortida = sortida + "{{taucatEnt|" + ent + "}}\n"

    sortida = sortida + "{{taucatFi}}"

    text_modificat = text_origen[:pos_ini] + sortida + text_origen[pos_fi:]

    # comprovem si el nom de les imatges que hi havia a la taula, 
    # i per consequència al servidor, era "correcte"
    err_nom_img = 0
    nom_img_loc =   u"Localització " + cap_1 + cap_2 + "\.png"
    nom_img_loc_b = re.sub ( " ", "[ _]", nom_img_loc)

    print "regex nom correcte localització: " + nom_img_loc_b.encode('utf-8')

    if not re.search( nom_img_loc_b, text_origen ) :
        err_nom_img = 1
    if te_bandera :
        nom_img_ban = u"Bandera " + cap_1 + cap_2 + " \(petita\)\.png"
        nom_img_ban_b = re.sub ( " ", "[ _]", nom_img_ban)
        print "regex nom correcte bandera: " + nom_img_ban_b.encode('utf-8')
        if not re.search( nom_img_ban_b, text_origen ) :
            err_nom_img = 1
    if te_escut : 
        nom_img_esc = u"Escut " + cap_1 + cap_2 + " \(petit\)\.png"
        nom_img_esc_b = re.sub ( " ", "[ _]", nom_img_esc)
        print "regex nom correcte escut: " + nom_img_esc_b.encode('utf-8')
        if not re.search( nom_img_esc_b, text_origen ) :
            err_nom_img = 1

    vars_ret = (text_modificat, ent, err_nom_img)
    return vars_ret


def main():

    inici_entcat = "<TABLE WIDTH"
    inici_taucat = "<table border"
    article = ""
    num_ents = 0                #per decidir si cal fer entcat

    for arg in sys.argv[1:]:
        if arg.startswith('-e:'):
            inici_entcat = arg[3:]
        elif arg.startswith('-t:'):
            inici_taucat = arg[3:]
        else:
            article = arg

    # msg de canvis
    wikipedia.setAction( u'Robot: taules -> templates, segons [[Viquipèdia:Viquiprojecte Municipis de Catalunya|]]' )

    # pillem la pàgina
    if len(article):
        # byte_string = unicode_string.encode(encoding)
        article = article.decode('utf-8')
        page = wikipedia.Page(wikipedia.getSite(), article)
        text_orig = page.get()
        text = text_orig
    else:
        sys.exit("ERROR: Falta l'article")

    if len(inici_taucat) :
        # taucat
        text, num_ents, err_nom_img = taula_a_taucat(inici_taucat, text, article)

    troba_ent = re.compile ( u'\{\{taucatEnt\|(.*?)\}\}' ) 
    m = troba_ent.search ( text_orig )
    if m :
        num_ents = m.group(1)

    if len(inici_entcat) and ( int(num_ents) > 1 ) :
        # entcat
        # enviar article (nom del municipi) en el cas que surti a la taula sense enllaç
        text = taula_a_entcat(inici_entcat, text, article, num_ents)

    if text_orig != text :
        if err_nom_img :
            print "\nATENCIÓ: El nom d'alguna imatge és incorrecte, cal comprovació manual\n"
        raw_input ( "premeu ENTER per veure quins canvis es faran" )
        wikipedia.showDiff(text_orig, text)
        opcio = wikipedia.inputChoice(u'Vols enviar aquests canvis?',  ['Si', 'No'], ['s', 'N'], 'N')
        if opcio in ['s', 'S']:
            page.put(text)
    else :
        print "No cal fer canvis en aquest"


if __name__ == "__main__":
    try:
        main()
    finally:
        wikipedia.stopme()