Есть ли простой способ определить, сканируется ли PDF?

8

У меня есть тысячи документов, и некоторые из них отсканированы. Поэтому мне нужен скрипт для проверки всех файлов PDF, которые принадлежат каталогу. Есть ли простой способ сделать это?

  1. Большинство PDF-файлов являются отчетами. Таким образом, у них много текста.
  2. Они очень разные, но отсканированные, как упомянуто ниже, могут найти некоторый текст из-за нестабильного процесса OCR, связанного со сканированием.

  3. Предложение из-за Судодуса в комментариях ниже, кажется очень интересным. Посмотрите на разницу между отсканированным и не отсканированным PDF:

Отсканированные:

grep --color -a 'Image' AR-G1002.pdf
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 340615/Name/Obj13/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 40452/Name/Obj18/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 41680/Name/Obj23/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 41432/Name/Obj28/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 59084/Name/Obj33/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 472681/Name/Obj38/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 469340/Name/Obj43/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 371863/Name/Obj48/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 344092/Name/Obj53/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 59416/Name/Obj58/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 48308/Name/Obj63/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 51564/Name/Obj68/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 63184/Name/Obj73/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 40824/Name/Obj78/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 23320/Name/Obj83/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 31504/Name/Obj93/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 18996/Name/Obj98/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 8/ColorSpace/DeviceRGB/Filter[/DCTDecode]/Height 2197/Length 292932/Name/Obj103/Subtype/Image/Type/XObject/Width 1698>>stream
<</BitsPerComponent 1/ColorSpace/DeviceGray/DecodeParms<</Columns 1698/K -1>>/Filter/CCITTFaxDecode/Height 2197/Length 27720/Name/Obj108/Subtype/Image/Type/XObject/Width 1698>>stream
               <rdf:li xml:lang="x-default">Image</rdf:li>
               <rdf:li xml:lang="x-default">Image</rdf:li>

Не отсканировано:

