Progetto:Bot/Programmi in Python per i bot/uploader7.py
Aspetto
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:])