Найдите дублирующиеся файлы PDF содержанием

Если это действительно должно обратиться к рандомизации (ASLR имеет отношение, где программа загружается, посмотрите здесь: http://en.wikipedia.org/wiki/Address_space_layout_randomization), затем можно отключить его путем передачи norandmaps к ядру в параметрах загрузки (см. здесь: http://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/re30.html).

9
22.03.2015, 16:08
8 ответов

Вы смотрели Content PDF Content ? Есть варианты командной строки , которые должны позволить вам автоматизировать процесс.

Вы можете запустить какую-то логику в разных журналах, она создает, чтобы увидеть, насколько они похожи.

Не удалось попробовать разделить PDF в несколько файлов временно и сравнивать их таким образом. Вы, вероятно, все равно все равно будете дублироваться таким образом. Один PDF может просто иметь дополнительную пустую страницу или что-то, что приведет к сравнению со всеми последующими страницами, что является совершенно другим.

1
27.01.2020, 20:07

Я бы дал pdftotext другой шанс, по крайней мере, для PDF в вашей коллекции, который на самом деле имеет текст (в противном случае вам нужно будет запустить OCR), используя лучший Инструмент для обработки вывода.

После того, как вы получите свой (грязный) текстовый вывод, запустите его через программу, предназначенную для определения сходства (а не различий , которые можно было бы быстрому пути к безумия) Отказ

Рассмотрим что-то вроде строки Perl :: Сходство или Simhash Simhash Simhash (которая доступна на Debian, но не Fedora / Rheel).

2
27.01.2020, 20:07

После скромного вклада в обсуждение (частичный ответ):

после преобразования в текст я бы использовал следующее для расчета (Слово на основе слов) файл Smilerity:

wdiff -s -123 file1.txt file2.txt |    ## word difference statistics (1)
     grep -Po '(\d+)(?=% common)' |    ## 
     awk '{a+=$1}END{print a/2}'       ## (2)

(1) создает результат, такой как

file1.txt: 36 words  33 92% common  3 8% deleted  0 0% changed
file2.txt: 35 words  33 94% common  2 6% inserted  0 0% changed

(2) = 93

1
27.01.2020, 20:07

PDF-файлы содержат метаданные, и я только что проверил ряд работ по физике от разных издателей, и все они имеют, по крайней мере, атрибут "Title". Для некоторых, заголовок - это фактическое название публикации, для некоторых он содержит DOI или подобные идентификаторы. В любом случае, каждая работа, которую я проверял, содержит заголовок, и это всегда что-то уникальное для данной публикации.

Вы можете использовать pdftk для доступа к метаданным PDF-файлов и их сравнения. Для вашей цели этого должно быть определенно достаточно и намного быстрее, чем pdftotext, если проблема с производительностью. В случае, если статья действительно не должна содержать метаданные заголовков, вы все равно можете вернуться к pdftotext.

Для сброса всех метаданных в текстовый файл (или stdout) для дальнейшей обработки используйте

pdftk <PDF> dump_data output <TEXTFILE>

или обратитесь к руководству за дополнительными опциями.

Если вы хотите попробовать ImageMagick's сравнивать , но при этом возникают проблемы с несколькими страницами, вы также можете использовать pdftk для извлечения отдельных страниц и сравнения их всех по отдельности (может быть, достаточно просто сравнить одну из них).

Вот фрагмент кода, который использует этот подход для создания diff-подобного PDF-выхода для многостраничных PDF-файлов: https://gist.github.com/mpg/3894692

2
27.01.2020, 20:07

Поскольку разные издатели используют разные методы «маркировки» PDF, вам необходимо убедиться, что вы сравниваете, не принимая учетную запись.

Вам также нужен эффективный метод для сравнения нового PDF для всех уже загруженных PDF в случае, если вы многократно загружаете один и тот же PDF, и это E.g. Отмечены IP и / или дату-временной маркой, поскольку вы предлагаете. Вы не хотите использовать механизм сравнения от времени, который сравнивает каждый новый PDF со многими уже загруженными PDF

, что вам нужно, это утилита, которая покладирует каждую из возможных маркировков и генерирует хест оставшихся данных. Вам нужно будет сохранить хеш → Карта имени файла, которая может быть в простом файле, и если вычисляемый хэш уже находится в файле, у вас есть дубликат (и удалить его или делать все необходимое), а если хеш еще не Там вы добавляете хеш и имя файла. Файл будет выглядеть что-то вроде:

6fcb6969835d2db7742e81267437c432  /home/anthon/Downloads/explanation.pdf
fa24fed8ca824976673a51803934d6b9  /home/anthon/orders/your_order_20150320.pdf

Этот файл небрежно мал по сравнению с исходными PDF. Если у вас миллионы PDFS, вы можете подумать о сохранении этих данных в базе данных. Для эффективности ради эффективности вы можете включить файловые файлы и количество страниц там ( pdfinfo | egreep -e '^ страницы:' | grep -eo '[0-9] *' ).


Вышеуказанное толкает проблему, чтобы удалить маркировки и генерируя хеш. Если вы знаете, откуда приходит PDF при вызове хеш-генерации рутины (I.e. Если вы выполняете загрузок программно), вы можете точно настроить генерацию HASH на основе этого. Но даже без того, что существует несколько возможностей для генерации HASH:

  1. , если метаданные для заголовка и автора не пустыются и не включают неспецифические строки, такие как «Acrobat» или «PDF», вы могли бы создать хеш на основе просто Автор и информация о названии. Использование pdfinfo -e file.pdf | grep -e '^ (автор :) | (название :) | md5sum , чтобы получить хеш. Вы можете включить количество страниц в расчете HASH (' страниц: ' в pdfinfo вывод).
  2. Если предыдущее правило не работает, и PDF содержит изображения, извлечь изображения и генерируют хеш на комбинированных данных изображения. Если изображения когда-либо содержат текст в нижнем колонтитуле или заголовок, как «Licensed To Joe User», полосу ногой x строки образуют верх или снизу, перед вычислением хеша. Если эта маркировка находится в некоторых больших буквах серых фоном текста, это будет, конечно, не работать, если вы не отфильтровали пиксели, которые не полностью черные (для того, чтобы вы могли использовать ImageMagick ). Вы можете использовать PDFImages для извлечения информации изображения во временный файл.
  3. Если предыдущие правила не работают (потому что нет изображений), вы можете использовать pdftext , чтобы извлечь текст, отфильтровать маркировку (если вы немного отфильшете, это не проблема), а затем генерируют хеш на основе этого.

Дополнительно вы можете сравнить, если размер файла старого файла найден через хэш и посмотреть, если находится в определенных полях с новым файлом. Сжатие и IFFERCENCES в строках (IP / Date-Time-Stamp) должны привести к тому, что приведут только менее чем на одну процентную разницу.

Если вы знаете метод, который издатель использует при определении хеша, вы можете напрямую применить «правильный» метод вышеперечисленного, но даже без того, что вы можете проверить наличие метаданных и применить некоторую эвристику или определить количество изображений В файле и сравните это с количеством страниц (если они близки, у вас, вероятно, есть документ, состоящий из сканов). PDFTEXT На отсканированном изображении PDFS также имеет узнаваемый выход.


Как основа для работы от I создал пакет Python, который находится на Bitbucket и / или может быть установлен из PYPI , используя PIP Установить Ruamel.pdfdouble Отказ Это предоставляет вам команду PDFDBL , которая выполняет сканирование, как описано выше на метаданных, извлеченных изображениями или на тексте. Это не выполняет фильтрацию маркировки (еще) , но readme описывает, какие (два) методы улучшения, чтобы сделать это.

Включенные README:

RUAMEL.PDFDOUBL

Этот пакет предоставляет команду PDFDBL PDFDBL .

pdfdbl scan dir1 dir2

Это будет содержать каталоги, предоставленные в качестве аргумента, и для найденных файлов PDF Хаш на основе (в порядке):

  • Метаданные, если уникальные изображения
  • , если количество изображений
  • , если это текст

это предполагает, что pdfinfo, pdfimages и pdftoText` из пакета Popcler-utils доставляют.

А «база данных» накапливается в ~ / .CONFIG / PDFDBL / PDF.LST , против которого тестируются дальнейшие сканирования.

Удаление маркировки

в RUAMEL / PDFDOUBLE / PDFDOUBLE.PY Существует два метода, которые могут быть улучшены для отфильтровывания маркировков в PDF, которые делают их менее уникальными и сделать практически одни и те же файлы для иметь разные хэши.

Для текста метод pdfdata.filter_for_marking должен быть расширен для удаления и отметок из строки, которая является ее аргументами и возвращает результат.

Для отсканированных изображений метод PDFData.process_Image_and_Update необходимо улучшить, например, e.g. Вырезая изображения нижних и верхних х строк, и удалив любой серый текст фона, устанавливая все черные пиксели в белый. Эта функция должна обновлять хеш, передаваемый методом .update () , проходящий в фильтрованные данные.

Ограничения

Текущая «база данных» не может обрабатывать пути, содержащие ньюгин

, эта утилита в настоящее время имеет только Python 2.7.


IP-установленные stringParts могут быть заменены модулем Python Re :

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'
4
27.01.2020, 20:07

Существует приложение Linux, называемое . . Это может выполнить задачу, но только для PDF с текстовым слоем.

-1
27.01.2020, 20:07

Я бы предложил Perl как решение. Существует модуль под названием CAM :: PDF , который позволяет извлечь ... PDF Content.

Это работает немного похоже на это:

#!/usr/bin/perl

use strict;
use warnings;

use CAM::PDF;

my $file = 'sample.pdf';

my $pdf = CAM::PDF->new($file);

my $word_count = 0;
for my $pagenum ( 1 .. $pdf->numPages ) {
    my $page_text = $pdf->getPageText($pagenum) );
    print $page_text; 
}

Вы можете извлечь текст и сравнивать это.

Для отсканированных только документов - это намного сложнее, но , при условии, , они используют одни и те же базовые изображения (например, их не разделить), тогда вы, вероятно, можете использовать:

#!/usr/bin/perl

use strict;
use warnings;

use CAM::PDF;
use CAM::PDF::Renderer::Images;
use Data::Dumper; 

my $file = 'sample.pdf';

my $pdf = CAM::PDF->new($file);

my $word_count = 0;
for my $pagenum ( 1 .. $pdf->numPages ) {
    my $content =  $pdf->getPageText($pagenum);
    my $page = $pdf->getPageContentTree($pagenum);
    my $gs = $page->findImages();
    my @imageNodes = @{$gs->{images}};
    print Dumper \@imageNodes;

    print Dumper \$gs;
}

Я не тестировал Это особенно хорошо, потому что у меня нет ваших исходных документов. Я думаю Этот подход должен сделать трюк, хотя - вы не сравниваете фактический контент изображения, потому что .... Ну, это действительно сложно. Но вы должны быть в состоянии распознать подобные изображения из метаданных.

Для идентичных PDFS с различными метаданными, то что-то простое, как хеширование текстового контента, а метаданные изображения должны сделать трюк.

0
27.01.2020, 20:07

У меня есть скрипт, который смотрит на PDF и сначала пытается извлечь текст, используя pdftotext , но если это не удается (как он будет с отсканированным документом), он использует Ghostscript Чтобы повернуть Multi-Page Scanced PDF в серию файлов PNG, а затем использует Tesseract для преобразования этой серии в один текстовый файл. Если сканирование имеет достаточное качество, это делает довольно хорошую работу. Было бы просто добавить код, сравнивающий текст между файлами, но у меня не было этого требования.

Ghostscript и Tesseract являются как открытым исходным кодом, так и работают из командной строки.

1
27.01.2020, 20:07

Теги

Похожие вопросы