grep --color -a 'Image' AR-G1003.pdf
<</Lang(en-US)/MarkInfo<</Marked true>>/Metadata 167 0 R/Pages 2 0 R/StructTreeR<</Contents 4 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F3 9 0 R/F4 11 0 R/F5 13 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/StructParents 0/Tabs/S/Type/<</Filter/FlateDecode/Length 5463>>stream
<</BaseFont/Times#20New#20Roman,Bold/Encoding/WinAnsiEncoding/FirstChar 32/FontD<</Ascent 891/AvgWidth 427/CapHeight 677/Descent -216/Flags 32/FontBBox[-558 -216 2000 677]/FontName/Times#20New#20Roman,Bold/FontWeight 700/ItalicAngle 0/Leadi<</BaseFont/Times#20New#20Roman/Encoding/WinAnsiEncoding/FirstChar 32/FontDescri<</Ascent 891/AvgWidth 401/CapHeight 693/Descent -216/Flags 32/FontBBox[-568 -216 2000 693]/FontName/Times#20New#20Roman/FontWeight 400/ItalicAngle 0/Leading 42<</BaseFont/Arial,Bold/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 10 0<</Ascent 905/AvgWidth 479/CapHeight 728/Descent -210/Flags 32/FontBBox[-628 -210 2000 728]/FontName/Arial,Bold/FontWeight 700/ItalicAngle 0/Leading 33/MaxWidth<</BaseFont/Times#20New#20Roman,Italic/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 12 0 R/LastChar 118/Name/F4/Subtype/TrueType/Type/Font/Widths 164 0 <</Ascent 891/AvgWidth 402/CapHeight 694/Descent -216/Flags 32/FontBBox[-498 -216 1333 694]/FontName/Times#20New#20Roman,Italic/FontWeight 400/ItalicAngle -16.4<</BaseFont/Arial/Encoding/WinAnsiEncoding/FirstChar 32/FontDescriptor 14 0 R/La<</Ascent 905/AvgWidth 441/CapHeight 728/Descent -210/Flags 32/FontBBox[-665 -210 2000 728]/FontName/Arial/FontWeight 400/ItalicAngle 0/Leading 33/MaxWidth 2665<</Contents 16 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F5 13 0 R>>/ProcSet[<</Filter/FlateDecode/Length 7534>>streamarents 1/Tabs/S/Type/Page>>
<</Contents 18 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F5 13 0 R>>/ProcSet[<</Filter/FlateDecode/Length 6137>>streamarents 2/Tabs/S/Type/Page>>
<</Contents 20 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R/F5 13 0 R/F6 21 0 R><</Filter/FlateDecode/Length 6533>>stream>>/StructParents 3/Tabs/S/Type/Page>>
<</BaseFont/Times#20New#20Roman/DescendantFonts 22 0 R/Encoding/Identity-H/Subty<</BaseFont/Times#20New#20Roman/CIDSystemInfo 24 0 R/CIDToGIDMap/Identity/DW 100<</Ascent 891/AvgWidth 401/CapHeight 693/Descent -216/Flags 32/FontBBox[-568 -216 2000 693]/FontFile2 160 0 R/FontName/Times#20New#20Roman/FontWeight 400/Italic<</Contents 27 0 R/Group<</CS/DeviceRGB/S/Transparency/Type/Group>>/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<</ExtGState<</GS28 28 0 R/GS29 29 0 R>>/Font<</F1 5 0 R/F2 7 0 R/F3 9 0 R/F5 13 0 R/F6 21 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC<</Filter/FlateDecode/Length 5369>>streamge>>

Количество изображений на странице намного больше (около одного на страницу)!

DanielTheRocketMan
источник
7
Вы имеете в виду текст или изображения?
ДК Бозе
8
Почему вы хотите знать, сканируется ли файл PDF или нет? Как вы собираетесь использовать эту информацию?
Судод
4
@sudodus задает очень хороший вопрос. Например, для большинства отсканированных PDF-файлов их текст доступен для выбора и конвертируется с помощью OCR. Есть ли разница между такими файлами и текстовыми файлами? Как вы знаете , источник ваших PDF - файлов?
труба
1
Есть ли разница в метаданных отсканированных и не отсканированных документов? Это было бы очень чисто и легко.
десерт
1
Если pdfфайл содержит изображение (вставленное в документ вместе с текстом или целыми страницами, «отсканированный pdf»), файл часто (возможно, всегда) содержит строку /Image/, которую можно найти с помощью командной строки grep --color -a 'Image' filename.pdf. Это позволит отделить файлы, содержащие только текст, от изображений, содержащих изображения (полностраничные изображения, а также текстовые страницы с небольшими логотипами и иллюстрирующими изображениями среднего размера).
Судодус

Ответы:

4

Shellscript

  • Если pdfфайл содержит изображение (вставленное в документ рядом с текстом или целыми страницами, «отсканированный pdf»), файл часто (возможно, всегда) содержит строку /Image/.

  • Таким же образом вы можете искать строку, /Textчтобы узнать, содержит ли файл PDF текст (не отсканированный).

Я сделал шеллскрипт pdf-text-or-image, и он может работать в большинстве случаев с вашими файлами. Shellscript ищет текстовые строки /Image/и /Textв pdfфайлах.

#!/bin/bash

echo "shellscript $0"
ls --color --group-directories-first
read -p "Is it OK to use this shellscript in this directory? (y/N) " ans
if [ "$ans" != "y" ]
then
 exit
fi

mkdir -p scanned
mkdir -p text
mkdir -p "s-and-t"

for file in *.pdf
do
 grep -aq '/Image/' "$file"
 if [ $? -eq 0 ]
 then
  image=true
 else
  image=false
 fi
 grep -aq '/Text' "$file"
 if [ $? -eq 0 ]
 then
  text=true
 else
  text=false
 fi


 if $image && $text
 then
  mv "$file" "s-and-t"
 elif $image
 then
  mv "$file" "scanned"
 elif $text
 then
  mv "$file" "text"
 else
  echo "$file undecided"
 fi
done

Сделать исполняемый скрипт,

chmod ugo+x pdf-text-or-image

Перейдите в каталог, где у вас есть pdfфайлы и запустите скрипт.

Идентифицированные файлы перемещаются в следующие подкаталоги

  • scanned
  • text
  • s-and-t (для документов с [отсканированными?] изображениями и текстовым содержимым)

Неопознанные файловые объекты, «НЛО», остаются в текущем каталоге.

Тестовое задание

Я протестировал шеллскрипт с двумя вашими файлами, AR-G1002.pdfи AR-G1003.pdf, и с некоторыми собственными pdfфайлами (которые я создал с помощью Libre Office Impress).

$ ./pdf-text-or-image
shellscript ./pdf-text-or-image
s-and-t                                 mkUSB-quick-start-manual-11.pdf    mkUSB-quick-start-manual-nox-11.pdf
scanned                                 mkUSB-quick-start-manual-12-0.pdf  mkUSB-quick-start-manual-nox.pdf
text                                    mkUSB-quick-start-manual-12.pdf    mkUSB-quick-start-manual.pdf
AR-G1002.pdf                            mkUSB-quick-start-manual-74.pdf    OBI-quick-start-manual.pdf
AR-G1003.pdf                            mkUSB-quick-start-manual-75.pdf    oem.pdf
DescriptionoftheOneButtonInstaller.pdf  mkUSB-quick-start-manual-8.pdf     pdf-text-or-image
GrowIt.pdf                              mkUSB-quick-start-manual-9.pdf     pdf-text-or-image0
list-files.pdf                          mkUSB-quick-start-manual-bas.pdf   README.pdf
Is it OK to use this shellscript in this directory? (y/N) y

$ ls -1 *
pdf-text-or-image
pdf-text-or-image0

s-and-t:
DescriptionoftheOneButtonInstaller.pdf
GrowIt.pdf
mkUSB-quick-start-manual-11.pdf
mkUSB-quick-start-manual-12-0.pdf
mkUSB-quick-start-manual-12.pdf
mkUSB-quick-start-manual-8.pdf
mkUSB-quick-start-manual-9.pdf
mkUSB-quick-start-manual.pdf
OBI-quick-start-manual.pdf
README.pdf

scanned:
AR-G1002.pdf

text:
AR-G1003.pdf
list-files.pdf
mkUSB-quick-start-manual-74.pdf
mkUSB-quick-start-manual-75.pdf
mkUSB-quick-start-manual-bas.pdf
mkUSB-quick-start-manual-nox-11.pdf
mkUSB-quick-start-manual-nox.pdf
oem.pdf

Будем надеяться, что

  • в вашем наборе файлов нет НЛО
  • сортировка верна в отношении текста и отсканированных изображений
sudodus
источник
вместо перенаправления в / dev / null вы можете просто использоватьgrep -q
phuclv
1
@phuclv, спасибо за подсказку :-) Это тоже делает его несколько быстрее, особенно с большими файлами, потому что grep -qсразу выходит с нулевым статусом, если найдено какое-либо совпадение (вместо поиска по всем файлам).
Судодус
6
  1. Поместите все файлы .pdf в одну папку.
  2. В этой папке нет файла .txt.
  3. В терминале измените каталог на эту папку с помощью cd <path to dir>
  4. Создайте еще один каталог для не отсканированных файлов. Пример:
