Vés al contingut

Usuari:PereBot/robot coordenades comarques

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

Aquest programa fa servir coordenades de Wikidata. Per una versió més antiga que treu les coordenades de la {{infotaula de municipi de França}} vegeu Usuari:PereBot/robot coordenades cantons.

# -*- coding: utf-8 -*-
# Programa per posar les coordenades a una comarca
# calculant les coordenades mitjanes dels municipis que
# la componen. Els municipis els treu dels articles enllaçats
# de la secció "Municipis" o "Composició", i si no prova
# amb tots els enllaços de l'article. A més, agafa els paràmetres
# de la plantilla Comarcas. Les coordenades
# les llegeix de Wikidata, i exclou els municipis molt
# allunyats de la resta, per evitar les dades errònies,
# que són molt freqüents a Wikidata.

import sys
sys.path.append('C:\pywikipedia')
import wikipedia,catlib
import re

def treuratlla(x): return float(re.sub(u"\|",u"",x))

def coorplant(plant):
    nums=re.findall(u"\|-?[0-9]+[.,]?[0-9]*",plant)
    nums=map(treuratlla,nums)
    if len(nums)==2:
        lat=nums[0]
        lon=nums[1]
    elif len(nums)==4:
        lat=nums[0]+math.copysign(nums[1],nums[0])/60
        lon=nums[2]+math.copysign(nums[3],nums[2])/60
    elif len(nums)==6:
        lat=nums[0]+math.copysign(nums[1],nums[0])/60+math.copysign(nums[2],nums[0])/3600
        lon=nums[3]+math.copysign(nums[4],nums[2])/60+math.copysign(nums[5],nums[3])/3600
    else:
        lat=False
        lon=False
    return lat,lon

#Dona l'enllaç a una pàgina en forma d'interviqui
#L'argument és un objecte pàgina
def enllac(pag):
    site=pag.site()
    llengua=site.lang
    titol=pag.title()
    return "[[:"+llengua+":"+titol+"]]"

# Munta la plantilla a partir de les coordenades
def plantcoord(lat,lon):
    plant=u"{{coord|"+u"{:}".format(lat)+u"|"
    plant=plant+u"{:}".format(lon)+u"|"
    plant=plant+"source:cawiki_type:adm3rd|display=title}}"
#    print plant
    return plant

def dataitem(pag):
    try:
        data=wikipedia.DataPage(pag)
    except wikipedia.NoPage:
        data=False
        print u"Error: no hi ha pàgina a wikidata"
    except wikipedia.MaxTriesExceededError:
        data=False
        print u"Error: Temps excedit"
    except urllib2.HTTPError:
        data=False
        print u"Error HTTP (no deu funcionar el web)"
    return data

# Recupera la propetat "coordenades" a Wikidata
# L'argument és una pàgina de wikidata (objecte pàgina)
# Retorna una cadena.
# Si no hi ha la propietat, retorna una cadena buida.
def datacoord(data):
    ccat=u""
    try:
        dict = data.get()
        claims=dict[u'claims']
        for el in claims:
            m=el[u'm']
            num=m[1]
            if num==625:
                ccat=m[3]
    except IndexError:
        print u"Error: paràmetre sense contingut a wikidata"
        ccat={}
    except wikipedia.NoPage:
        print u"Error: no hi ha pàgina a wikidata"
        ccat={}
    except wikipedia.MaxTriesExceededError:
        print u"Error: Temps excedit"
        ccat={}
    except urllib2.HTTPError:
        print u"Error HTTP (no deu funcionar el web)"
        ccat={}
    try:
        lat=ccat['latitude']
        lon=ccat['longitude']
    except IndexError: # probablement es produeix quan no hi ha coordenades
        return False,False
    except TypeError: # probablement es produeix quan no hi ha coordenades
        return False,False
    except KeyError: # probablement es produeix quan no hi ha coordenades
        return False,False
    return lat,lon

