Da verschiedene Verlage unterschiedliche Methoden zum "Markieren" der PDFs verwenden, müssen Sie sicherstellen, dass Sie sie vergleichen, ohne die Markierungen zu berücksichtigen.
Sie benötigen auch eine effiziente Methode, um ein neues PDF mit allen bereits heruntergeladenen PDFs zu vergleichen, falls Sie wiederholt dasselbe PDF herunterladen und es z. B. mit der IP und / oder dem Datums- / Zeitstempel gekennzeichnet ist, wie Sie vorschlagen. Sie möchten keinen zeitaufwändigen Vergleichsmechanismus verwenden, der jedes neue PDF mit vielen bereits heruntergeladenen PDFs vergleicht
Was Sie brauchen, ist ein Dienstprogramm, das jede der möglichen Markierungen entfernt und einen Hash der verbleibenden Daten generiert. Sie müssen eine Hash → Dateinamenzuordnung behalten, die sich in einer einfachen Datei befinden kann. Wenn sich bereits ein berechneter Hash in der Datei befindet, haben Sie ein Duplikat (und löschen es oder tun, was auch immer erforderlich ist) und wenn der Hash noch nicht vorhanden ist Dort fügen Sie den Hash und den Dateinamen hinzu. Die Datei würde ungefähr so aussehen:
6fcb6969835d2db7742e81267437c432 /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9 /home/anthon/orders/your_order_20150320.pdf
Diese Datei ist im Vergleich zu den Original-PDFs fahrlässig klein. Wenn Sie Millionen von PDFs haben, können Sie diese Daten in einer Datenbank speichern. Aus Effizienzgründen möchten Sie möglicherweise die Dateigröße und die Anzahl der Seiten dort einfügen ( pdfinfo | egrep -E '^Pages:' | grep -Eo '[0-9]*'
).
Das Obige führt dazu, dass die Markierungen entfernt und der Hash generiert werden. Wenn Sie wissen, woher das PDF stammt, wenn Sie die Hash-Generierungsroutine aufrufen (dh wenn Sie die Downloads programmgesteuert durchführen), können Sie die Hash-Generierung basierend darauf optimieren. Aber auch ohne das gibt es mehrere Möglichkeiten für die Hash-Generierung:
- Wenn die Metadaten für Titel und Autor nicht leer sind und keine unspezifischen Zeichenfolgen wie "Acrobat" oder "PDF" enthalten, können Sie den Hash nur anhand der Autoren- und Titelinformationen generieren. Verwenden Sie
pdfinfo -E file.pdf | grep -E '^(Author:)|(Title:) | md5sum
, um den Hash zu erhalten. Sie können auch die Anzahl der Seiten in die Berechnung des Hashs einbeziehen (' Pages:
' in der pdfinfo
Ausgabe).
- Wenn die vorherige Regel nicht funktioniert und die PDF-Datei Bilder enthält, extrahieren Sie die Bilder und generieren Sie einen Hash für die kombinierten Bilddaten. Wenn die Bilder jemals Text in der Fußzeile oder in der Kopfzeile enthalten, z. B. "Lizenziert für Joe-Benutzer", entfernen Sie eine X-Anzahl von Zeilen oben oder unten, bevor Sie den Hash berechnen. Wenn sich diese Markierungen in einem grau hinterlegten Text mit großen Buchstaben befinden, funktioniert dies natürlich nicht, es sei denn, Sie filtern Pixel heraus, die nicht vollständig schwarz sind (für die Sie sie verwenden könnten
imagemagick
). Sie können pdfimages
die Bildinformationen in eine temporäre Datei extrahieren.
- Wenn die vorherigen Regeln nicht funktionieren (da keine Bilder vorhanden sind), können Sie
pdftext
den Text extrahieren, die Markierung herausfiltern (wenn Sie ein wenig zu viel herausfiltern, ist dies kein Problem) und dann den Hash basierend auf generieren Das.
Außerdem können Sie vergleichen, ob die Dateigröße der alten Datei, die über den Hash gefunden wurde, mit der neuen Datei innerhalb bestimmter Grenzen liegt. Komprimierung und ifferences in Zeichenfolgen (IP / Datums- / Zeitstempel) sollten nur zu einem Unterschied von weniger als einem Prozent führen.
Wenn Sie die Methode kennen, die der Herausgeber bei der Ermittlung des Hashs verwendet, können Sie die oben beschriebene "richtige" Methode direkt anwenden. Auch ohne diese Methode können Sie nach Metadaten suchen und einige Heuristiken anwenden oder die Anzahl der Bilder in einer Datei bestimmen und vergleichen Sie das mit der Anzahl der Seiten (wenn sie geschlossen sind, haben Sie wahrscheinlich ein Dokument, das aus Scans besteht). pdftext
Bei gescannten Bildern haben PDFs auch eine erkennbare Ausgabe.
Als Grundlage für die Arbeit habe ich ein Python-Paket erstellt, das sich auf Bitbucket befindet und / oder mit PyPI installiert werden kann pip install ruamel.pdfdouble
. Auf diese Weise erhalten Sie den pdfdbl
Befehl, der das Scannen wie oben beschrieben für Metadaten, extrahierte Bilder oder Text ausführt.
Es führt keine Filterung von Markierungen (noch) nicht , aber die readme beschrieben , die (zwei) Methoden zu verbessern , das zu tun hinzuzufügen.
Die mitgelieferte Readme:
ruamel.pdfdouble
Dieses Paket enthält den folgenden pdfdbl
Befehl:
pdfdbl scan dir1 dir2
Dadurch werden die als Argument angegebenen Verzeichnisse durchsucht und für die gefundenen PDF-Dateien ein Hash erstellt, der auf (in der Reihenfolge) basiert:
- Metadaten, falls eindeutig
- Bilder, wenn die Anzahl der Bilder
- Text
Dies setzt voraus, dass pdfinfo, pdfimages und pdftotext` aus dem poppler-utils-Paket verfügbar sind.
Es wird eine "Datenbank" aufgebaut, in ~/.config/pdfdbl/pdf.lst
der weitere Scans getestet werden.
Markierungen entfernen
Es ruamel/pdfdouble/pdfdouble.py
gibt zwei Methoden, die verbessert werden können, um Markierungen in der PDF-Datei herauszufiltern, die sie weniger eindeutig machen und praktisch dieselben Dateien mit unterschiedlichen Hashes erstellen.
Für Text sollte die Methode PdfData.filter_for_marking
erweitert werden, um Markierungen aus der Zeichenfolge, die ihre Argumente sind, zu entfernen und das Ergebnis zurückzugeben.
Bei gescannten Bildern muss die Methode PdfData.process_image_and_update
verbessert werden, z. B. indem die unteren und oberen X-Linien der Bilder abgeschnitten werden und grauer Hintergrundtext entfernt wird, indem alle schwarzen Pixel auf Weiß gesetzt werden. Diese Funktion muss den übergebenen Hash mithilfe der .update()
in den gefilterten Daten übergebenen Methode aktualisieren .
Beschränkungen
Die aktuelle "Datenbank" kann keine Pfade verarbeiten, die Zeilenumbrüche enthalten
Dieses Dienstprogramm ist derzeit nur Python 2.7.
IP-konforme Stringparts können durch das Python- re
Modul ersetzt werden:
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'