mkdir ./x 
for file in *.pdf; do
    if [ $(pdftotext "$file")"x" == "x" ] ; then mv "$file" ./x; fi
rm *.txt
done

Все отсканированные в формате PDF файлы останутся в папке, а другие файлы будут перемещены в другую папку.

Виджай
источник
это замечательно. Однако этот файл переходит в другую папку и сканируется: drive.google.com/open?id=12xIQdRo_cyTf27Ck6DQKvRyRvlkYEzjl Что происходит?
DanielTheRocketMan
8
Отсканированные PDF-файлы часто всегда содержат текст OCRed, поэтому я предполагаю, что простой тест для них не пройдет. Лучшим показателем может быть одно большое изображение на странице, независимо от содержания текста.
Джои
2
Отказался из-за очевидного недостатка: как узнать, сканируются ли файлы или нет? Это то, что ОП спрашивает: как программно проверять сканированные или нет.
jamesqf
1
@DanielTheRocketMan Версия файла PDF, вероятно, влияет на инструмент, который вы используете для выделения текста. Вывод file pdf-filename.pdfвыдаст номер версии. Мне не удалось найти конкретный текст в BR-L1411-3.pdf BR-L1411-3.pdf: документ PDF, версия 1.3, но я смог найти текст в обоих других предоставленных вами файлах, которые являются версией 1.5 и 1.6 и получите один или несколько совпадений. Я использовал PDF XChange Viewer для поиска этих файлов, но у меня были похожие результаты с evince. документ версии 1.3 ничего не соответствовал.
Старейшина Гик
1
@DanielTheRocketMan Если это так, вы можете найти сортировку документов по версии, используя fileполезные результаты при завершении вашего проекта. Хотя, как мне кажется, другие до сих пор не знают, чего именно вы пытаетесь достичь.
Старейшина Гик
2