# Coordenades d'un municipi, segons Wikidata
# Per una versió equivalent que fa servir les coordenades de la infotaula
# vegeu la funció coordmunfr al programa específic (i més antic) que
# calcula coordenades de cantons francesos.
def coordmun(pag):
    text=pag.get()
    esmun=re.search(u"[Ii]nfotaula de municipi|\[\[ ?[Cc]ategoria: ?[Mm]unicipis",text)
    if esmun:
        data=dataitem(pag)
        if data:
            lat,lon=datacoord(data)
        else:
            return False,False,False
        if lat==False:
            esmun=False
    else:
        return False,False,False
    return lat,lon,esmun

#Retorna una llista amb els municipis d'un cantó
#L'argument és la pàgina del cantó (amb secció de municipis enllaçats)
#Pot haver-hi enllaços que no siguin municipis.
#Fa servir els enllaços del text de l'article i els paràmetres
#de la plantilla Comarcas.
def municipis(pagcant):
    text=pagcant.get()
    elp=[]  # Llista de noms de municipis trets de la plantilla Comarcas
    if u'Comarcas' in pagcant.templates():
        el0=re.findall(u"Poblacion=.*?\|",text)
        for el in el0:
            el=el.replace("Poblacion=",u"")
            el=re.sub("\|.*",u"",el)
            elp.append(el)
        print u"Municipis trets de la plantilla Comarcas",elp
    else:
        print u"No hi ha la plantilla Comarcas"
    llista=[]
    if not re.search(u"== ?Municipis ?==",text):
        text=re.sub(u"== ?Composició ?==",u"== Municipis ==",text)
        text=re.sub(u"== ?Dades per municipi ?==",u"== Municipis ==",text)
        text=re.sub(u"== ?(Municipis de la comarca|Municipis que la componen) ?==",u"== Municipis ==",text)
    if re.search(u"== ?Municipis ?==",text):
        fragments=re.split(u"== ?Municipis ?==",text)
#        print fragments
        text= fragments [1]
        fragments=re.split(u"==",text)
#        print fragments
        text=fragments[0]
#        print text
    else:
        print u"Sense secció de muncipis. Es tracten tots els enllaços de l'article com a municipis."
    elt=[]  # Llista de noms de municipis (enllaços) trets del text
    fragments=re.split(u"\]\]",text)
    fragments=fragments[:-1]
    for el in fragments:
        el = re.sub(u"\n",ur"",el)
        el = re.sub(u".*\[\[",ur"",el)
        el = re.sub(u"\|.*",ur"",el)
        el = re.sub(u"\]\].*",ur"",el)
        if len(el)>0:
            elt.append(el)
    titols=[]
    for el in elp+elt:
        if not el in titols:
            titols.append(el)
    titols.sort()
    for el in titols:
        if len(el)>0:    
            if el[0]!=u"#" and not re.match(u"(File|Fitxer)\:",el):
                pagmun=wikipedia.Page(site,el)
        #        print pagmun
                try:
                    ex=pagmun.exists()
                except NameError:
                    ex=False
                except wikipedia.BadTitle:
                    ex=False
                if ex:
                    if pagmun.isRedirectPage():
                        pagmun=pagmun.getRedirectTarget()
                try:
                    ex=pagmun.exists()
                except NameError:
                    ex=False
                except wikipedia.BadTitle:
                    ex=False
                if ex:
                    if not pagmun.isRedirectPage():
                        llista.append(pagmun)
                    else:
                        print u"Doble redirecció", pagmun
                else:
                    print u"Enllaç vermell", pagmun
            else:
                print u"Cosa rara que no és un bon enllaç:",el
    return catlib.unique(llista)

