Usuari:KRLS/referències.py

# -*- coding: utf-8 -*-                                                      
import codecs, os, re, sys, urllib2
from time import strftime as formatTS
import wikipedia
 
"""
	Este script ha estat creat per a corregir la puntuació en les referències.
	* reubica punts, tancament d'interrogació i tancament d'exclamació posats arrere una referència fins al seu començament.
	
	La sintaxi és ben simple. Només cal fer una crida al script.
	
	Opcionalment s'admeten diversos paràmentres, alguns d'ell necessiten una valor, a continuació es mostre els paràmetres, aquells
	necessiten una valor acaben amb dos punts, els elements posats entre "<>" indiquen una valor definida per l'usuari.
	* -start: <títol>	(Opcional) permet començar l'exploració a partir d'un determinat títol.
	* -end: <títol>		(Opcional) permet aturar l'exploració fins un determinat títol.
	* -count: <nombre>	(Opcional) permet explorar un determinat nombre de pàgines, es superposa al paràmetre -end:.
	* -url: <adreça URL>	(Opcional) permet canviar l'adreça URL d'on es carregarà les pàgines a explorar
				per defecte és http://toolserver.org/~sk/checkwiki/cawiki/cawiki_error_list_error_061.html
				la sintaxi de la pàgina haurà de ser semblant a aquesta pàgina.
	* -file: <fitxer>	(Opcional) permet carregar un fitxer determinat d'on s'obtindrà la llista de pàgines per a explorar.
				Aquesta opció invalida el paràmetre -url:. Les pàgines han d'anar dins de dobles claudators (amb la
				típica sintaxi d'un enllaç intern).
	* -file			(Opcional) semblant al seu precedent, carregarà automàticament el darrer fitxer creat on figuren
				articles per a explorar. Aquesta opció també invalida el paràmetre -url:.  Les pàgines han d'anar 
				dins de dobles claudators (amb la típica sintaxi d'un enllaç intern).
	* -debug		(Opcional) s'usa a l'hora de fer proves, per a no editar cap pàgina.
	* -verbose		(Opcional) permet visualitzar els canvis.
	* -force		(Opcional) no permet cap excepció, explorant totes les pàgines.
	
	Una vegada acabada l'exploració es genera un registre d'aquells articles en els quals no s'ha efectuat cap canvi. El nom del
	fitxer tindrà la següent aparença: referencies_sense_tocar-AAMMDD-HHMMSS.log
	
	També es generarà un fitxer de tots aquells articles que s'han explorat, això permetrà en successives exploracions saltar
	estos mateixos articles, accelerant així el procés (sempre que no s'haja introduït el paràmetre -force). El nom del fitxer
	tindrà la següent aparença: referencies_tocats-AAMMDD-HHMMSS.log
	
"""

class Browser:
	def __init__(self):
		self.user_agent=u'Geni ircpybot 1.0'
		self.cache_control=u'no-cache'
		self.pragma=u'no-cache'
		self.accept_charset='utf-8'

	def getURL(self, url, user_agent=None, nocache=False, encoding=None):
		#"""
		#TODO: Fix 404 (and other errors)  urllib2.HTTPError: HTTP Error 404: Not Found
		#"""
		try:
			request=urllib2.Request(url)
			if user_agent==None:
				request.add_header('User-Agent', self.user_agent)
			if nocache:
				request.add_header('Cache-Control',self.cache_control)
				request.add_header('Pragma',self.pragma)
			if not encoding: encoding=self.accept_charset
			request.add_header('Accept-Charset', encoding)
			response=urllib2.urlopen(request)
			text=response.read()
			response.close()
			return text
		except:
			return ""
B = Browser()	
getURL = B.getURL

def getArgs(txt, params=[]):
	keys=re.findall(r" (-[^ :\.]+[\.:]?)", txt)
	items={}
	for key in keys:
		next = keys.index(key)+1
		if next >= len(keys): next = len(keys)-1
		nextkey=keys[next]
		items[key]=txt.split(key)[1].split(nextkey)[0].strip()
		if key[-1]!=":": items[key]=True
	newdict = {}
	for item in items:
		key   = item[1:]
		if key[-1] in ":.": key= key[:-1]
		value = items[item]
		newdict.update({key: value})
	for param in params:
		if not newdict.has_key(param): newdict[param]=False
	return newdict

def getPagesFromURL(url):
	html=getURL(url)
	pages=re.findall("([^\n<]+)<br />", html)
	return pages

def getArticleLinks(filename):
	f = codecs.open(filename,"r","utf-8")
	txt=f.read()
	f.close()
	pages=re.findall("\[\[(.+?)(?:\|.+)?\]\]", txt)
	return pages
	
def getLastLog(target):
	dir = os.listdir(os.getcwd())
	cur_filename = ""
	for filename in dir:
		if filename.startswith(target) and filename.endswith(".log"): 
			cur_filename=filename
	pages = getArticleLinks(cur_filename) if cur_filename	else []
	return pages

def getPagesFromFile(filename):
	return getLastLog(filename)

def loadReachedPages():
	return getLastLog("referencies_tocats")
	