Я создал скрипт, чтобы определить, был ли PDF OCRd. Основная идея: в OCRd PDFs текст невидим.

Алгоритм проверки, был ли данный PDF ( f1) OCRd:

  1. создать копию, f1отмеченную какf2
  2. удалить весь текст на f2
  3. создавать изображения (PNG) для всех (или только нескольких) страниц для f1иf2
  4. f1был OCRd, если все изображения f1и f2идентичны.

https://github.com/jfilter/pdf-scripts/blob/master/is_ocrd_pdf.sh

#!/usr/bin/env bash
set -e
set -x

################################################################################
# Check if a PDF was scanned or created digitally, works on OCRd PDFs
#
# Usage:
#   bash is_scanned_pdf.sh [-p] file
#
#   Exit 0: Yes, file is a scanned PDF
#   Exit 99: No, file was created digitally
#
# Arguments:
#   -p or --pages: pos. integer, only consider first N pages
#
# Please report issues at https://github.com/jfilter/pdf-scripts/issues
#
# GPLv3, Copyright (c) 2020 Johannes Filter
################################################################################

# parse arguments
# h/t https://stackoverflow.com/a/33826763/4028896
max_pages=-1
# skip over positional argument of the file(s), thus -gt 1
while [[ "$#" -gt 1 ]]; do
  case $1 in
  -p | --pages)
    max_pages="$2"
    shift
    ;;
  *)
    echo "Unknown parameter passed: $1"
    exit 1
    ;;
  esac
  shift
done

# increment to make it easier with page numbering
max_pages=$((max_pages++))

command_exists() {
  if ! [ -x $($(command -v $1 &>/dev/null)) ]; then
    echo $(error: $1 is not installed.) >&2
    exit 1
  fi
}

command_exists mutool && command_exists gs && command_exists compare
command_exists pdfinfo

orig=$PWD
num_pages=$(pdfinfo $1 | grep Pages | awk '{print $2}')

echo $num_pages

echo $max_pages

if ((($max_pages > 1) && ($max_pages < $num_pages))); then
  num_pages=$max_pages
fi

cd $(mktemp -d)

for ((i = 1; i <= num_pages; i++)); do
  mkdir -p output/$i && echo $i
done

# important to filter text on output of GS (tmp1), cuz GS alters input PDF...
gs -o tmp1.pdf -sDEVICE=pdfwrite -dLastPage=$num_pages $1 &>/dev/null
gs -o tmp2.pdf -sDEVICE=pdfwrite -dFILTERTEXT tmp1.pdf &>/dev/null
mutool convert -o output/%d/1.png tmp1.pdf 2>/dev/null
mutool convert -o output/%d/2.png tmp2.pdf 2>/dev/null

for ((i = 1; i <= num_pages; i++)); do
  echo $i
  # difference in pixels, if 0 there are the same pictures
  # discard diff image
  if ! compare -metric AE output/$i/1.png output/$i/2.png null: 2>&1; then
    echo " pixels difference, not a scanned PDF, mismatch on page $i"
    exit 99
  fi
done
Йоханнес Фильтр
источник
1

Любитель предлагает хорошее решение, если в отсканированных документах коллекции документов нет текста с оптическим распознаванием символов (OCR). Если это возможно, вы можете захотеть pdfinfo -metaсоздать сценарий, который считывает выходные данные и проверяет инструмент, использованный для создания файла, или использовать процедуру Python, которая использует одну из библиотек Python для их проверки. Поиск текста с помощью подобного инструмента stringsбудет ненадежным, поскольку содержимое PDF можно сжать. Кроме того, проверка инструмента создания также небезопасна, поскольку страницы PDF можно комбинировать; Я регулярно комбинирую текстовые документы в формате PDF с отсканированными изображениями, чтобы все было вместе.

Мне жаль, что я не могу предложить конкретные предложения. Прошло много времени с тех пор, как я изучил внутреннюю структуру PDF, но в зависимости от того, насколько жесткими являются ваши требования, вы можете захотеть узнать, что это довольно сложно. Удачи!

