Progetto:Bot/Programmi in Python per i bot/uploader7.py
Versione 07.07.15
Abilitata la chiamata via linea di comando
# -*- coding: cp1252 -*- import pywikibot as wikipedia import os,re,json,sys from datetime import date from urllib import FancyURLopener '{{}}' # dati obbligatori: data, autore, titolo, base, from, to mesi=".gennaio.febbraio.marzo.aprile.maggio.giugno.luglio.agosto.settembre.ottobre.novembre.dicembre".split(".") sito=wikipedia.Site("it","wikisource") commons=wikipedia.Site("commons","commons") class MyOpener(FancyURLopener): version = version = 'User-Agent: Alex (+http://it.wikisource.org/wiki/Utente:Alex_brollo)' opener=MyOpener() ''' Nuova versione: automazione integrale Parametro unico: nome del File o dell'Indice Flusso: 1. verificare se esiste il djvu in locale e eventualmente caricarlo 2. caricare la pagina Indice e estrarne tutti i dati con parseTemplate e eseguendo il parsing di pagelis e sommario 3. caricare la pagina Discussioni indice e caricare memoRegex e RigaIntestazione 4. caricare il testo delle pagine in nsPagina 4. creare la pagina principale in ns0 5. creare le altre sottopagine compreso tag pages provvisorio dai dati di Sommario ''' # routine base def carica(fileDjvu,ini=None,fin=None,sovrascrivi=False,\ aggiustaParagrafi=False,test=False,soloNs0=False,piu_uno=True): if ini==None: ini=1 # normalizzazione nome file fileDjvu=fileDjvu.replace(" ","_") #caricamento di tutti i dati #0 download del file djvu se non esistente commonsGrab("File:"+fileDjvu) #1 caricamento template Indice e eventuale caricamento del file djfu dati=caricaDatiIndice(fileDjvu) #2 lettura numero pagine numeroPag=numeroPagine(fileDjvu) if fin==None: fin=numeroPag #3 parsing sommario sommario=caricaSommario(dati[0]["Sommario"],numeroPag) #4 parsing pagelist pagelistDict=pagelist(dati[0]["Pagine"]) #5 parsing memoRegex memoregex=caricaMemoregex(dati[1]) #6 parsing schemi RigaIntestazione riList=caricaSchemi(dati[1]) #7 loop creazione pagine if not soloNs0: for p in range(ini,fin): nomePagina="Pagina:"+fileDjvu+"/"+str(p) pagina=wikipedia.Page(sito,nomePagina) if pagina.exists() and not sovrascrivi: continue # preparazione comando djvuLibre comando="djvutxt -page=%numeroPagina %fileDjvu > pagina.utf"\ .replace("%numeroPagina",str(p))\ .replace("%fileDjvu",fileDjvu) #lancio comando os.system(comando) # elaborazione testo testo=unicode(open("pagina.utf").read(),"utf-8").replace(u"\x1f","") # qui aggiungere passi di elaborazione; il testo è unicode testo=djvutxtFix0(testo,aggiustaParagrafi) # esecuzione memoregex testo=eseguiMemoregex(testo,memoregex) #creazone rigaIntestazione ri=creaRi(p,pagelistDict,riList) #eliminazione testo rigaintestazione testo=testo.split("\n") if simil(testo[0].lower(),ri.lower(),2)>0.50: # print simil(testo[0].lower(),ri.lower(),2),ri, testo[0] testo=testo[1:] testo="\n".join(testo).strip() #aggiunta rigaintestazione header='<noinclude><pagequality level="1" user="Alebot" /><div class="pagetext">#ri#\n\n\n</noinclude>'.replace("#ri#",ri) footer='<noinclude></div>\n<references/></div></noinclude>' testo=header+testo+footer if not test: pagina.put(testo) else: print nomePagina print testo #8 loop creazione pagine ns0 listaPagine=listaNs0(sommario) for i in range(len(listaPagine)): # se solopagina ha un valore continua se il valore non corrisponde # a listaPagine[i] pagina=wikipedia.Page(sito,listaPagine[i]) if (not sovrascrivi): if pagina.exists(): print "Pagina ",listaPagine[i], u" già esistente" continue #creaPagina(listaPagine[i]) print "Lancio creazione di: ",listaPagine[i] # si ottiene qual+inclInt oppure qual+Intestazione, pages, from, to sottopagina=listaPagine[i].replace("_"," ") testoSottopagina=creaSottopagina(fileDjvu,sommario,sottopagina,dati,piu_uno) # if test: print testoSottopagina else: pagina.put(testoSottopagina) return def listaNs0(sommario): l=[] for i in range(len(sommario)): stp=sommario[i]["nome"] if not stp in l: l.append(stp) l1=[] for i in range(len(l)): if len(l[i].split("/"))==1: l1.append(l[i]) if len(l1)==0: l1.append(l[i].split("/")[0]) for i in range(len(l)): if len(l[i].split("/"))>1: l1.append(l[i]) return l1 def caricaDatiIndice(fileDjvu): rawIndice=wikipedia.Page(sito,"Indice:"+fileDjvu).get() print "Letti dati Indice:"+fileDjvu datiIndice=parseTemplate(rawIndice,":MediaWiki:Proofreadpage_index_template")[0] rawDiscussioniIndice='<inizio>1\t1000\t{{RigaIntestazione|999||}}\t{{RigaIntestazione|||999}}<fine>\n'+\ '{"c (.+)":["c (.+)","{{Centrato|$1}}","gm"]}' pdi=wikipedia.Page(sito,"Discussioni indice:"+fileDjvu) if pdi.exists(): rawDiscussioniIndice=pdi.get() print "Letti dati Discussioni indice:"+fileDjvu else: print "Pagina Discussioni indice non esiste, creo valori di default" return (datiIndice,rawDiscussioniIndice) def caricaMemoregex(testo): rls=find_stringa(testo,'\n{"','"]}',1) if rls=="": rls=ur'{"^c\\ (.+)":["^c\\ (.+)","{{Centrato|$1}}","gm"],"^ct (.+)":["^ct (.+)","{{Centrato|{{Type|$1}}}}","gm"]}' #print rls if rls !="": memoregex=json.loads(rls) for regex in memoregex: memoregex[regex][1]=memoregex[regex][1].replace("$1",r"\1")\ .replace("$2",r"\2").replace("$3",r"\3") return memoregex def caricaSchemi(testo): schemi=find_stringa(testo,"<inizio>","<fine>",0) if schemi=="": schemi="1\t1000\t{{RigaIntestazione|999||}}\t{{RigaIntestazione|||999}}" riList=caricaRighe1(schemi) return riList # costruisce RigaIntestazione per la pagina corrente def creaRi(pagina,pagelistDict,riList): numeroPagina=pagelistDict[pagina] #print pagina,numeroPagina rigaIntestazione="{{RigaIntestazione|||}}" for i in range(len(riList)): if pagina>=int(riList[i][0]) and pagina<int(riList[i][1]): if isOdd(numeroPagina): # isOdd gstisce numeri, digitals e romani rigaIntestazione=riList[i][2] else: rigaIntestazione=riList[i][3] rigaIntestazione=rigaIntestazione.replace("999",str(numeroPagina)) break return rigaIntestazione # esegue memoRegex def eseguiMemoregex(testo,memoregex): for i in memoregex: r=re.compile(memoregex[i][0]) testo=re.sub(r,memoregex[i][1],testo) return testo def caricaSommario(testoSommario,pagine): listaIndiceSommario=produci_lista(testoSommario,'{{Indice sommario','}}',1) sommario=[] for i in range(len(listaIndiceSommario)): dato=parseTemplate(listaIndiceSommario[i],"Indice sommario")[0] sommario.append(dato) for i in range(len(sommario)): try: sommario[i]["to"]=sommario[i+1]["from"] except: sommario[i]["to"]=str(pagine) return sommario # restituisce il numero di pagine di un file djvu def numeroPagine(fileDjvu): os.system('djvused -e "n" %fileDjvu>numeroPagine.utf'.replace("%fileDjvu",fileDjvu)) np=int(open("numeroPagine.utf").read().strip()) return np def creaSottopagina(fileDjvu,sommario,pagina,dati,piu_uno): # crea template Qualità oggi=date.today() qual=u"{{Qualità|avz=25%|data=#data|arg=}}" qual=qual.replace("#data",str(oggi.day)+" "+mesi[int(oggi.month)]+" "+str(oggi.year)) paginaBase=False if not "/" in pagina: paginaBase=True # sommario viene scorso alla ricerca dell'elemento pagina. # tre situazioni: # sottopagina; # pagina principale senza pagina titolo=Frontespizio; # pagina principale con pagina titolo=Frontespizio for posizione in range(len(sommario)): if sommario[posizione]["nome"]==pagina or (paginaBase and sommario[posizione]["nome"]=="Frontespizio"): break # costruzione di IncludiIntestazione oppure di Intestazione if "/" in pagina: #sottopagina inclInt=u"{{IncludiIntestazione|sottotitolo=#sottotitolo|prec=#prec|succ=#succ}}" # pages=u'<pages index="#indice" from=#from to=#to fromsection= tosection= /> # crea IncludiIntestazione prec=("" if posizione==0 else rel_atob(pagina,sommario[posizione-1]["nome"])) succ=("" if posizione==len(sommario)-1 else rel_atob(pagina,sommario[posizione+1]["nome"])) template=inclInt.replace("#sottotitolo",sommario[posizione]["titolo"])\ .replace("#prec",prec)\ .replace("#succ",succ) #pages=pages.replace("#from",sommario[posizione]["from"]).replace("#to",sommario[posizione]["to"]).replace("#indice",fileDjvu) else: schemaIntestazione=u'''{{Intestazione | Nome e cognome dell'autore = #autore | Titolo =#titolo | Iniziale del titolo = | Anno di pubblicazione = #anno | Lingua originale del testo = | Nome e cognome del traduttore = | Anno di traduzione = | Progetto = #progetto | Argomento = | URL della versione cartacea a fronte = Indice:#base }} ''' template=schemaIntestazione.replace("#autore",dati[0]["Autore"])\ .replace("#anno",dati[0]["Anno"])\ .replace("#titolo",pagina)\ .replace("#progetto",dati[0]["Progetto"])\ .replace("#base",fileDjvu) pages='\n\n<pages index="#indice#" from=#from# to=#to# fromsection= tosection= />'\ .replace("#indice#",fileDjvu)\ .replace("#from#",sommario[posizione]["from"]) if piu_uno: pages=pages.replace("#to#",sommario[posizione]["to"]) else: pages=pages.replace("#to#",str(int(sommario[posizione]["to"])-1)) return qual+template+pages # esegue la post-elaborazione del testo def djvutxtFix0(testo,aggiustaParagrafi): # pulizia scannos comuni testo=testo.replace(u"\x1d\x0b","")\ .replace(u"\n\x1f\n\x0c","")\ .replace(u"\x0c","")\ .replace("\n\x1f","\n\n")\ .replace("\n\nDigitized by ","")\ .replace(u"\u2022",".")\ .replace(" \n","\n")\ .replace(" ,",",")\ .replace(" .",".")\ .replace(" ;",";")\ .replace(" :",":")\ .replace(u"¬","-")\ .replace("\t"," ")\ .replace("'",u"\u2019") #preOCR testo=testo.replace("{","(").replace("}",")")\ .replace("<","").replace(">","")\ .replace("[","(").replace("]",")") # eliminazione spazi a destra e a sinistra e stripping finale testo=testo.split("\n") for i in range(len(testo)): testo[i]=testo[i].strip() testo="\n".join(testo).strip() #dehyphenazione con salvataggio dell'eventuale ultimo hyphen testo=re.sub(ur"[-¬]\n([^ ]*)[ ]*[\n]?",ur"\1\n",testo) #aggiustamento paragrafi if aggiustaParagrafi: testo=testo.replace("\n\n","<fine paragrafo>")\ .replace(".\n",".<fine paragrafo>")\ .replace("?\n","?<fine paragrafo>")\ .replace(":\n","!<fine paragrafo>")\ .replace("!\n","!<fine paragrafo>")\ .replace("\n"," ")\ .replace("<fine paragrafo>","\n\n") return testo # carica gli schemi e intervalli di RigaIntestazione # si aspetta un file nomedjvu.ri # pagina iniziale, pagina finale, rigaIntestazione pari, rigaIntestazione dispari # separati da tabulazioni def caricaRighe1(testo): ri=testo.split("\n") for i in range(len(ri)): ri[i]=ri[i].split("\t") ri[i][0]=int(ri[i][0]) ri[i][1]=int(ri[i][1]) return ri # estrae dalla pagina Indice correlata al file djvu il codice pagelist # e lo trasforma in un dizionario numero pagina djvu:numero pagina cartacea def pagelist(pagine): codice=find_stringa(pagine,"<pagelist","/>",0).strip() r_to=re.compile(r"^to=(\d+)") r_from=re.compile(r"^from=(\d+)") r_1to1=re.compile(r"^(\d+)to(\d+)=(.+)") r_eq=re.compile(r"^(\d+)=(\d+)") r_eq1=re.compile(r"^(\d+)=([^0-9]+)") codice=codice.split() np=int(open("numeroPagine.utf").read().strip()) paglist={} for i in range(1,np+1): paglist[i]=str(i) stili=[] for c in codice: if re.match(r_to,c): # caso tipo to=100 #print c, "elemento tipo to=" continue if re.match(r_from,c): # caso tipo from=100 #print c, "elemento tipo from=" continue if re.match(r_1to1,c): # caso tipo to=100 #print c, "elemento tipo 1to1=x" # stili: roman highroman empty if re.match(r_1to1,c).group(3) in ["roman","highroman","empty"]: stili.append(c) else: da=int(re.match(r_1to1,c).group(1)) finoa=int(re.match(r_1to1,c).group(2))+1 for i in range(da,finoa): paglist[i]=re.match(r_1to1,c).group(3) if re.match(r_eq1,c): # caso tipo 1=- #print c, "elemento tipo 1=-" da=int(re.match(r_eq1,c).group(1)) paglist[da]=re.match(r_eq1,c).group(2) if re.match(r_eq,c): # caso tipo to=100 #print c, "elemento tipo 2=1" da=int(re.match(r_eq,c).group(1)) ini=int(re.match(r_eq,c).group(2)) while da<np: paglist[da]=str(ini) da+=1 ini+=1 for stile in stili: da=int(re.match(r_1to1,stile).group(1)) finoa=int(re.match(r_1to1,stile).group(2))+1 stileCorr=re.match(r_1to1,stile).group(3) for i in range(da,finoa): if stileCorr=="roman": if paglist[i].isdigit(): paglist[i]=int_to_roman(int(paglist[i])) if stileCorr=="highroman": if paglist[i].isdigit(): paglist[i]=int_to_roman(int(paglist[i]),True) return paglist ############### # funzioni varie di servizio ############### def fileObj(nomeFile): pagina=wikipedia.Page(commons,nomeFile) paginaFile=wikipedia.FilePage(pagina) return paginaFile def grab(url,output): page=opener.open(url+"?action=render") content=page.read() open(output,"wb").write(content) risposta="File salvato in "+output print risposta return def commonsGrab(nomeFile): if not nomeFile.startswith("File:"): nomeFile="File:"+nomeFile #normalizzazione nomeFile=nomeFile.replace(" ","_") obj=fileObj(nomeFile) if os.path.isfile(nomeFile.replace("File:","")): print u"File già esistente" else: print "Download in corso..." grab(obj.fileUrl(),nomeFile.replace("File:","")) print "Finito" return def simil(a,b,c=10): punti=0 test=0 if len(a)<=c or len(b)<=c: return -1 for i in range(0,len(a)-c+1): test+=1 #print a[i:i+c] if a[i:i+c] in b: punti+=1 somiglianza=(punti*100/test)/100. return somiglianza def find_stringa(stringa,idi,idf,dc=0,x=None,side="left"): if side=="right": idip=stringa.rfind(idi) else: idip=stringa.find(idi) idfp=stringa.find(idf,idip+len(idi))+len(idf) if idip>-1 and idfp>0: if x!=None: while stringa[idip:idfp].count(x)>stringa[idip:idfp].count(idf): if stringa[idip:idfp].count(x)>stringa[idip:idfp].count(idf): idfp=stringa.find(idf,idfp)+len(idf) if dc==0: vvalore=stringa[idip+len(idi):idfp-len(idf)] else: vvalore=stringa[idip:idfp] else: vvalore="" return vvalore def produci_lista(testo,idi,idf,dc=1,inizio=None): t=testo[:] lista=[] while not find_stringa(t,idi,idf,1,inizio)=="": el=find_stringa(t,idi,idf,1,inizio) t=t.replace(el,"",1) if dc==0: el=find_stringa(el,idi,idf,0,inizio) lista.append(el) return lista numeral_map = tuple(zip( (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1), ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I') )) def int_to_roman(i,highroman=False): result = [] for integer, numeral in numeral_map: count = i // integer result.append(numeral * count) i -= integer * count roman=''.join(result) if not highroman: roman=roman.lower() return roman def roman_to_int(n): n=n.upper() i = result = 0 for integer, numeral in numeral_map: while n[i:i + len(numeral)] == numeral: result += integer i += len(numeral) return result def isOdd(n): try: pari= (int(n)%2==0) except: pari= (roman_to_int(n) %2 ==0) return pari # wiki template parser. Extracts the tl "template" from the containing "text" # and returns a list containing a list (parameter list) and a dictionary (parameter names # content) # dependencies: code(), find_stringa(), produci_lista(). # The object can be reverted to a template code by rewrite(). def parseTemplate(testo,template): template=template[0:1].upper()+template[1:] testo=testo.replace("{{"+template,"{{"+template[0:1].upper()+template[1:])\ .replace("{{"+template[0:1].lower()+template[1:],"{{"+template[0:1].upper()+template[1:]) templateOld=find_stringa(testo,"{{"+template,"}}",1,"{{") template=templateOld[2:-2] t,b=code(template) t=t.split("|") n=0 d={} l=[] for i in range(len(t)): x=t[i].split("=",1) x[0]=x[0].strip() if len(x)==2: x[1]=x[1].strip() d[x[0]]=x[1] l.append(x[0]) else: d[str(n)]=x[0] l.append(str(n)) n+=1 for i in d: while find_stringa(d[i],"#e","#",1)!="": d[i]=d[i].replace(find_stringa(d[i],"#e","#",1),b[eval(find_stringa(d[i],"#e","#",0))]) return d,l def code(p=""): if p=="": p='''prova ''test'' <test1> prova' test {{test2<br />}} prova test <test1> prova test [[test3' {{test2' <br />}} ]] prova [test4] prova' http://www.alex'.com prova ''' lista=[] p1=p[:] ne=0 l=produci_lista(p1,u"<!--",u"-->",1) for r in l: el="#e"+str(ne)+"#" lista.append(r) p1=p1.replace(r,el) ne=ne+1 l=produci_lista(p1,"{{","}}",1,inizio="{{") for r in l: el="#e"+str(ne)+"#" lista.append(r) p1=p1.replace(r,el) ne=ne+1 #print l #return l=produci_lista(p1,u"<",u">",1) for r in l: el="#e"+str(ne)+"#" lista.append(r) p1=p1.replace(r,el) ne=ne+1 l=produci_lista(p1,u"[[",u"]]",1) for r in l: el="#e"+str(ne)+"#" lista.append(r) p1=p1.replace(r,el) ne=ne+1 l=produci_lista(p1,u"[",u"]",1) for r in l: el="#e"+str(ne)+"#" lista.append(r) p1=p1.replace(r,el) ne=ne+1 return [p1,lista] # d: dictionary from parseTemplate: l: list from parseTemplate def rewrite(oggettoTemplate): d=oggettoTemplate[0] l=oggettoTemplate[1] testo="{{"+d["0"]+"\n" for i in l[1:]: if (i.isdigit()): testo+=" | "+d[i]+"\n" else: testo+=" | "+i+" = "+d[i]+"\n" testo+="}}\n" return testo def rel_atob(a,b): # creazione di link relativo da A a B path=os.path.relpath(b,a).replace("\\","/") return path+"/" if path.endswith("..") else path def split(pagina): splitSourcePage=wikipedia.Page(sito,pagina) testo=splitSourcePage.get().split("\n") lista=produci_lista(testo,"==[[Pagina","]]==") print "Pagine: "+len(lista) pointer=testo.find(lista[0]) iniziotesto=testo[0:pointer] testo=testo[pointer:] return def main(argv): #print argv #def carica(fileDjvu,ini=None,fin=None,sovrascrivi=False,\ # aggiustaParagrafi=False,test=False,soloNs0=False,piu_uno=True): fileDjvu=argv[0] sovrascrivi=False aggiustaParagrafi=False test=False ini=None fin=None soloNs0=False piu_uno=True for arg in argv[1:]: if arg.startswith("sovrascrivi="): sovrascrivi=(arg.replace("sovrascrivi=","")=="True") if arg.startswith("aggiustaParagrafi="): aggiustaParagrafi=(arg.replace("aggiustaParagrafi=","")=="True") if arg.startswith("ini="): ini=int(arg.replace("ini=","")) if arg.startswith("fin="): fin=int(arg.replace("fin=","")) if arg.startswith("soloNs0="): soloNs0=(arg.replace("soloNs0=","")=="True") if arg.startswith("piu_uno="): piu_uno=(arg.replace("piu_uno=","")=="True") if arg.startswith("test="): test=(arg.replace("test=","")=="True") print "Comando: carica(", fileDjvu,ini,fin,sovrascrivi,aggiustaParagrafi,test,soloNs0,piu_uno,")" carica(fileDjvu,ini,fin,sovrascrivi,aggiustaParagrafi,test,soloNs0,piu_uno) return if __name__=="__main__": main(sys.argv[1:])