# Calcula les coordenades d'un cantó
# Argument és la pàgina del cantó (o qualsevol pàgina amb municipis enllaçats)
def coordcanto(pagcanto):
    llistamun=municipis(pagcanto) # Aquí crida funcions
    try:
        print llistamun #
    except UnicodeEncodeError:
        print u"Llista de municipis no imprimible"
    nmunpot=len(llistamun)
    nmun=0
    slat=0
    slon=0
    slat2=0
    slon2=0
    maxlat=-90
    maxlon=-180
    minlat=90
    minlon=180
    dlat={}
    dlon={}
    dval={}
    if len(llistamun)>1:
        for mun in llistamun:
            try:
                print mun
            except UnicodeEncodeError:
                print u"Municipi no imprimible"
            latm,lonm,nhiha=coordmun(mun) # Aquí crida funcions
            print latm,lonm,nhiha
            if nhiha:
                nmun=nmun+1               
                slat=slat+latm
                slon=slon+lonm
                slat2=slat2+latm**2
                slon2=slon2+lonm**2
                dlat[mun]=latm
                dlon[mun]=lonm
                if latm>maxlat:
                    maxlat=latm
                    munN=mun
                if latm<minlat:
                    minlat=latm
                    munS=mun
                if lonm>maxlon:
                    maxlon=lonm
                    munE=mun
                if lonm<minlon:
                    minlon=lonm
                    munO=mun
        if nmun>0:
            clat=slat/nmun
            clon=slon/nmun
            vlat=slat2/nmun-clat**2
            sdlat=vlat**(0.5)
            vlon=slon2/nmun-clon**2
            sdlon=vlon**(0.5)
            sigmes=2
            lslat=clat+sigmes*sdlat          
            lilat=clat-sigmes*sdlat          
            lslon=clon+sigmes*sdlon          
            lilon=clon-sigmes*sdlon
            slat=0
            slon=0
            nmun=0
            nmunlluny=0
            for mun in dlat.keys():
                if (dlat[mun]<lslat) and (dlat[mun]>lilat) and (dlon[mun]<lslon) and (dlon[mun]>lilon):
                    slat=slat+dlat[mun]
                    slon=slon+dlon[mun]
                    nmun=nmun+1
                else:
                    print mun,u"exclòs per quedar fora dels límits de",sigmes,u"dv"
                    nmunlluny=nmunlluny+1
    else:
        nmun=0
    if nmun>0:
        clat=slat/nmun
        clon=slon/nmun
        if nmun>1:
            print u"Coordenades de la comarca",clat,clon,u"basades en",nmun,u"municipis de",nmunpot,u"possibles"
            if nmunlluny>0:
                print u"EXCLÒS",nmunlluny,u"MUNICIPIS"
            print u"Dispersió lat:",maxlat-minlat,u"Dispersió lon:",maxlon-minlon
            print u"Nord:",munN,u"Sud:",munS,u"Est:",munE,u"Oest:",munO
        if nmun==1:
            print u"Comarca monomunicipal"
            clat=clat+0.001
            clon=clon+0.001
        return plantcoord(clat,clon)
    else:
        print u"Falten municipis per poder calcular"
        return u""

# Retorna les categories i articles d'una categoria, subcategories incloses.
# No torna a mirar les categories que ja ha mirat.
# Filtra pels noms de les categories fent servir una expressió regular.
def miracatfiltre(cat,catprevies=[],filtre=u""):
    articles=cat.articlesList(recurse=False)
    categories=cat.subcategoriesList(recurse=False)
    for scat in categories:
        print scat
#        print u"Títol",scat.title()
        if scat not in catprevies:
            catprevies.append(scat)
            if filtre==u"":
                nopassa=False
                print u"Filtre desactivat"
            else:
                nopassa=re.search(filtre,scat.title())                
            if not nopassa:
                print u"Sí que es llegeix", scat
                noucats,nouarts=miracatfiltre(scat,catprevies+categories,filtre)
                categories=categories+noucats
                articles=articles+nouarts
            else:
                print u"No es llegeix", scat
        else:
            print u"Aquesta ja la tinc vista"
    articles=catlib.unique(articles)         
    return categories, articles
    