def order_signs(pages, first, last = None, count = None):
	first = first[0].upper()+first[1:] if len(first)>1 else first.upper()
	if last: last=last[0].upper()+last[1:] if len(last)>1 else last.upper()
	count= int(count) if count else len(pages)

	print "s'han trobat %i articles." % len(pages)
	site = wikipedia.getSite()

	foundFirst=False
	modified, scanned = 0, 0
	first_scanned, last_scanned = "", ""
	unmatched, reached = [], []
	
	for page in pages :
		try:
			scanned+=1
			if scanned > count: break

			title = unicode(page,'utf-8')
			reached.append(title)
			
			if foundFirst==False and not title.startswith(first): 	continue
			if foundFirst==False:
				if count==len(pages): count= len(pages)-scanned 
				scanned=1
				foundFirst=True
			if title in excepted: continue
			
			page = wikipedia.Page(site, title)
			if not first_scanned: first_scanned=title
		
			wikipedia.output("%i/%i. %s" % (scanned,count,page.aslink()))
			try:
				txt = page.get()
			except wikipedia.IsRedirectPage:
				page = page.getRedirectTarget()
				title = page.title()
				wikipedia.output(u"\tredirigeix a [[%s]]" % page.title())
				txt = page.get()
			except wikipedia.NoPage:
				print "\tno existeix"
				continue

			rpl_txt=txt

			#simplest match (point and interrogation)
			rpl_txt =  re.sub(r'([.? ])?(<ref[^/>]*>[^<]+</ref>) *([.?])', r"\3\2", rpl_txt)
			rpl_txt =  re.sub(r'([.? ])?(<ref[^/]+/>) *([.?])', r"\3\2", rpl_txt)

			#bang (!! is used in wikitables)
			rpl_txt =  re.sub(r'(!)?(<ref[^/>]*>[^<]+</ref>) *(!)([^!])', r"\3\2\4", rpl_txt)
			rpl_txt =  re.sub(r'(!)?(<ref[^/]+/>) *(!)([^!])', r"\3\2\4", rpl_txt)

			#ref can got any other embedded tags
			rpl_txt =  re.sub(r'([.? ])?(<ref[^/>]*>[^<]+(?:<[^/>]+>[^<]+</[^>]+>|<[^/]+/>|<!--[^>]+>)[^<]+</ref>) *([.?])', r"\3\2", rpl_txt)

			#repeated signs?
			rpl_txt =  re.sub(r'[.?!]([.?!])(<ref)', r"\1\2", rpl_txt)

			if txt == rpl_txt :      #txt == txt1 :
				h = page.getVersionHistory(revCount=5)
				done=False
				for v in h:
					summaries = (	u"Robot treu puntuació penjada després de referències", 
							u'Robot corregint puntuació duplicada darrere de les referències',
							u'Robot corregint puntuació postposada a les referències'
						     )
					if v[3] in summaries:
						print "\tfet per "+v[2]
						done=True
						break
				if not done and title not in unmatched:
					unmatched.append(title)
				print "\tno hi ha canvis"
			else :
				if verbose:
					wikipedia.showDiff(txt,rpl_txt)
				if not debug:
					page.put(rpl_txt, u'Robot corregint puntuació postposada a les referències')
					modified+=1
			
			if last and title.startswith(last): break
			
		except KeyboardInterrupt:
			break

	last_scanned=title
	
	if unmatched:
		print "no s'han pogut corregir els següents articles:"
		log = codecs.open("referencies_sense_tocar-%s.log" % formatTS("%y%m%d-%H%M%S"),"w","utf-8")
		for art in unmatched:
			log.write(u"[[%s]]\r\n" % art)
			wikipedia.output(art)
		unmatched=len(unmatched)
		log.write("\r\nTotal: %i" % unmatched)
		log.close()
		print "total:", unmatched

	log = codecs.open("referencies_tocats-%s.log" % formatTS("%y%m%d-%H%M%S"),"w","utf-8")
	for art in reached:
		log.write(u"[[%s]]\r\n" % art)
	reached=len(reached)
	log.write("\r\nTotal: %i" % reached)
	log.write("\r\nS'han explorat %i articles i s'ha corregit %i" % (scanned,modified))
	log.write(u'\r\nPrimera pàgina "%s" darrera pàgina "%s"' % (first_scanned, last_scanned))
	print "scanned:", scanned, "modified:", modified
	log.close()

def main():
	#get pages from a file
	filename= params['file'] 
	if filename:
		if isinstance(filename, basestring):
			pages = getPagesFromFile(filename)
		else:
			pages = getLastLog("referencies_sense_tocar")
	#if file is missing, then get pages from an URL.
	else:
		url =  params['url'] if params['url'] else "http://toolserver.org/~sk/checkwiki/cawiki/cawiki_error_list_error_061.html"
		pages = getPagesFromURL(url)
	
	if not pages:
		print "No s'ha especificat l'origen de les pàgines a carregar."
		return
	
	#start at a specified article from the list
	first = params['start'] if params['start'] else pages[0][:1]
	#end scannig when exceed count
	count = params['count']
	#end scanning when reach page
	last = params['last']

	order_signs(pages, first, last, count)
	
	
if __name__ == "__main__":
	params = " ".join(sys.argv)
	try:
		params = unicode(params, "iso-8859-1")
	except UnicodeError:
		try:
			params = unicode(params, "utf-8")
		except:
			pass
	#treat as globals
	params = getArgs(params, ["file", "url", "start","count", "last", "force", "debug", "verbose"])
	debug=params['debug']
	verbose=params['verbose']
	_force_complete_scan =  params['force']
	excepted=loadReachedPages() if not _force_complete_scan else []
	main()

	wikipedia.stopme()