Dado que diferentes editores usan diferentes métodos para "marcar" los archivos PDF, debe asegurarse de comparar sin tener en cuenta las marcas.
También necesita un método eficiente para comparar un nuevo PDF con todos los PDF ya descargados en caso de que descargue repetidamente el mismo PDF y, por ejemplo, esté marcado con la IP y / o la marca de fecha y hora que sugiere. No desea utilizar un mecanismo de comparación que consume mucho tiempo que compara cada nuevo PDF con muchos PDF ya descargados
Lo que necesita es una utilidad que elimine cada una de las posibles marcas y genere un hash de los datos restantes. Deberá mantener un mapa de nombre de archivo hash →, que puede estar en un archivo simple, y si un hash calculado ya está en el archivo, tiene un duplicado (y eliminarlo o hacer lo que sea necesario) y si el hash aún no está allí, agrega el hash y el nombre del archivo. El archivo se vería así:
6fcb6969835d2db7742e81267437c432 /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9 /home/anthon/orders/your_order_20150320.pdf
Ese archivo es negligentemente pequeño en comparación con los PDF originales. Si tiene millones de archivos PDF, puede considerar almacenar estos datos en una base de datos. Por razones de eficiencia, es posible que desee incluir el tamaño del archivo y el número de páginas allí ( pdfinfo | egrep -E '^Pages:' | grep -Eo '[0-9]*'
).
Lo anterior empuja el problema a eliminar las marcas y generar el hash. Si sabe de dónde proviene el PDF al invocar la rutina de generación de hash (es decir, si realiza las descargas mediante programación), puede ajustar la generación de hash en función de eso. Pero incluso sin eso, hay varias posibilidades para la generación de hash:
- si los metadatos para el título y el autor no están vacíos y no incluyen cadenas no específicas como "Acrobat" o "PDF", podría generar el hash basado solo en la información del autor y el título. Use
pdfinfo -E file.pdf | grep -E '^(Author:)|(Title:) | md5sum
para obtener el hash. También puede incluir el número de páginas al calcular el hash (' Pages:
' en la pdfinfo
salida).
- Si la regla anterior no funciona y el PDF contiene imágenes, extraiga las imágenes y genere un hash en los datos de imagen combinados. Si las imágenes alguna vez contienen texto en el pie de página o en el encabezado, como "Con licencia para el usuario Joe", elimine una X cantidad de líneas en la parte superior o inferior, antes de calcular el hash. Si esas marcas están en un gran texto de fondo gris con letras, esto, por supuesto, no funcionará, a menos que filtre los píxeles que no son totalmente negros (para eso podría usar
imagemagick
). Puede usar pdfimages
para extraer la información de la imagen en un archivo temporal.
- si las reglas anteriores no funcionan (porque no hay imágenes) puede usar
pdftext
para extraer el texto, filtrar la marca (si filtra un poco demasiado, eso no es un problema) y luego generar el hash basado en ese.
Además, puede comparar si el tamaño del archivo antiguo encontrado a través del hash y ver si está dentro de ciertos márgenes con el nuevo archivo. La compresión y las ifferencias en cadenas (IP / fecha-hora-sello) solo deberían dar como resultado una diferencia de menos del uno por ciento.
Si conoce el método que utiliza el editor para determinar el hash, puede aplicar directamente el método "correcto" de lo anterior, pero incluso sin eso puede verificar los metadatos y aplicar algunas heurísticas, o determinar la cantidad de imágenes en un archivo y compare eso con el número de páginas (si están cerca, probablemente tenga un documento que consta de escaneos). pdftext
en PDF escaneados de imágenes también tiene una salida reconocible.
Como base para trabajar, creé un paquete de Python que está en bitbucket y / o puede instalarse desde PyPI usando pip install ruamel.pdfdouble
. Esto le proporciona el pdfdbl
comando que realiza el escaneo como se describió anteriormente en metadatos, imágenes extraídas o en texto.
Todavía no filtra las marcas (todavía) , pero el archivo Léame describe qué (dos) métodos mejorar para agregar eso.
El archivo Léame incluido:
ruamel.pdfdouble
Este paquete proporciona el pdfdbl
comando:
pdfdbl scan dir1 dir2
Esto recorrerá los directorios proporcionados como argumento y para los archivos PDF encontrados, cree un hash basado en (en orden):
- metadatos si son únicos
- imágenes si el número de imágenes
- texto
Esto supone que pdfinfo, pdfimages y pdftotext` del paquete poppler-utils están disponibles.
Se crea una "base de datos" en la ~/.config/pdfdbl/pdf.lst
que se prueban más exploraciones.
Eliminar marcas
En ruamel/pdfdouble/pdfdouble.py
hay dos métodos que pueden ser mejoradas para filtrar las marcas en el PDF que los hacen menos único y hacer prácticamente los mismos archivos que tienen diferentes valores hash.
Para el texto, el método PdfData.filter_for_marking
debe extenderse para eliminar y marcar de la cadena que son sus argumentos y devolver el resultado.
Para las imágenes escaneadas, el método PdfData.process_image_and_update
debe mejorarse, por ejemplo, cortando las líneas X inferiores y superiores de las imágenes, y eliminando cualquier texto de fondo gris configurando todos los píxeles negros a blancos. Esta función necesita actualizar el hash pasado usando el .update()
método que pasa los datos filtrados.
Restricciones
La "base de datos" actual no puede manejar rutas que contienen nuevas líneas
Esta utilidad es actualmente solo Python 2.7.
Las partes de cadena conformes a IP se pueden sustituir con el re
módulo de 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'