User:Alex brollo/python/djvu.py
Appearance
#!/usr/bin/python
# -*- coding: utf-8 -*-
# introducing pyquery
import pywikibot as wikipedia
import pywikibot.data.api as api
import pickle,gzip, sys, os, re, json
from urllib import FancyURLopener
from scripts import *
#from pyquery import PyQuery
class MyOpener(FancyURLopener):
version = version = 'User-Agent: Alex (+http://it.wikisource.org/wiki/Utente:Alex_brollo)'
opener=MyOpener()
lista=type("")
stringa=type("")
s_unicode=type(u"")
tuple=type(())
commons=wikipedia.getSite("commons","commons")
caratteriVietatiNomeFile='\/?:*"><|'
dic={"word":" <span class='ocrx_word' id='word_%numero' title='bbox %coordinate'>%testo</span>\n",\
"line":" <span class='ocr_line' id='line_%numero' title='bbox %coordinate'>\n",\
"para":" <p class='ocr_par' dir='ltr' id='par_%numero' title='bbox %coordinate'>\n",\
"region":" <div class='ocr_carea' id='block_%numero_%numero' title='bbox %coordinate'>\n",\
"column":"",
"page":"<div class='ocr_page' id='page_1' title='image \'immagine.tif\'; bbox %coordinate; ppageno 0'>\n"}
'''
routines per la gestione dei file djvu
commonsGrab : dato il nome di un file djvu lo scarica da Commons nella cartella djvu
leggiPagDjvu: legge lo strato testo di una pagina djvu con djvutxt
pageObj : trasforma una pagina lisp-like in un oggetto python
hOCR : trasforma un oggetto python in un hOCR (xml)
hOCR1 : variante
id2title : ricava il titolo dall'id e inverso
'''
def id2title(id=None,title=None):
r=api.Request(site=commons,action="query",prop="info")
if id != None:
r["pageids"]=id
else:
r["titles"]=title
data=r.submit()
id=data["query"]["pages"].keys()[0]
if title==None:
title=data["query"]["pages"][id]["title"]
return {"id":id, "title":title}
pageOby()
def commonsGrab(nomefile="File:Georgiche.djvu"):
id=id2title(title=nomefile)["id"]
commons=wikipedia.getSite("commons","commons")
immagine=wikipedia.ImagePage(commons,nomefile)
url=immagine.fileUrl()
grab(url,"djvu/"+id+".djvu")
return id
# data una pagina djvu-lisp la trasforma in oggetto python (tuple annidata)
def pageObj(testo):
p=re.compile("(page|column|region|para|line|word)\s\d+\s\d+\s\d+\s\d+")
iteratore=p.finditer(testo)
for i in iteratore:
testo=testo.replace(i.group(),'"'+i.group()+'",',1)
testo=testo.split("\n")
for i in range(len(testo)):
testo[i]=testo[i].strip()
testo="\n".join(testo)
testo=testo.replace(")\n(","),(\n").replace("\n","")
oggetto=eval(testo)
return oggetto
# dato un oggetto python-pagina lo trasforma in hOCR
def hOCR(pagina):
vuota=False
testo=u""
nword=nline=npara=nregion=ncolumn=npage=1
lclose=[]
for i1 in range(len(pagina)): #livello pagina
if i1==0:
testo+=dic["page"].replace("%coordinate",pagina[0].split(" ",1)[1])
#print pagina[0],testo
lclose.insert(0,"</div>")
continue
for i2 in range(len(pagina[i1])): #livello colonna
if i2==0:
x=""
if pagina[i1][1]=="":
vuota=True
continue
if pagina[i1][1]!="":
for i3 in range(len(pagina[i1][i2])): #livello regione
if i3==0:
#print i1,i2
testo+=dic["region"].replace("%coordinate",pagina[i1][i2][0].split(" ",1)[1]).replace("%numero",str(nregion))
#print pagina[i1][i2][0],testo
nregion+=1
lclose.insert(0," </div>\n")
continue
for i4 in range(len(pagina[i1][i2][i3])): #livello paragrafo
if i4==0:
#print i1,i2,i3
testo+=dic["para"].replace("%coordinate",pagina[i1][i2][i3][0].split(" ",1)[1]).replace("%numero",str(npara))
#print pagina[i1][i2][i3][0],testo
npara+=1
lclose.insert(0," </p>\n")
continue
for i5 in range(len(pagina[i1][i2][i3][i4])): #livello linea
if i5==0:
#print i1,i2,i3,i4
testo+=dic["line"].replace("%coordinate",pagina[i1][i2][i3][i4][0].split(" ",1)[1]).replace("%numero",str(nline))
#print pagina[i1][i2][i3][i4][0],testo
nline+=1
lclose.insert(0," </span>\n")
continue
testo+=dic["word"].replace("%coordinate",pagina[i1][i2][i3][i4][i5][0].split(" ",1)[1])\
.replace("%numero",str(nword))\
.replace("%testo",pagina[i1][i2][i3][i4][i5][1])
nword+=1
testo+=lclose.pop(0) #chiusura linea
testo+=lclose.pop(0)
testo+=lclose.pop(0)
testo+=lclose.pop(0) #chiusura pagina
return testo
# riceve un elemento oggetto python lo trasforma in elemento hOCR
def hOCR1(oggetto):
if type(oggetto[1]) in (stringa,s_unicode):
tipo,coordinate=oggetto[0].split(" ",1)
oggetto=dic[tipo][0].replace("%testo",oggetto[1]).replace("%coordinate",coordinate)
return oggetto
#da un file djvu estrae un oggetto python a liste annidate di una pagina
def leggiPagDjvu(pagina,djvu="Opere matematiche (Cremona) III.djvu"):
command='djvused "#file" -e "select #pagina;print-txt" > out/out.txt'\
.replace("#file",djvu)\
.replace("#pagina",str(pagina))
print "Comando:",command
os.system(command)
testo=unicode(open("out/out.txt").read(),"utf-8")
oggetto=json.loads(json.dumps(pageObj(testo)))
return oggetto
# dato un oggetto python lista lo trasforma in un oggetto python tuple
def list2tuple(oggettoLista):
# ....
return oggettoTuple
#dato un oggetto python tuple lo trasforma in un djvu lisp utf-8
def tuple2djvu(oggettoTuple):
# ....
return djvuLisp
# lancia tesseract su una serie di pagine e ottiene hOCR modificato (solo html interno a body)
def tess(ini,fin,lang="ita",base="opere_2 - #pag.tif",hocr=True,inDir="tiff/",outDir="hOCR/"):
for i in range(ini,fin):
pagina=str(i).zfill(4)
pagIn='"'+inDir+base.replace("#pag",pagina)+'"'
pagOut=pagIn.replace(inDir,outDir).replace(".tif","")
command="tesseract #pagin -l #lang tessOut hocr"\
.replace("#lang",lang)\
.replace("#pagin",pagIn)
print command
os.system(command)
testo=open("tessOut.html").read()
header=find_stringa(testo,"<?xml","<body>\n",1)
footer=find_stringa(testo,"</body>","</html>",1)
if header!="":
testo=testo.replace(header,"")
if footer!="":
testo=testo.replace(footer,"")
pagOut=pagIn[1:-1].replace(inDir,outDir).replace(".tif",".html")
print pagOut
open(pagOut,"w").write(testo)
return
def djvuTxt(pagina, djvu="numi.djvu", base="Rivista italiana di numismatica 1892.djvu"):
nomePagina=wikipedia.Page("it","Pagina:"+base+"/"+str(pagina))
os.system("djvutxt -page=#pagina numi.djvu pagina.txt".replace("#pagina",str(pagina)))
testo=unicode(open("pagina.txt").read(),"utf-8")\
.replace(u"\x1f\x1d\x0b","\n").replace(u"\x0c","").replace(u"\x1f","\n")
#print testo
if not nomePagina.exists():
nomePagina.put(testo,comment="caricamento OCR via bot")
return #testo
def x():
trattino=u'\u2015'
return "―"
def apriXml(gz="ricordidilondrad00deamuoft_abbyy.gz"):
testo=gzip.open(gz,"r").read()
pagine=produci_lista(testo,"<page ","</page>",1)
return pagine
def scriviPagina(p): # pagina è un oggetto pyquery page
t=''
for i1 in range(len(p("block"))):
blocco=p("block").eq(i1)
if blocco.attr("blockType")=="Text":
for i2 in range(len(blocco("par"))):
par=blocco("par").eq(i2)
for i3 in range(len(par("line"))):
line=par("line").eq(i3)
t+=" ".join(analizzaLinea(line))+"\n"
t+="\n"
return t
def analizzaLinea(linea): # linea è oggetto pyquery; page è la main class
ln=[]
w=[]
caratteri=linea("charParams")
l=eval(linea(caratteri[0]).attr("l"))
t=eval(linea(caratteri[0]).attr("t"))
r=eval(linea(caratteri[0]).attr("r"))
b=eval(linea(caratteri[0]).attr("b"))
for i in range(len(caratteri)):
if i>0:
if linea(caratteri[i]).attr("wordStart")=="true":
ln.append([w,str(l)+" "+str(t)+" "+str(r)+" "+str(b)])
l=eval(linea(caratteri[i]).attr("l"))
t=eval(linea(caratteri[i]).attr("t"))
r=eval(linea(caratteri[i]).attr("r"))
b=eval(linea(caratteri[i]).attr("b"))
w=[]
w.append(caratteri[i])
t=min(eval(linea(caratteri[i]).attr("t")),t)
r=max(eval(linea(caratteri[i]).attr("r")),r)
b=max(eval(linea(caratteri[i]).attr("b")),b)
ln.append([w,str(l)+" "+str(t)+" "+str(r)+" "+str(b)])
parole=[]
parola=''
for i in ln:
for j in i[0]:
parola+=linea(j).text()
if linea(i[0][0]).attr("wordPenalty")!="0":
parola='<span style="color:red" data-xy="'+i[1]+'">'+parola+"</span>"
parole.append(parola)
parola=''
return parole
# opens a well-formed xml of a page adding original headet and documenta tag
# to <page> tag content to study xml structure
def xmlPage(base="ricordidilondrad00deamuoft_abbyy",n=1):
lp=carica_pcl(base,"")
xml=gzip.open(base+".gz","rb")
xml.seek(lp[n][0])
pagina=lp[0][0]+xml.read(lp[n][1])+lp[0][1]
open("pagina"+str(n)+".xml","w").write(pagina)
return
# all together.....
def pagineAbbyy(base="ricordidilondrad00deamuoft_abbyy", ws="Ricordi di Londra.djvu"):
testiPagine=f=gzip.open(base+".gz","rb")
l=carica_pcl(base,"")
listaTesti=[]
for pagine in range(1,len(l)):
f.seek(l[pagine][0])
testo=f.read(l[pagine][1])
testoWiki=testoBlocchi(parseText2(testo))
print pagine, len(testoWiki)
listaTesti.append(["Pagina:"+ws,pagine,testoWiki])
listaTesti=[""]+listaTesti
salva_pcl(listaTesti,"listaTestiAbbyy","")
return
def testAlign(c=10):
ldjvu=carica_pcl("listaTestiDjvu","")
labbyy=carica_pcl("listaTestiAbbyy","")
for a in range(1,len(ldjvu)):
for i in range(a,len(labbyy)):
if simil(ldjvu[a][1],labbyy[i][2])>40 and not len(ldjvu[a][1])<20:
#print a,i
ldjvu[a][2]=labbyy[i][2]
break
if ldjvu[a][2]=="":
ldjvu[a][2]=ldjvu[a][1]
salva_pcl(ldjvu,"listaTestiDjvu","")
return "Fatto"
def newcarica(baseWiki,ini,fin):
ldjvu=carica_pcl("listaTestiDjvu","")
if fin>len(ldjvu):
fin=len(djvu)
for pag in range(ini,fin):
pagina=wikipedia.Page("it",baseWiki+"/"+str(pag))
testoWiki=unicode(ldjvu[pag][2],"utf-8")
if pagina.exists():
noincludes=produci_lista(pagina.get(),"<noinclude>","</noinclude>",1)
header=noincludes[0]
footer=noincludes[len(noincludes)-1]
user=find_stringa(header,'user="','"',1)
header=header.replace(user,'user="Alebot"')
testoWiki=header+testoWiki+footer
pagina.put(testoWiki)
return
def pagineDjvu(fileDjvu="ricordidilondrad00deamuoft.djvu"):
comando='djvutxt -detail=page "#f"> djvutxt.txt'
os.system(comando.replace("#f",fileDjvu))
t=open("djvutxt.txt").read()
l=produci_lista(t,"(",")\n",1)
for i in range(len(l)):
l[i]=l[i].replace(find_stringa(l[i],"(page",'"',1),'')\
.replace(find_stringa(l[i],'"',"\n",1,side="right"),'')\
.replace("\\n","\n")\
.replace("\\037","\n")\
.replace("\\035","")\
.replace("\\013","")\
.replace(" \n","\n")
l[i]=[i+1,l[i],""]
l=['']+l
salva_pcl(l,"listaTestiDjvu","")
return # lista dei testi delle pagine in utf-8; caratteri speciali
# riconvertiti
def grab(url,output=None):
page=opener.open(url+"?action=render")
content=page.read()
if output!=None:
open(output,"wb").write(content)
return "Fatto"
else:
return content
def IAgrab(url="http://archive.org/details/LeGeorgicheDiVirgilioCommentateDaEttoreStampiniPartePrimaLibriIEIi"):
link=find_stringa(grab(url),"<b>All Files","</a>",1)
link=find_stringa(link, 'href="','"',0)
l=[]
for i in produci_lista(grab(link),'href="','"',0):
if i.endswith("abbyy.gz"):
print "Grabbing abbyy.gz..."
urlAbbyy=link+"/"+i
grab(urlAbbyy,i)
if i.endswith(".djvu"):
print "Grabbing djvu..."
urlDjvu=link+"/"+i
grab(urlDjvu,i)
base=urlAbbyy.replace(link+"/")
parsePages1(base)
return "Fatto"
# gets a html/xml tag code by tag name
def find_element(tag,text):
elc=find_stringa(text,"<"+tag,">",1)
element=find_stringa(text,elc,"</"+tag+">",1)
return element
# gets xml of a page
def parseText2(testoPagina):
# page=open(pagina).read()
parole=[]
blocchi=produci_lista(testoPagina,"<block","</block>",1)
for i0 in range(len(blocchi)):
blocchi[i0]=produci_lista(blocchi[i0],"<region","</text>",1)
for i1 in range(len(blocchi[i0])):
blocchi[i0][i1]=produci_lista(blocchi[i0][i1],"<par","</par>",1)
for i2 in range(len(blocchi[i0][i1])):
blocchi[i0][i1][i2]=produci_lista(blocchi[i0][i1][i2],"<line","</line>",1)
for i3 in range(len(blocchi[i0][i1][i2])):
blocchi[i0][i1][i2][i3]=produci_lista(blocchi[i0][i1][i2][i3],"<charParams","</charParams>",1)
# blocchi[i0][i1][i2][i3] è la lista di caratteri per ogni elemento blocco.paragrafo.linea
parole=[]
parola=[]
for car in blocchi[i0][i1][i2][i3]: #per ogni carattere:
if valPar("wordStart",car)=="true":
if parola!=[]:
parole.append(parola)
parola=[]
parola.append(car)
parole.append(parola)
blocchi[i0][i1][i2][i3]=parole
return blocchi
def valPar(par,testo):
par=find_stringa(testo,par+'="','"',0)
return par
def testoBlocchi(blocchi,apos=True):
t=""
for blocco in blocchi: # livello blocchi
for regione in blocco:
for paragrafo in regione: # livello paragrafi
for linea in paragrafo: #livello linea
for parola in linea: #livello carattere
tt=''
span=False
for carattere in parola:
tt+=find_stringa(carattere,">","<",0)
if valPar("wordPenalty",carattere)!="0":
span=True
spanText='<span style="color:red;">'
if span:
tt=spanText+tt+"</span>"
t+=tt
t+="\n"
t+="\n"
return t
# new parsing page algorithm
def parsePages1(f="georgiche-stampini_abbyy.gz"):
#l=[f] # list of offset/length of page code into xml file; l[0] empty by now
# to align l index to djvu page number
offset=0 # offset initialization
xml=gzip.open(f).read() # loading the whole fileinto a string variable
header=xml[0:xml.find("<page")]
footer="\n</document>"
l=[[header,footer]]
while True:
offset=xml.find("<page",offset)
if offset==-1:
break
endoffset=xml.find("</page>",offset)+7
l.append([offset,endoffset-offset])
print offset,endoffset-offset
offset=endoffset
# saving list of [offset, length] into offsets.pcl
# no more need to save pages xml into files
# to rietrieve code simply
# f=open(file_xml,"r+")
# f.seek(l[page_number][0])
# pagexml=f.read(l[page_number][1])
salva_pcl(l,f.replace(".gz",""),"")
return "Fatto"
# Nuova versione, gestisce i tag annidati; x e' la parte "aspecifica" del
# tag di apertura (es: {{ cercando {{Intestazione| )
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
def carica_pcl(nome_file, folder="dati/"):
nome_file=folder+nome_file+".pcl"
f=open(nome_file)
contenuto=pickle.load(f)
f.close()
return contenuto
def salva_pcl(variabile,nome_file="dato",folder="dati/"):
nome_file=folder+nome_file+".pcl"
f=open(nome_file,"w")
pickle.dump(variabile, f)
f.close()
print "Variabile salvata nel file "+nome_file
return
####
def caricaPagina(numero,baseGz="ricordidilondrad00deamuoft_abbyy"):
l=carica_pcl(baseGz,"")
f=gzip.open(baseGz+".gz", "rb")
f.seek(l[numero][0])
testo=f.read(l[numero][1])
p=PyQuery(testo)
return p
def caricaPagine(baseGz="ricordidilondrad00deamuoft_abbyy"):
l=carica_pcl(baseGz,"")
f=gzip.open(l[0], "rb")
lt=[""]
for i in l[1:]:
f.seek(i[0])
t=f.read(i[1])
blocchi=parseText2(t)
lt.append(testoBlocchi(blocchi))
return lt
def simil(a,b,c=10):
punti=0
if len(a)<=c or len(b)<=c:
return -1
for i in range(len(a)-c):
if a[i:i+c] in b:
punti+=1
somiglianza=punti*100/(len(a)-c)
return somiglianza