Ихавод
источник
2
Я также пытаюсь использовать Python, но это не тривиально, чтобы узнать, сканируется ли PDF или нет. Дело в том, что даже документы, которые вы не можете выделить, представляют текст при преобразовании в текстовый формат. Например, я использую pdf-майнер в Python, и я могу найти какой-то текст в преобразовании даже для pdf, что инструмент выбора не работает.
DanielTheRocketMan
1

Если это больше касается фактического обнаружения, если PDF был создан путем сканирования, а не в pdf есть изображения вместо текста, то вам, возможно, придется копаться в метаданных файла, а не только в содержимом.

В целом, для файлов, которые я мог найти на своем компьютере, и для ваших тестовых файлов, верно следующее:

  • Отсканированные файлы имеют менее 1000 символов на страницу по сравнению с не отсканированными, у которых всегда более 1000 символов на страницу
  • На нескольких независимых отсканированных файлах в качестве создателя PDF был указан «Canon», вероятно, ссылающийся на программное обеспечение сканера Canon.
  • PDF-файлы с «Microsoft Word» в качестве создателя, скорее всего, не будут сканироваться, поскольку они являются экспортом слов. Но кто-то может сканировать в слово, а затем экспортировать в PDF - у некоторых людей очень странный рабочий процесс .

Сейчас я использую Windows, поэтому я использовал node.jsследующий пример:

const fs = require("mz/fs");
const pdf_parse = require("pdf-parse");
const path = require("path");


const SHOW_SCANNED_ONES = process.argv.indexOf("scanned") != -1;

const DEBUG = process.argv.indexOf("debug") != -1;
const STRICT = process.argv.indexOf("strict") != -1;

const debug = DEBUG ? console.error : () => { };

(async () => {
    const pdfs = (await fs.readdir(".")).filter((fname) => { return fname.endsWith(".pdf") });

    for (let i = 0, l = pdfs.length; i < l; ++i) {
        const pdffilename = pdfs[i];
        try {
            debug("\n\nFILE: ", pdffilename);
            const buffer = await fs.readFile(pdffilename);
            const data = await pdf_parse(buffer);

            if (!data.info)
                data.indo = {};
            if (!data.metadata) {
                data.metadata = {
                    _metadata: {}
                };
            }


            // PDF info
            debug(data.info);
            // PDF metadata
            debug(data.metadata);
            // text length
            const textLen = data.text ? data.text.length : 0;
            const textPerPage = textLen / (data.numpages);
            debug("Text length: ", textLen);
            debug("Chars per page: ", textLen / data.numpages);
            // PDF.js version
            // check https://mozilla.github.io/pdf.js/getting_started/
            debug(data.version);

            if (evalScanned(data, textLen, textPerPage) == SHOW_SCANNED_ONES) {
                console.log(path.resolve(".", pdffilename));
            }
        }
        catch (e) {
            if (strict && !debug) {
                console.error("Failed to evaluate " + item);
            }
            {
                debug("Failed to evaluate " + item);
                debug(e.stack);
            }
            if (strict) {
                process.exit(1);
            }
        }
    }
})();
const IS_CREATOR_CANON = /canon/i;
const IS_CREATOR_MS_WORD = /microsoft.*?word/i;
// just defined for better clarity or return values
const IS_SCANNED = true;
const IS_NOT_SCANNED = false;
function evalScanned(pdfdata, textLen, textPerPage) {
    if (textPerPage < 300 && pdfdata.numpages>1) {
        // really low number, definitelly not text pdf
        return IS_SCANNED;
    }
    // definitelly has enough text
    // might be scanned but OCRed
    // we return this if no 
    // suspition of scanning is found
    let implicitAssumption = textPerPage > 1000 ? IS_NOT_SCANNED : IS_SCANNED;
    if (IS_CREATOR_CANON.test(pdfdata.info.Creator)) {
        // this is always scanned, canon is brand name
        return IS_SCANNED;
    }
    return implicitAssumption;
}

Чтобы запустить его, вам нужно установить Node.js (это должна быть одна команда), а также вызвать:

npm install mz pdf-parse

Применение:

node howYouNamedIt.js [scanned] [debug] [strict]

 - scanned show PDFs thought to be scanned (otherwise shows not scanned)
 - debug shows the debug info such as metadata and error stack traces
 - strict kills the program on first error

