Wydobywanie tekstów i grafik z plików PDF

Podziel się z innymi!

    Bywa że klient przysyła Ci treści do umieszczenia na stronie z krótkim komentarzem – „Tak to sobie wyobrażam”. Otwierasz maila i widzisz plik PDF. Są tam pięknie ułożone teksty okraszone kolorowymi fotografiami, wszystko elegancko poukładane i skomponowane, a Ty drapiesz się w głowę i nic nie mówisz bo szkoda słów. Jeśli jesteś webdeveloperem, specjalistą od cięcia i stylowania to szczerze Ci współczuję. Jeśli jednak Twoim jedynym zadaniem jest wydobycie z tego PDF-a wszystkich tekstów oraz grafik to jest nadzieja.

    Klikacze lub marzyciele często patrzący w „okna” mogą skorzystać z jednej z rad proponowanych w artykule How to Extract Text from a PDF document lub How Can I Get Text or Images Out of a PDF File?. Alternatywą jest użycie konsoli i wierzcie mi w tym przypadku jest to o wiele wygodniejsze i szybsze rozwiązanie.

    Do wyłuskania tekstów używamy programu „pdftotext” będącego częścią programu „xpdf

    pdftotext ./dokument.pdf

    Gdyby były problemy z polskimi literami warto zapoznać się z opcją „enc”:

    pdftotext -enc Latin2 dokument.pdf

    albo

    pdftotext -enc UTF-8 dokument.pdf

    Z obrazkami robimy identycznie tylko, że używając programu „pdfimages” także będącego konsolowym narzędziem „xpdf-a”

    pdfimages ./dokument.pdf  przedrostek_obrazka

    Program „pdfimages” zapisuje obrazki w formacie plików „ppm” więc trzeba je jeszcze przekonwertować do jpg-ów np. przy pomocy programu „pnmtojpeg” będącego częścią większego pakietu programów graficznych „Netpbm„.

    for pic in *.ppm 
    do 
        pnmtojpeg "${pic}" > "${pic/%ppm/jpg}" 
    done

    O ile programy „pdftotext” jak i „pdfimages” miałem już w systemie to „pnmtojpeg” trzeba było doinstalować i kiedy już to zrobiłem i przetestowałem przypomniałem sobie, że mam przecież zainstalowanego „ImageMagick-a„, którego użycie okazało się jeszcze prostsze.

    mogrify -format jpg *.ppm

    Pliki wynikowe uzyskane po zastosowaniu „mogrify” są większe co sugeruje mniejszą stratę na jakości, poza tym jak się ma „ImageMagick-a” to można z tymi plikami zrobić przy okazji dużo więcej np. automatycznie przeskalować, utworzyć miniatury, dodać ramki czy co nam tam jeszcze przyjdzie do głowy. Tworząc skrypt, który wszystkie wyżej przytoczone komendy zbiera w jedną zdecydowałem się właśnie na „mogrify”.

    Plik extractpdf.sh

    #!/bin/sh
     
    if [ $# -lt 1 ]; then
        echo "Usage: `basename $0` file.pdf"
        exit 1;
    fi
     
    PDF=$1
    FILE_NAME=`basename ${PDF%.*}`
    TEMP_DIR="`dirname $PDF`/${FILE_NAME}"
     
    if [ ! -e $TEMP_DIR ]; then
        mkdir -p $TEMP_DIR;
    fi
    pdftotext $PDF "${TEMP_DIR}/${FILE_NAME}.txt"
     
    pdfimages $PDF "${TEMP_DIR}/${FILE_NAME}"
     
    mogrify -format jpg ${TEMP_DIR}/*.ppm
    find ${TEMP_DIR}/ -name "*.ppm" -exec rm {} \;

    Skrypt oszczędza masę pisania poza tym jest uniwersalny więc nadaje się do wielokrotnego użytku. Teraz wystarczy nadać mu prawa do wykonywania

    chmod +x ./extractpdf.sh

    i cała praca to wywołanie skryptu z podaniem ścieżki do pliku pdf w parametrze

    ./extractpdf.sh ./dokument.pdf

    Można pokusić się o rozbudowę tego skryptu o sprawdzanie czy wymagane programy są zainstalowane oraz zwiększyć funkcjonalność poprzez próbę użycia „pnmtojpeg” w przypadku jeśli „ImageMagick” nie jest zainstalowany.

    Plik extractpdf2.sh

    #!/bin/bash
     
    if [ $# -lt 1 ]; then
        echo "Usage: `basename $0` file.pdf"
    	exit 1;
    fi
     
    type -P pdftotext &>/dev/null || { echo "I require pdftotext but it's not installed.  Aborting." >&2; exit 1; }
     
    type -P pdfimages &>/dev/null || { echo "I require pdfimages but it's not installed.  Aborting." >&2; exit 1; }
     
    if type -P mogrify >/dev/null; then
        CONVERTER="mogrify"
    else
        type -P pnmtojpeg &>/dev/null || { echo "I require the mogrify or pnmtojpeg but none of them is not installed.  Aborting." >&2; exit 1; } 
        CONVERTER="pnmtojpeg"
    fi
     
    PDF=$1
    FILE_NAME=`basename ${PDF%.*}`
    TEMP_DIR="`dirname $PDF`/${FILE_NAME}"
     
    if [ ! -e $TEMP_DIR ]; then
        mkdir -p $TEMP_DIR;
    fi
     
    pdftotext $PDF "${TEMP_DIR}/${FILE_NAME}.txt"
     
    pdfimages $PDF "${TEMP_DIR}/${FILE_NAME}"
     
    if [ $CONVERTER = 'mogrify' ]; then
        mogrify -format jpg ${TEMP_DIR}/*.ppm
        find ${TEMP_DIR}/ -name "*.ppm" -exec rm {} \;
    else
        for PIC in ${TEMP_DIR}/*.ppm
        do
            pnmtojpeg "${PIC}" > "${PIC/%ppm/jpg}"
            rm $PIC
        done
    fi

    UWAGA!!! Użycie „type -P” wymaga skorzystania konkretnie z powłoki „bash” gdyż w „sh” program „type” nie ma opcji „-P” i traktuje ją jak ścieżkę do pliku co kończy się komunikatem błędu (-P: not found). Dlatego pomimo, że plik dalej nazywa się extractpdf.sh to zamiast „#!/bin/sh” należy wpisać „#!/bin/bash”.

    To oczywiście nie wyczerpuje naszych możliwości. Zaproponowane przeze mnie narzędzie to niezbędne minimum. Stworzenie tego skryptu kosztowało mnie trochę czasu ale jest to praca jednorazowa. Podobnie miałem ze skryptem do generowania miniatur za to obecnie stale mam go w swoim arsenale i wierzcie mi, że suma sumarum zaoszczędził mi już naprawdę wiele czasu.

    Podziel się z innymi!

      Posted in Bash by Zbigniew Heintze · Tag: