Étant donné que différents éditeurs utilisent différentes méthodes de «marquage» des fichiers PDF, vous devez vous assurer de les comparer sans prendre en compte les marquages.
Vous avez également besoin d'une méthode efficace pour comparer un nouveau PDF à tous les PDF déjà téléchargés au cas où vous téléchargez à plusieurs reprises le même PDF et qu'il est par exemple marqué de l'IP et / ou de l'horodatage comme vous le suggérez. Vous ne voulez pas utiliser un mécanisme de comparaison chronophage qui compare chaque nouveau PDF avec de nombreux PDF déjà téléchargés
Vous avez besoin d'un utilitaire qui supprime chacun des marquages possibles et génère un hachage des données restantes. Vous devrez conserver une table de hachage → nom de fichier, qui peut être dans un fichier simple, et si un hachage calculé est déjà dans le fichier, vous en avez un doublon (et supprimez-le ou faites tout ce qui est nécessaire) et si le hachage n'est pas encore là, vous ajoutez le hachage et le nom du fichier. Le fichier ressemblerait à quelque chose comme:
6fcb6969835d2db7742e81267437c432 /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9 /home/anthon/orders/your_order_20150320.pdf
Ce fichier est négligemment petit par rapport aux PDF d'origine. Si vous avez des millions de PDF, vous pouvez envisager de stocker ces données dans une base de données. Pour des raisons d'efficacité, vous souhaiterez peut-être inclure la taille du fichier et le nombre de pages ( pdfinfo | egrep -E '^Pages:' | grep -Eo '[0-9]*'
).
Ce qui précède pousse le problème à supprimer les marquages et à générer le hachage. Si vous savez d'où vient le PDF lors de l'appel de la routine de génération de hachage (c'est-à-dire si vous effectuez les téléchargements par programme), vous pouvez affiner la génération de hachage en fonction de cela. Mais même sans cela, il existe plusieurs possibilités pour la génération de hachage:
- si les métadonnées pour le titre et l'auteur ne sont pas vides et n'incluent pas de chaînes non spécifiques comme "Acrobat" ou "PDF", vous pouvez générer le hachage en fonction uniquement des informations sur l'auteur et le titre. Utilisez
pdfinfo -E file.pdf | grep -E '^(Author:)|(Title:) | md5sum
pour obtenir le hachage. Vous pouvez également inclure le nombre de pages dans le calcul du hachage (' Pages:
' dans la pdfinfo
sortie).
- si la règle précédente ne fonctionne pas et que le PDF contient des images, extrayez les images et générez un hachage sur les données d'image combinées. Si les images contiennent du texte dans le pied de page ou l'en-tête comme "Licensed to Joe User", supprimez un nombre X de lignes en haut ou en bas, avant de calculer le hachage. Si ces marquages sont dans un gros texte d'arrière-plan grisé, cela ne fonctionnera bien sûr pas, sauf si vous filtrez les pixels qui ne sont pas totalement noirs (pour cela, vous pouvez les utiliser
imagemagick
). Vous pouvez utiliser pdfimages
pour extraire les informations d'image dans un fichier temporaire.
- si les règles précédentes ne fonctionnent pas (car il n'y a pas d'images), vous pouvez utiliser
pdftext
pour extraire le texte, filtrer le marquage (si vous filtrez un peu trop, ce n'est pas un problème), puis générer le hachage en fonction de cette.
De plus, vous pouvez comparer si la taille du fichier de l'ancien fichier trouvé via le hachage et voir si se trouve dans certaines marges avec le nouveau fichier. La compression et les différences dans les chaînes (IP / horodatage) ne devraient entraîner qu'une différence de moins d'un pour cent.
Si vous connaissez la méthode que l'éditeur utilise pour déterminer le hachage, vous pouvez directement appliquer la "bonne" méthode de ce qui précède, mais même sans cela, vous pouvez vérifier les métadonnées et appliquer des heuristiques, ou déterminer le nombre d'images dans un fichier et comparez cela avec le nombre de pages (si elles sont proches, vous avez probablement un document composé de numérisations). pdftext
sur les images numérisées, les PDF ont également une sortie reconnaissable.
Comme base de travail, j'ai créé un package python qui est sur bitbucket et / ou peut être installé à partir de PyPI en utilisant pip install ruamel.pdfdouble
. Cela vous fournit la pdfdbl
commande qui effectue la numérisation comme décrit ci-dessus sur les métadonnées, les images extraites ou le texte.
Il ne filtre pas (encore) les marquages , mais le fichier Lisez-moi décrit les (deux) méthodes à améliorer pour l'ajouter.
Le fichier Lisezmoi inclus:
ruamel.pdfdouble
ce package fournit la pdfdbl
commande:
pdfdbl scan dir1 dir2
Cela parcourra les répertoires fournis en argument et pour les fichiers PDF trouvés, créez un hachage basé sur (dans l'ordre):
- métadonnées si uniques
- images si le nombre d'images
- texte
Cela suppose que pdfinfo, pdfimages et pdftotext` du paquet poppler-utils sont disponibles.
Une "base de données" est en train de se constituer, par ~/.config/pdfdbl/pdf.lst
rapport à laquelle d'autres analyses sont testées.
Suppression des marquages
Il ruamel/pdfdouble/pdfdouble.py
existe deux méthodes qui peuvent être améliorées pour filtrer les marquages dans le PDF qui les rendent moins uniques et font pratiquement les mêmes fichiers pour avoir des hachages différents.
Pour le texte, la méthode PdfData.filter_for_marking
doit être étendue pour supprimer et marquer de la chaîne qui est ses arguments et retourner le résultat.
Pour les images numérisées, la méthode PdfData.process_image_and_update
doit être améliorée, par exemple en coupant les lignes X inférieures et supérieures des images, et en supprimant tout texte d'arrière-plan gris en définissant tous les pixels noirs sur blanc. Cette fonction doit mettre à jour le hachage transmis à l'aide de la .update()
méthode transmettant les données filtrées.
Restrictions
La "base de données" actuelle ne peut pas gérer les chemins d'accès qui contiennent des retours à la ligne
Cet utilitaire est actuellement Python 2.7 uniquement.
Les parties de chaîne conformes à IP peuvent être remplacées par le re
module 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'