Poiché diversi editori utilizzano metodi diversi per "contrassegnare" i PDF, è necessario assicurarsi di effettuare un confronto senza tenere conto dei contrassegni.
È inoltre necessario un metodo efficace per confrontare un nuovo PDF con tutti i PDF già scaricati nel caso in cui si scarichi ripetutamente lo stesso PDF ed è ad esempio contrassegnato con l'IP e / o la data e l'ora come si suggerisce. Non vuoi usare un meccanismo di confronto che richiede tempo che confronta ogni nuovo PDF con molti PDF già scaricati
Ciò di cui hai bisogno è un'utilità che elimini ciascuno dei possibili contrassegni e generi un hash dei dati rimanenti. Dovrai mantenere un hash → mappa del nome del file, che può essere in un semplice file, e se un hash calcolato è già nel file hai un duplicato (ed eliminalo o fai tutto il necessario) e se l'hash non è ancora lì, aggiungi l'hash e il nome del file. Il file sarebbe simile a:
6fcb6969835d2db7742e81267437c432 /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9 /home/anthon/orders/your_order_20150320.pdf
Quel file è negligentemente piccolo rispetto ai PDF originali. Se hai milioni di PDF potresti prendere in considerazione la possibilità di archiviare questi dati in un database. Per motivi di efficienza, potresti voler includere la dimensione del file e il numero di pagine ( pdfinfo | egrep -E '^Pages:' | grep -Eo '[0-9]*'
).
Quanto sopra spinge il problema a rimuovere i segni e generare l'hash. Se sai da dove proviene il PDF quando invochi la routine di generazione dell'hash (ovvero se esegui i download a livello di codice), puoi ottimizzare la generazione dell'hash in base a quello. Ma anche senza questo ci sono diverse possibilità per la generazione di hash:
- se i metadati per titolo e autore non sono vuoti e non includono stringhe non specifiche come "Acrobat" o "PDF", è possibile generare l'hash in base solo alle informazioni sull'autore e sul titolo. Usa
pdfinfo -E file.pdf | grep -E '^(Author:)|(Title:) | md5sum
per ottenere l'hash. Puoi anche calcolare il numero di pagine nel calcolo dell'hash (' Pages:
' pdfinfo
nell'output).
- se la regola precedente non funziona e il PDF contiene immagini, estrarre le immagini e generare un hash sui dati di immagine combinati. Se le immagini contengono mai testo nel piè di pagina o nell'intestazione come "Concesso in licenza a Joe User", rimuovere un numero X di righe dalla parte superiore o inferiore, prima di calcolare l'hash. Se quei segni sono in un testo di sfondo grigio con lettere grandi, questo ovviamente non funzionerà, a meno che tu non filtri i pixel che non sono totalmente neri (per questo potresti usare
imagemagick
). È possibile utilizzare pdfimages
per estrarre le informazioni sull'immagine in un file temporaneo.
- se le regole precedenti non funzionano (perché non ci sono immagini) è possibile utilizzare
pdftext
per estrarre il testo, filtrare il segno (se si filtra un po 'troppo, non è un problema) e quindi generare l'hash in base a quello.
Inoltre, puoi confrontare se la dimensione del file precedente è stata trovata tramite l'hash e vedere se rientra in determinati margini con il nuovo file. Compressione e ifferenze nelle stringhe (IP / data-ora-timbro) dovrebbero comportare solo una differenza inferiore all'uno percento.
Se conosci il metodo utilizzato dall'editore per determinare l'hash, puoi applicare direttamente il metodo "giusto" di cui sopra, ma anche senza di ciò puoi controllare i metadati e applicare alcune euristiche o determinare il numero di immagini in un file e confrontalo con il numero di pagine (se sono vicine probabilmente hai un documento composto da scansioni). pdftext
sui PDF di immagini scansionate ha anche un output riconoscibile.
Come base per lavorare da ho creato un pacchetto python che è su bitbucket e / o che può essere installato da PyPI usando pip install ruamel.pdfdouble
. Ciò fornisce il pdfdbl
comando che esegue la scansione come descritto sopra su metadati, immagini estratte o testo.
Non esegue alcun filtraggio dei contrassegni (ancora) , ma il readme descrive quali (due) metodi per migliorare per aggiungerlo.
Il readme incluso:
ruamel.pdfdouble
questo pacchetto fornisce il pdfdbl
comando:
pdfdbl scan dir1 dir2
In questo modo verranno visualizzate le directory fornite come argomento e, per i file PDF trovati, verrà creato un hash basato su (in ordine):
- metadati se unici
- immagini se il numero di immagini
- testo
Ciò presuppone che pdfinfo, pdfimages e pdftotext` dal pacchetto poppler-utils siano disponibili.
Viene creato un "database" in ~/.config/pdfdbl/pdf.lst
base al quale vengono testate ulteriori scansioni.
Rimozione dei segni
Nel ruamel/pdfdouble/pdfdouble.py
ci sono due metodi che possono essere migliorato per filtrare le marcature nel PDF che li rendono meno unici e rendere praticamente gli stessi file per avere diverse hash.
Per il testo, il metodo PdfData.filter_for_marking
deve essere esteso per rimuovere e contrassegnare dalla stringa che è i suoi argomenti e restituire il risultato.
Per le immagini scansionate il metodo PdfData.process_image_and_update
deve essere migliorato, ad esempio tagliando le linee X in basso e in alto e rimuovendo qualsiasi testo di sfondo grigio impostando tutti i pixel neri su bianco. Questa funzione deve aggiornare l'hash passato usando il .update()
metodo che passa nei dati filtrati.
restrizioni
L'attuale "database" non è in grado di gestire percorsi che contengono newline
Questa utility è attualmente solo Python 2.7.
Le stringhe conformi IP possono essere sostituite con il re
modulo Python :
import re
IPre = re.compile("(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}"
"([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])")
x = IPre.sub(' ', 'abcd 132.234.0.2 ghi')
assert x == 'abcd ghi'