Fullmenu null

 

03 November 2017

En ete script vamos a tratar las siguientes capacidades de Groovy:

  • Incluir dependencias externas, en concreto PdfBox de Apache

  • Realizar bucles anidados de una forma sencilla

  • Generar mapas (key/value) al vuelo

Objetivo

Mediante este script y usando la librería PdfBox de Apache, dividiremos las páginas de un Pdf en áreas de tal forma que hagamos un "barrido" en cada una de ellas y podamos extraer el texto que se encuentre en las regiones. Al ir haciendo el "barrido" podremos identificar cada línea leída con una posición dentro de la página

Dependencias

Para la lectura del Pdf utilizaremos esta vez las librerías de Apache, PdfBox

@Grapes(
        @Grab(group='org.apache.pdfbox', module='pdfbox', version='2.0.8')
)
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.text.*
import java.awt.Rectangle

Script

margenright = 10    //(1)

PDDocument document = PDDocument.load(new URL(args[0]).bytes)

def pages = [:]
document.documentCatalog.pages.eachWithIndex { page , pageIndex->

    def paragraphs = [:]

    PDFTextStripperByArea stripper = new PDFTextStripperByArea(sortByPosition:true)
    (0..42).each {  //(2)
        stripper.addRegion("$it", new Rectangle( margenright, it * 20, 1500, 20));  //(3)
    }
    stripper.extractRegions(page)

    stripper.regions.eachWithIndex{ r, index->
        def str = stripper.getTextForRegion(r)
        if (str.trim().length() > 0)
            paragraphs["$index"] = str.trim()       //(4)
    }
    pages["$pageIndex"] = paragraphs    //(5)
}
println pages
  1. Puedes "jugar" a definir el margen derecho para afinar cuanto texto tomar desde la derecha.

  2. Definimos 42 regiones de 20 pixeles, suficientes para un A4

  3. Definimos un área de 1500x20 suficientes para leer el ancho de un A4

  4. Para cada region que encuentra con texto la añadimos dinámicamente a un mapa creado para la página

  5. Para cada página añadimos las áreas encontradas en un mapa creado para todo el documento.

En una linea (más Grappe)

@jmiguel en un afán minimalista nos comenta que el código anterior cumple su función en una sóla línea:

println new PDFTextStripper().getText(PDDocument.load(new URL(args[0]).bytes))//(1)

<1>Si el primer argumento es una ruta local a un PDF, comienzalo con file://


Script
//tag::dependencies[]
@Grapes(
        @Grab(group='org.apache.pdfbox', module='pdfbox', version='2.0.8')
)
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.text.*
import java.awt.Rectangle
//end::dependencies[]

//tag::sourceCode[]
margenright = 10    //(1)

PDDocument document = PDDocument.load(new URL(args[0]).bytes)

def pages = [:]
document.documentCatalog.pages.eachWithIndex { page , pageIndex->

    def paragraphs = [:]

    PDFTextStripperByArea stripper = new PDFTextStripperByArea(sortByPosition:true)
    (0..42).each {  //(2)
        stripper.addRegion("$it", new Rectangle( margenright, it * 20, 1500, 20));  //(3)
    }
    stripper.extractRegions(page)

    stripper.regions.eachWithIndex{ r, index->
        def str = stripper.getTextForRegion(r)
        if (str.trim().length() > 0)
            paragraphs["$index"] = str.trim()       //(4)
    }
    pages["$pageIndex"] = paragraphs    //(5)
}
println pages
//end::sourceCode[]