#Paraules amb les que comencen categories que tenen les pàgines que no necessiten coordenades (principalment biografies)
def catsnocoord():
    cadena = u"Persones|Jugadors|Polítics|Escriptors|Pintors|Dibuixants"
    cadena = cadena+u"|Poetes|Dramaturgs|Novel·listes|Autors|Traductors"
    cadena = cadena+u"|Escultors|Arquitectes|Músics|Cantants|Actors|Compositors"
    cadena = cadena+u"|Artistes|Cuiners"
    cadena = cadena+u"|Esportistes|Futbolistes|Ciclistes|Nedadors|Entrenadors|Medallistes"
    cadena = cadena+u"|Emperadors|Reis|Ducs|Grans ducs|Comtes|Vescomtes|Virreis|Nobles"
    cadena = cadena+u"|Tsars|Electors|Prínceps|Infants|Barons|Diàdocs|Khans"
    cadena = cadena+u"|Reines|Consorts|Emperadrius|Primeres dames"
    cadena = cadena+u"|Cònsols|Tribuns|Pretors|Sàtrapes|Faraons"
    cadena = cadena+u"|Governadors|Senyors|Marcgravis|Majordoms|Sobirans"
    cadena = cadena+u"|Guanyadors|Exiliats|Militars|Comandants|Militars|Pilots"
    cadena = cadena+u"|Socialistes|Comunistes|Feministes|Militants|Feixistes|Nazis"
    cadena = cadena+u"|Activistes|Presidents|Ministres|Primers ministres|Diputats"
    cadena = cadena+u"|Alcaldes|Consellers|Regidors"
    cadena = cadena+u"|Empresaris|Dirigents"
    cadena = cadena+u"|Periodistes|Directors|Advocats|Juristes"
    cadena = cadena+u"|Científics|Economistes|Físics|Químics|Matemàtics"
    cadena = cadena+u"|Historiadors|Arqueòlegs|Filòsofs"
    cadena = cadena+u"|Alumnes|Professors"
    cadena = cadena+u"|Papes|Religiosos|Bisbes|Monjos|Frares|Abats|Canonges|Sacerdots"
    cadena = cadena+u"|Sants|Heretges|Beats|Déus"
    cadena = cadena+u"|Jesuïtes|Benedictins|Dominics"
    cadena = cadena+u"|Catalans|Anglesos|Escocesos|Gal·lesos"
    cadena = cadena+u"|Víkings|Alemanys|Bavaresos|Prussians|Suïssos"
    cadena = cadena+u"|Andalusins|Àrabs|Algerians|Egipcis"
    cadena = cadena+u"|Imams|Musulmans|Emirs|Sultans|Companys"
    cadena = cadena+u"|Discs|Cançons|Grups de música|Pel·lícules|Canals de televisió|Programes"
    cadena = cadena+u"|Obres literàries|Obres de literatura|Obres teatrals|Llibres|Novel·les|Contes|Personatges"
    cadena = cadena+u"|Dominis de primer|Monedes|Himnes|Banderes|Escuts|Tractats"
    cadena = cadena+u"|Seleccions|Clubs|Partits|Jocs|Campionat|Condecoracions"
    cadena = cadena+u"|Plantilles|Llistes|Articles destacats|Articles bons"
    cadena = cadena+u"|Esport|Entitats"  #Provisional. Treure quan no calgui.
    cadena = cadena+u"|Corona d'Aragó|Sacre Imperi"  #Provisional. Treure quan no calgui.
    return cadena

