Discussioni progetto:Bot/Programmi in Python per i bot/ms.py
Doc
modifica@Paperoastro Ecco qua il primo vagito. Occhio, è una ciofeca per uso personale, interattivo sotto Idle.
La routine fondamentale è do_match() che riceve una lista delle pagine OCR, il testo completo target (in cui vanno aggiunti i codici match ==[[Pagina:...]]==, la pagina da cui iniziare il match, e altri parametri secondari con valori di default.
La routine iniziale è go(fileTargetName, djvuName, startPageNumber, verbose=True, fileOutputName="output.txt", oldText=False):
- fileTargetName: nome del file target
- djvuName: nome del file djvu o pdf
- startPageNumber: prima pagina da cui partire con il match
- verbose=True: esegue output di debug; mettere False
- fileOutputName="output.txt": file output (target con codici Match)
- oldText=False: mettere True nei testi antichi (al momento facilita il match convertendo, in una copia di lavoro del testo target, le s in f; parte molto interessante da sviluppare)
Al momento, le cose sono sistemate in modo che nella cartella dove corre lo script ci sia anche parseTemplate.py, che ci sia una copia del file djvu o pdf con strato testo OCR, un file txt target da matchare. Inoltre devono essere raggiungibili e funzionanti gli script djvutxt (di djvuLibre) e pdftotext (di xpdf). --Alex brollo (disc.) 11:11, 8 giu 2021 (CEST)
- Ciao @Alex brollo, Visto tutto! Grazie per il M&S del testo di Torricelli. Geniale l'opzione oldText! Se trovo altri testi in cui manca il testo a fronte, lo collaudo certamente! --Paperoastro (disc.) 11:32, 8 giu 2021 (CEST)
- @Paperoastro oldText è stato una specie di illuminazione: riguardando gli anfratti (tremendi, per me!) di do_match, improvvisamente mi sono reso conto di quando era semplice risolvere. Già mi stavo mettendo nei pasticci, con strategie molto complicate e incerte... Sei già stato capace di capire a fondo cosa combina do_match()? Se sì, provo enorme invidia: io ci ho messo settimane... :-( Alex brollo (disc.) 15:05, 8 giu 2021 (CEST)
- funzioni parseTemplate integrate nello script. Alex brollo (disc.) 15:17, 8 giu 2021 (CEST)
- Capire a fondo è una parola grossa ;-) Ho intuito il meccanismo, ma dovrei studiarlo a fondo. In passato ho avuto a che fare con programmi molto intricati in php, ma li ci lavoravo a tempo pieno. Appena ho un po' di tempo ci metto le mani, ma ho il concorso insegnanti che incombe... --Paperoastro (disc.) 15:44, 8 giu 2021 (CEST)
- @Paperoastro Poichè è inutile (anche se interessante e formativo) riscoprire l'acqua calda, cerco di iniziare la doc, partendo dal cuore dell'algoritmo. Il tutorial per l'uso pratico lo lascio per ultimo: temo che prima lo script sarà molto modificato e il tutorial rischia di dover essere riscritto daccapo (vedi il solo inserimento delle routine parseTemplate che hanno modificato le indicazioni iniziali!). Alex brollo (disc.) 09:26, 9 giu 2021 (CEST)
- Capire a fondo è una parola grossa ;-) Ho intuito il meccanismo, ma dovrei studiarlo a fondo. In passato ho avuto a che fare con programmi molto intricati in php, ma li ci lavoravo a tempo pieno. Appena ho un po' di tempo ci metto le mani, ma ho il concorso insegnanti che incombe... --Paperoastro (disc.) 15:44, 8 giu 2021 (CEST)
- funzioni parseTemplate integrate nello script. Alex brollo (disc.) 15:17, 8 giu 2021 (CEST)
- @Paperoastro oldText è stato una specie di illuminazione: riguardando gli anfratti (tremendi, per me!) di do_match, improvvisamente mi sono reso conto di quando era semplice risolvere. Già mi stavo mettendo nei pasticci, con strategie molto complicate e incerte... Sei già stato capace di capire a fondo cosa combina do_match()? Se sì, provo enorme invidia: io ci ho messo settimane... :-( Alex brollo (disc.) 15:05, 8 giu 2021 (CEST)
Il cuore dell'algoritmo e le sue implicazioni
modificaIl cuore dell'algoritmo è costituito da alcune regex che trasformano sia l'OCR, che il testo di cui eseguire il match, in due liste:
p = re.compile(r'[\W]+', re.U) # lista sequenze caratteri
fp = re.compile(r'([\W]+)', re.U) # lista sequenze caratteri e non caratteri
ftext1 = fp.split(text1) # nelle due pagine djvu
ftext2 = fp.split(text2) # nel testo target modificato
ftext3 = fp.split(text3) # nel testo target nel testo originale
page1 = p.split(page1) #lista parole in pagina corrente
text1 = p.split(text1) #lista parole in pagina corrente + successiva
text2 = p.split(text2) #lista parole blocco testo
La regex p individua i blocchi di "non caratteri" consecutivi (spazi, a capo, punteggiatura...) interpretati come "separatori di parole"; la regex fp è identica, ma salva i blocchi individuati.
Le successive istruzioni regex split, applicate ai testi, producono due liste diverse.
Lo split con la regex p produce la sola lista delle "parole", ossia dei blocchi di caratteri, separatori esclusi. Il match si basa sull'analisi di queste liste di parole.
Lo split con la regex fp produce invece la lista, regolarmente alternata, delle "parole" e dei "blocchi di separatori". La lista non viene utilizzata per il match, ma per la ricostruzione finale del testo. Ha due proprietà interessanti:
- il semplice accodamento di tutti gli elementi con "".join(lista) restituisce esattamente il testo di partenza;
- esiste una relazione costante con la lista delle parole, vista la regolare alternanza di parole e di separatori.
I passi successivi comportano l'uso della libreria difflib, che opera sulle liste delle parole.
(continua)