Viquipèdia:Viquitrobada 2009/Taller de bots/Exemple coordenades

De la Viquipèdia, l'enciclopèdia lliure
# -*- coding:utf-8 -*-
"""
psq_coordenades.py
 
El següent programa es va fer entre el 15 de novembre de 2009 per poder il·lustrar com s'empren
alguns mòduls del pywikipedia.
 
Script creat per extreure la plantilla de coordenades existent als articles en anglés.
 
Els articles sense interwikis, es registraran en un fitxer de text que anomenarem psq_coordenades.log.
 
"""
 
#carreguem els mòduls de la biblioteca Python
import codecs, re
 
#mòduls pywikipedia
import catlib, wikipedia
 
#declarem una funció per editar
def edita(pagina, text1, text2, resum):
	wikipedia.showDiff(text1, text2)
	editem = wikipedia.input("editem?")
	if editem in ("Si","S","s","si","y","Y","Yes",u"Sí",u"sí"):
		pagina.put(text2, resum)


#creem un fitxer per registrar les excepcions.
registre = codecs.open("psq_coordenades.log", "a", "utf-8")
 
# Assignem una funció del mòdul de wikipedia a la variable site per a especificar sobre quin projecte volem treballar.
# Esta funció pot dur dos arguments, si no els posem, s'agafen per defecte els que hem definit al fitxer user-config.py corresponent a les
# variables lang i fam.
projecte = wikipedia.getSite()
 
# Amb la següent variable obtenim un objecte Category per poder treballar amb la categoria "Articles mancats de coordenades"
cat = catlib.Category(projecte, u"Categoria:Articles mancats de coordenades")
 
# De l'objecte anterior extraem els articles mitjançant el mètode .articles()
# Aquest mètode permet explorar recursivament les subcategories i extreure'n els seus articles assignant al argument 'recurse' la valor de True.
# La llista del mètode obté objectes Page del qual podrem treure el títol, el text, les plantilles, les categories, els enllaços interlingüístics,
# el número corresponent al seu espai de noms, l'idioma, el projecte, etc.
pagines = cat.articles(recurse=True)
 
#Iniciem un bucle per anar obrint cada pàgina i conéixer-ne el seu contingut i les seues plantilles.
for pagina in pagines:

	# El mòdul de wikipedia té una funció per assegurar una sortida evitant errors de codificació, que varien segons la consola que emprem.
	# tractant-se de la Viquipèdia on aparéixen molts diacrítics, el més recomanable és emprar esta funció enlloc de l'intrucció print.
	wikipedia.output(pagina.title())

	# Agafem el text de l'article en català.
	text_cat = pagina.get( get_redirect = True ) 
	nou_text = text_cat # Esta variable l'afegim per després poder comprovar els canvis.

	#si al text ja figura la plantilla {{coord}}, llavors traem la plantilla {{cal coor}}, i passem a un altre article.
	plantilles_cat = pagina.templates()
	if "{{Coord" in plantilles_cat:
		edita(pagina, text_cat, text_nou, u"Bot: eliminant plantilla {{cal coord}}, ja hi és")                
		continue
	else:

		# Ara obtindrem els enllaços interlingüístics de l'objecte Page assignat en cada element de la llista de pàgines.
		# Els elements d'esta llista també seran objectes Page.
		interwikis = pagina.interwiki()

		#boolean per saber si s'ha obtingut l'interwiki en anglés
		iw_en_angles = False

		# De nou inicialitzem un bucle per cercar l'article en anglés corresponent.
		for interwiki in interwikis:

			# Assignem a la variable projecte el mètode .site() de l'objecte que ens permetrà conéixer l'idioma de l'interwiki
			projecte_iw = interwiki.site()
			idioma   = projecte_iw.language()

			# Si l'enllaç interlinguístic no es correspon a l'aticle en anglés, passem al següent interwiki.
			if idioma != "en":
				continue
			else:

				iw_en_angles = True

				# Obtenim la llista de plantilles que conté l'article.
				# En este cas retorna cadenes de text del títol de la plantilla amb el títol normalitzat, és a dir, la primera lletra sempre figurarà en majúscula.
				plantilles_iw = interwiki.templates()

				# Si a la llista no hi ha la cadena "Coord", llavors l'article no ha de tenir la plantilla amb les coordenades,
				# per la qual cosa eixim del bucle dels interwikis (ja hem trobat l'article, però no ens serveix).
				if "Coord" not in plantilles_iw:
					registre.write( u"# [[%s]] té iw [[:en:%s]] però este article no té la plantilla {{coord}}\n" % ( pagina.title(), interwiki.title() ) )
					break
				else:    
					# Ja sabem que l'article en anglés conté la plantilla, ara carreguem el seu contingut.
					text_ang = interwiki.get( get_redirect = True )

					# Fem una cerca mitjançant una expressió regular per obtindre tot el text de la plantilla coord
					ER_plantilla = re.search(u"(\{\{[Cc]oord\|[^}]*\}\})", text_ang)

					# Si es troba una coincidència podrem obtindre el text de la plantilla amb el mètode .group()
					# És important avaluar l'objecte retornat pel mètode .search() ja que en ser fals, ens retorna None
					if ER_plantilla:

						resum = "Bot: afegint plantilla {{coord}}"
						plantilla = ER_plantilla.group(1)

						# Mitjançant una altra regexp cerquem la plantilla de {{cal coor *}}, per a retirar-la.
						nou_text = re.sub("(\{\{ *[Cc]al coor[^}]*\}\}\s*\n)", "", nou_text)

						# De nou cerquem una cadena amb una expressió regular. Pretenem obtenir la primera etiqueta de categoria
						# per poder col·locar-hi abans la plantilla {{coord}}, si ens trobem {{ORDENA:*}} llavors ho inserim abans d'esta etiqueta.
						RE_categoria = re.search(u"(\{\{ORDENA:[^}]*\}\}|\[\[[Cc]ategoria:[^\]]*\]\])", nou_text)
						
						if RE_categoria:
							categoria = RE_categoria.group(1)
							insereix_plantilla = "%s\n%s" % (plantilla, categoria)
							nou_text = nou_text.replace(categoria, insereix_plantilla)
							edita(pagina, text_cat, nou_text, resum)
							#eixim del bucle dels interwikis, no té sentit seguir endavant.
							break

						#L'article no està categoritzat, llavors intentarem col·locar la plantilla abans dels interwikis.
						#Cerquem primer que res el comentari que solen afegir els bots abans dels interwikis
						RE_comentari_iw = re.search(u"(<!-- ?interwikis ?-->)", nou_text)

						if RE_interwiki:
							comentari_iw = RE_interwiki.group(1)
							text_nou = plantilla + "\n" + comentari_iw
							edita(pagina, text_cat, nou_text, resum)
							#eixim del bucle dels interwikis, no té sentit seguir endavant.
							break

						#si no hi és, hem de cercar el primer iw
						else:
							primera_iw = interwikis[0].aslink()
							text_nou = plantilla + "\n" + primera_iw
							wikipedia.showDiff(text_cat, nou_text)                    
							edita(pagina, text_cat, nou_text, resum)
							#eixim del bucle dels interwikis, no té sentit seguir endavant.
							break

		#Ja hem mirat tots els interwikis i sabem si hem trobat l'interwiki en anglés
		#si no s'ha trobat, ho registrem.
		if not iw_en_angles:
			registre.write( u"# [[%s]] no té interwiki en anglés\n" % pagina.title() )

#tanquem el registre
registre.close()
 
#aturem el bot
wikipedia.stopme()