Ponieważ różni wydawcy używają różnych metod „oznaczania” plików PDF, musisz upewnić się, że porównujesz bez uwzględnienia oznaczeń.
Potrzebujesz także wydajnej metody porównania nowego pliku PDF ze wszystkimi już pobranymi plikami PDF, na wypadek, gdy wielokrotnie pobierasz ten sam plik PDF i jest on np. Oznaczony adresem IP i / lub datownikiem, jak sugerujesz. Nie chcesz używać czasochłonnego mechanizmu porównywania, który porównuje każdy nowy plik PDF z wieloma już pobranymi plikami PDF
Potrzebujesz narzędzia, które usuwa wszystkie możliwe oznaczenia i generuje skrót pozostałych danych. Musisz zachować mapę skrótów → nazwa pliku, która może znajdować się w prostym pliku, a jeśli obliczony skrót znajduje się już w pliku, masz duplikat (i usuń go lub zrób wszystko, co konieczne), a jeśli skrót nie jest jeszcze tam dodajesz skrót i nazwę pliku. Plik wyglądałby mniej więcej tak:
6fcb6969835d2db7742e81267437c432 /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9 /home/anthon/orders/your_order_20150320.pdf
Ten plik jest pomijalnie mały w porównaniu do oryginalnych plików PDF. Jeśli masz miliony plików PDF, możesz rozważyć przechowywanie tych danych w bazie danych. Ze względu na wydajność możesz w nim podać rozmiar pliku i liczbę stron ( pdfinfo | egrep -E '^Pages:' | grep -Eo '[0-9]*'
).
Powyższe popycha problem do usunięcia oznaczeń i wygenerowania skrótu. Jeśli wiesz, skąd pochodzi plik PDF podczas wywoływania procedury generowania skrótu (tj. Jeśli robisz pobieranie programowo), możesz dostosować generowanie skrótu na tej podstawie. Ale nawet bez tego istnieje kilka możliwości generowania skrótów:
- jeśli metadane tytułu i autora nie są puste i nie zawierają nieokreślonych ciągów, takich jak „Acrobat” lub „PDF”, można wygenerować skrót na podstawie informacji o autorze i tytule. Użyj,
pdfinfo -E file.pdf | grep -E '^(Author:)|(Title:) | md5sum
aby uzyskać skrót. Możesz również uwzględnić liczbę stron przy obliczaniu wartości skrótu (' Pages:
' w danych pdfinfo
wyjściowych).
- jeśli poprzednia reguła nie działa, a plik PDF zawiera obrazy, wyodrębnij obrazy i wygeneruj skrót dla połączonych danych obrazu. Jeśli obrazy zawierają tekst w stopce lub nagłówku, na przykład „Licencjonowane dla użytkownika Joe”, przed obliczeniem wartości skrótu usuń X linii z góry lub z dołu. Jeśli te oznaczenia znajdują się na dużym szarym tle z literami, to oczywiście nie zadziała, chyba że odfiltrujesz piksele, które nie są całkowicie czarne (do tego możesz użyć
imagemagick
). Możesz użyć pdfimages
do wyodrębnienia informacji o obrazie do pliku tymczasowego.
- jeśli poprzednie reguły nie działają (ponieważ nie ma obrazów), możesz użyć
pdftext
do wyodrębnienia tekstu, odfiltrowania oznaczenia (jeśli odfiltrujesz trochę za dużo, to nie jest problem), a następnie wygenerujesz skrót na podstawie że.
Dodatkowo możesz porównać, czy rozmiar starego pliku znalezionego za pomocą skrótu i sprawdzić, czy mieści się w określonych granicach nowego pliku. Kompresja i iffereferencje w ciągach znaków (IP / data-znacznik czasu) powinny skutkować różnicą mniejszą niż jeden procent.
Jeśli znasz metodę, którą wydawca stosuje przy określaniu wartości skrótu, możesz bezpośrednio zastosować „właściwą” powyższą metodę, ale nawet bez niej możesz sprawdzić metadane i zastosować heurystykę lub określić liczbę obrazów w pliku i porównaj to z liczbą stron (jeśli są blisko, prawdopodobnie masz dokument zawierający skany). pdftext
na zeskanowanym obrazie pliki PDF mają także rozpoznawalny wynik.
Jako podstawę do pracy stworzyłem pakiet Pythona, który jest na bitbucket i / lub może być zainstalowany z PyPI przy użyciu pip install ruamel.pdfdouble
. Zapewnia to pdfdbl
polecenie, które wykonuje skanowanie zgodnie z powyższym opisem w przypadku metadanych, wyodrębnionych obrazów lub tekstu.
Nie wykonuje jeszcze żadnego filtrowania oznaczeń (jeszcze) , ale readme opisuje, które (dwie) metody ulepszenia, aby to dodać.
Dołączony plik Readme:
ruamel.pdfdouble
ten pakiet zawiera pdfdbl
polecenie:
pdfdbl scan dir1 dir2
Spowoduje to przejście do katalogów podanych jako argument, a dla znalezionych plików PDF utwórz skrót na podstawie (w kolejności):
- metadane, jeśli są unikalne
- obrazy, jeśli liczba obrazów
- tekst
Zakłada się, że pdfinfo, pdfimages i pdftotext` z pakietu poppler-utils są dostępne.
Tworzona jest „baza danych”, na ~/.config/pdfdbl/pdf.lst
podstawie której testowane są kolejne skany.
Usuwanie oznaczeń
W ruamel/pdfdouble/pdfdouble.py
istnieją dwie metody, które mogą być ulepszone, aby odfiltrować znaki w formacie PDF, które czynią je mniej wyjątkowy i uczynić praktycznie te same pliki mają różne skrótów.
W przypadku tekstu PdfData.filter_for_marking
należy rozszerzyć metodę, aby usunąć i oznaczenia z łańcucha będącego jej argumentami i zwrócić wynik.
W przypadku skanowanych obrazów należy ulepszyć tę metodę PdfData.process_image_and_update
, np. Odcinając dolne i górne linie X obrazów oraz usuwając szary tekst tła, ustawiając wszystkie czarne piksele na białe. Ta funkcja musi zaktualizować skrót przekazany przy użyciu .update()
metody przekazującej przefiltrowane dane.
Ograniczenia
Obecna „baza danych” nie obsługuje ścieżek zawierających znaki nowej linii
To narzędzie jest obecnie tylko Python 2.7.
Ciągi znaków zgodne z IP można zastąpić re
modułem Pythona :
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'