Этот пример не считается законченным решением, но с debugфлагом вы получите некоторое представление о метаинформации файла:

FILE:  BR-L1411-3-scanned.pdf
{ PDFFormatVersion: '1.3',
  IsAcroFormPresent: false,
  IsXFAPresent: false,
  Creator: 'Canon ',
  Producer: ' ',
  CreationDate: 'D:20131212150500-03\'00\'',
  ModDate: 'D:20140709104225-03\'00\'' }
Metadata {
  _metadata:
   { 'xmp:createdate': '2013-12-12T15:05-03:00',
     'xmp:creatortool': 'Canon',
     'xmp:modifydate': '2014-07-09T10:42:25-03:00',
     'xmp:metadatadate': '2014-07-09T10:42:25-03:00',
     'pdf:producer': '',
     'xmpmm:documentid': 'uuid:79a14710-88e2-4849-96b1-512e89ee8dab',
     'xmpmm:instanceid': 'uuid:1d2b2106-a13f-48c6-8bca-6795aa955ad1',
     'dc:format': 'application/pdf' } }
Text length:  772
Chars per page:  2
1.10.100
D:\web\so-odpovedi\pdf\BR-L1411-3-scanned.pdf

Наивная функция, которую я написал, имеет 100% успех на документах, которые я могу найти на своем компьютере (включая ваши образцы). Я назвал файлы в зависимости от их состояния до запуска программы, чтобы можно было увидеть, верны ли результаты.

D:\xxxx\pdf>node detect_scanned.js scanned
D:\xxxx\pdf\AR-G1002-scanned.pdf
D:\xxxx\pdf\AR-G1002_scanned.pdf
D:\xxxx\pdf\BR-L1411-3-scanned.pdf
D:\xxxx\pdf\WHO_TRS_696-scanned.pdf

D:\xxxx\pdf>node detect_scanned.js
D:\xxxx\pdf\AR-G1003-not-scanned.pdf
D:\xxxx\pdf\ASEE_-_thermoelectric_paper_-_final-not-scanned.pdf
D:\xxxx\pdf\MULTIMODE ABSORBER-not-scanned.pdf
D:\xxxx\pdf\ReductionofOxideMineralsbyHydrogenPlasma-not-scanned.pdf

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

Томаш Зато - Восстановить Монику
источник
«Microsoft Word» как создатель, это будет зависеть от источника оригинальных документов. Если, например, они являются научными работами, многие, если не большинство, будут созданы чем-то в наборе инструментов LaTeX.
jamesqf
0

2 способа, которыми я могу придумать:

  1. Использование инструмента выбора текста: если вы используете отсканированный PDF, тексты не могут быть выделены, скорее появится окно. Вы можете использовать этот факт для создания сценария. Я знаю, что в C ++ QT есть способ, хотя я не уверен в Linux.

  2. Поиск слова в файле: в не отсканированном PDF ваш поиск будет работать, но не в отсканированном файле. Вам просто нужно найти слова, общие для всех PDF-файлов, или я бы сказал, искать букву «е» во всех PDF-файлах. Он имеет наибольшее распределение частот, поэтому, скорее всего, вы найдете его во всех документах, в которых есть текст (если только он не гадсби )

например

grep -rnw '/path/to/pdf/' -e 'e'

Используйте любой из инструментов обработки текста

swapedoc
источник
1
в отсканированном PDF также могут быть тексты, которые можно выбирать, потому что в настоящее время OCR не является чем-то странным, и даже многие бесплатные программы для чтения PDF имеют функцию OCR
phuclv
@phuclv: Но если файл был преобразован в текст с помощью OCR, он больше не является «отсканированным» файлом, по крайней мере, насколько я понимаю, цель ОП. Хотя на самом деле у вас теперь есть 3 типа PDF-файлов: текст ab initio, текст из OCR и «текст», который является отсканированным изображением.
jamesqf
1
@jamesqf, пожалуйста, посмотрите на пример выше. Они отсканированы в формате PDF. Большую часть текста я не могу получить с помощью обычного pdfminer.
DanielTheRocketMan
1
я думаю, что операционному агентству необходимо переосмыслить / перефразировать определение отсканированного в этом случае или прекратить использовать acrobat x, который берет отсканированную копию и воспринимает ее как ocr, а не как изображение
swapedoc