# Funció que inserta la plantilla Coord (o un altre text) en una pàgina.
# Mira de posar-la davant de l'ORDENA i si no davant les categories.
# Els arguments són la pàgina i el text a afegir (habitualment la plantilla amb
# el seus paràmetres).
# Retorna el text amb la plantilla (o sense, si no ha trobat on posar-la).
#
def insertacoor(page,afegit):
    if page.isRedirectPage():
        page=page.getRedirectTarget()
    text=page.get()
    if re.search(u"\{\{ORDENA",text):
        text=re.sub(u"\{\{ORDENA",afegit+u"\n{{ORDENA",text)
        print u"Text afegit davant de l'ORDENA"
    elif re.search(u"\[\[ ?[Cc]ategoria:",text):
        text=re.sub(u"\[\[ ?[Cc]ategoria:",afegit+u"\n[[Categoria:",text,count=1)
        print u"Text afegit davant de les categories"
    else:
        print u"No he trobat on afegir el text a [["+page.title()+u"]]"
    return text

#Funció que decideix si un article és una comarca.
#article = objecte pàgina
def escomarca(pag):
    tit=pag.title()
    if (u"Comarques" in tit) or (u"Quadrilles" in tit) or (u"Merindades" in tit): #Condició per filtrar nom articles si es possible
        return False
    elif re.match(u"Comarca|Merindad|Quadrilla",tit):
        return True
    text=pag.get()
    if re.search(u"[Ii]nfotaula de municipi|\[\[ ?[Cc]ategoria\: ?[Mm]unicipis",text):
        return False
    elif re.search(u"\{\{ ?[Cc]omarques|\{\{ ?[Cc]omarca|\{\{ ?[Ii]nfotaula (de )?comarca|\[\[ ?[Cc]ategoria\: ?[Cc]omarques",text):
        return True
    elif re.search(u"\[\[ ?[Cc]ategoria\: ?("+catsnocoord()+u")",text):
        return False
    elif re.search(u"[Éé]s una (comarca|de les comarques)",text):
        return True
    elif re.search(u"[Éé]s un municipi",text):
        return False
    print u"No es pot determinar si",pag,u"és una comarca"
    return False

#El programa comença aquí
site=wikipedia.getSite('ca')
catbuscar=u"Comarques de Múrcia" #Posar aquí la categoria que es revisarà
missatge=u" en el marc de la [[VP:QQ13|quinzena de la qualitat]]"  #Missatge promocional. Canviar per "" la resta de l'any.
missatgeno=missatge # Missatge promocional per quan posa {{cal coor}}
calcoortxt=u"{{cal coor esp}}"
categoria = catlib.Category(site,catbuscar)
filtrecats=u"Categoria:("+catsnocoord()+u")"
cats, asc  = miracatfiltre(categoria,filtre=filtrecats)
wikipedia.getall(site,asc)
comptapotencial=len(asc)
print "Articles a la categoria:",comptapotencial
#asc=asc[2:6] #Per fer només un grapat d'articles a la vegada
comptarevisar=len(asc)
informeno=""
marcagh=u"//toolserver.org/~geohack/geohack.php"
marcagh2=u"//tools.wmflabs.org/geohack/geohack.php"
comptaarticles=0
comptajaentenen=0
comptaposoplant=0
comptaposohack=0
comptanocalenllista=0
comptanocalencat=0
comptacalcoor=0
comptacalcoor0=0
for pag in asc:
    comptaarticles=comptaarticles+1
    print comptaarticles,"/",comptarevisar,":",pag
    if pag.isRedirectPage():     #Precaució contra que hi hagi alguna redirecció categoritzada
        pag=pag.getRedirectTarget()
    tit=pag.title()
    if catbuscar!=tit and escomarca(pag)==True:
        tottemp=pag.templates() 
    #    print tottemp
        if u'Coord' in tottemp:
            print u"Ja té la plantilla coord"
            comptajaentenen=comptajaentenen+1
        elif u"Llista d" in pag.title():
            print u"És una llista. No li calen coordenades generals."
            comptanocalenllista=comptanocalenllista+1
        elif marcagh in pag.get(expandtemplates=True) or marcagh2 in pag.get(expandtemplates=True):
            print u"Ja té coordenades però sense la plantilla coord"
            comptajaentenen=comptajaentenen+1
        else:
            resumno=enllac(pag)+u"\n"
            coordexistent=False
            plantxt=coordcanto(pag) # Aquí és on crida els càlculs
            if len(plantxt)>6:
                noutext=insertacoor(pag,plantxt)
                noutext=re.sub(u"{{[Cc]al coor.*}}\n?",u"",noutext)
                noutext=re.sub(u"\n\n+{{coord",u"\n\n{{coord",noutext)
#                pagprova=wikipedia.Page(site,u"Usuari:PereBot/taller")
                #canviar pagprova per pag a la línia següent per tenir versió funcional
                pag.put(noutext,u"Bot posa a la comarca la mitjana de les coordenades dels municipis"+missatge)
                comptaposohack=comptaposohack+1
                resumno=u""
            else:   # Si no ha pogut posar coordenades
                if u"*" in resumno:
                    informeno=informeno+resumno+u"\n\n"              
        # Comença a posar cal coor, si cal.
                if re.search(u"{{[Cc]al coor.*}}\n?",pag.get()):
                    print pag,u"Ja té {{cal coor}}"
                    comptacalcoor0=comptacalcoor0+1
                else:
                    print u"Li cal {{cal coor}} a",pag
                    comptacalcoor=comptacalcoor+1
                    noutext=insertacoor(pag,calcoortxt)
                    pag.put(noutext,u"Bot posa "+calcoortxt+missatgeno)
    else:
        print pag,u"no és una comarca"
resumestadistic=u"La [[:categoria:"+catbuscar+u"]] (un cop filtrada) té "+'{:}'.format(comptapotencial)+u" articles\n\n"
resumestadistic=resumestadistic+u"Revisats "+'{:}'.format(comptaarticles)+u" articles\n\n"
resumestadistic=resumestadistic+u"Ja tenien coordenades "+'{:}'.format(comptajaentenen)+u" articles\n\n"
resumestadistic=resumestadistic+u"No els calen coordenades a "+'{:}'.format(comptanocalenllista+comptanocalencat)+u" articles (llistes, persones, films, etc.)\n\n"
resumestadistic=resumestadistic+u"*Detectats pel nom (llistes): "+'{:}'.format(comptanocalenllista)+u" articles\n\n"
resumestadistic=resumestadistic+u"*Detectats per les categories: "+'{:}'.format(comptanocalencat)+u" articles\n\n"
resumestadistic=resumestadistic+u"Posades coordenades interpolant a "+'{:}'.format(comptaposohack)+u" articles\n\n"
resumestadistic=resumestadistic+u"Ja tenien cal coor "+'{:}'.format(comptacalcoor0)+u" articles\n\n"
resumestadistic=resumestadistic+u"Posat cal coor a "+'{:}'.format(comptacalcoor)+u" articles\n\n"
queden=comptaarticles-comptajaentenen-comptaposoplant-comptaposohack-(comptanocalenllista+comptanocalencat)
resumestadistic=resumestadistic+u"Queden "+'{:}'.format(queden)+u" articles sense coordenades\n\n" # (comptant els que no tenen iw)\n\n"
resumestadistic=resumestadistic+u"Des quals "+'{:}'.format(comptacalcoor+comptacalcoor0)+u" estan marcats amb cal coor\n\n"
resumestadistic=resumestadistic+u"Hi ha "+'{:}'.format(queden-comptacalcoor-comptacalcoor0)+u" casos dubtosos\n\n"
print resumestadistic
informeno=informeno+u"\n"+resumestadistic
if informeno!=u"":
    paginforme=wikipedia.Page(site,u"Usuari:PereBot/coordenades")  # Pàgina on deixarà l'informe del que ha fet
    informeno=u"\n=="+catbuscar+u"==\n"+informeno+u"\n--~~~~\n\n"
#    paginforme.put(paginforme.get()+informeno,catbuscar)
wikipedia.stopme()