Trabajar con archivos PDF en Python: leer y dividir páginas

    Este artículo es el primero de una serie sobre cómo trabajar con archivos PDF en Python:

    • Leer y dividir páginas (estás aquí)
    • Agregar imágenes y marcas de agua
    • Insertar, eliminar y reordenar páginas

    El formato de documento PDF

    Hoy en día, el formato de documento portátil (PDF) pertenece a los formatos de datos más utilizados. En 1990, Adobe definió la estructura de un documento PDF. La idea detrás del formato PDF es que los datos / documentos transmitidos se vean exactamente iguales para ambas partes involucradas en el proceso de comunicación: el creador, autor o remitente y el receptor. PDF es el sucesor del Posdata formato, y estandarizado como ISO 32000-2: 2017.

    Procesamiento de documentos PDF

    Para Linux existen poderosas herramientas de línea de comandos disponibles, como pdftk y pdfgrep. Como desarrollador, existe un gran entusiasmo al crear su propio software que se basa en Python y utiliza bibliotecas PDF que están disponibles gratuitamente.

    Este artículo es el comienzo de una pequeña serie y cubrirá estas útiles bibliotecas de Python. En la primera parte, nos centraremos en la manipulación de archivos PDF existentes. Aprenderá a leer y extraer el contenido (tanto texto como imágenes), rotar páginas individuales y dividir documentos en sus páginas individuales. La segunda parte cubrirá la adición de una marca de agua basada en superposiciones. La tercera parte se centrará exclusivamente en la redacción / creación de archivos PDF, y también incluirá eliminar y volver a combinar páginas individuales en un nuevo documento.

    Herramientas y bibliotecas

    La gama de soluciones disponibles para herramientas, módulos y bibliotecas PDF relacionadas con Python es un poco confusa, y lleva un momento averiguar qué es qué y qué proyectos se mantienen continuamente. Según nuestra investigación, estos son los candidatos que están actualizados:

    • PyPDF2: Una biblioteca de Python para extraer información y contenido de documentos, dividir documentos página por página, combinar documentos, recortar páginas y agregar marcas de agua. PyPDF2 admite documentos cifrados y no cifrados.
    • PDFMiner: Está escrito completamente en Python y funciona bien para Python 2.4. Para Python 3, use el paquete clonado PDFMiner.six. Ambos paquetes le permiten analizar, analizar y convertir documentos PDF. Esto incluye la compatibilidad con PDF 1.7, así como con los idiomas CJK (chino, japonés y coreano) y varios tipos de fuentes (Type1, TrueType, Type3 y CID).
    • PDFQuery: Se describe a sí misma como “una biblioteca de scraping de PDF rápida y sencilla” que se implementa como un contenedor de PDFMiner, lxml y pyquery. Su objetivo de diseño es “extraer datos de forma fiable de conjuntos de archivos PDF con la menor cantidad de código posible”.
    • tabula-py: Es una simple envoltura de Python de tabula-java, que puede leer tablas de archivos PDF y convertirlas en Pandas DataFrames. También le permite convertir un archivo PDF en un archivo CSV / TSV / JSON.
    • pdflib para Python: una extensión del Poppler Biblioteca que ofrece enlaces de Python para ello. Le permite analizar, analizar y convertir documentos PDF. No confundir con su colgante comercial que tiene el mismo nombre.
    • PyFPDF: Una biblioteca para la generación de documentos PDF en Python. Portado desde el FPDF Biblioteca PHP, un conocido reemplazo de extensión PDFlib con muchos ejemplos, scripts y derivados.
    • PDFTables: Un servicio comercial que ofrece extracción de tablas que viene como documento PDF. Ofrece una API para que PDFTables se pueda utilizar como SAAS.
    • Píxide – el paquete de gráficos de Python: PyX es un paquete de Python para la creación de archivos PostScript, PDF y SVG. Combina una abstracción del modelo de dibujo PostScript con una interfaz TeX / LaTeX. Tareas complejas como crear gráficos 2D y 3D en calidad lista para publicación se construyen a partir de estas primitivas.
    • ReportLab: Una biblioteca ambiciosa de nivel industrial centrada principalmente en la creación precisa de documentos PDF. Disponible gratuitamente como una versión de código abierto, así como una versión comercial mejorada llamada ReportLab PLUS.
    • PyMuPDF (también conocido como “fitz”): enlaces de Python para MuPDF, que es un visor de PDF y XPS ligero. La biblioteca puede acceder a archivos en formatos PDF, XPS, OpenXPS, epub, cómics y libros de ficción, y es conocida por su alto rendimiento y alta calidad de reproducción.
    • pdfrw: Un analizador de PDF puro basado en Python para leer y escribir PDF. Reproduce fielmente formatos vectoriales sin rasterización. Junto con ReportLab, ayuda a reutilizar partes de PDF existentes en nuevos PDF creados con ReportLab.

    Biblioteca utilizada para

    PyPDF2Leyendo
    PyMuPDFLeyendo
    pdflibLeyendo
    PDFTablesLeyendo
    tabula-pyLeyendo
    PDFMiner.sixLeyendo
    PDFQueryLeyendo
    pdfrwLeer, escribir / crear
    ReportlabEscribir / Crear
    PíxideEscribir / Crear
    PyFPDFEscribir / Crear

    A continuación, nos centraremos en PyPDF2 y PyMuPDF y explicaremos cómo extraer texto e imágenes de la forma más sencilla posible. Para comprender el uso de PyPDF2, fue útil una combinación de la documentación oficial y muchos ejemplos que están disponibles en otros recursos. En contraste, la documentación oficial de PyMuPDF es mucho más clara y considerablemente más rápida usando la biblioteca.

    Extrayendo texto con PyPDF2

    PyPDF2 se puede instalar como un paquete de software normal o utilizando pip3 (para Python3). Las pruebas aquí se basan en el paquete para la próxima versión de Debian GNU / Linux 10 “Buster”. El nombre del paquete Debian es python3-pypdf2.

    El Listado 1 importa el PdfFileReader clase, primero. A continuación, usando esta clase, abre el documento y extrae la información del documento usando el getDocumentInfo() método, el número de páginas que utilizan getDocumentInfo()y el contenido de la primera página.

    Tenga en cuenta que PyPDF2 comienza a contar las páginas con 0, y es por eso que la llamada pdf.getPage(0) recupera la primera página del documento. Finalmente, la información extraída se imprime en stdout.

    Listado 1: Extracción de la información y el contenido del documento.

    #!/usr/bin/python
    
    from PyPDF2 import PdfFileReader
    
    pdf_document = "example.pdf"
    with open(pdf_document, "rb") as filehandle:
        pdf = PdfFileReader(filehandle)
        info = pdf.getDocumentInfo()
        pages = pdf.getNumPages()
    
        print (info)
        print ("number of pages: %i" % pages)
    
        page1 = pdf.getPage(0)
        print(page1)
        print(page1.extractText())
    

    Fig.1: Texto extraído de un archivo PDF usando PyPDF2

    Como se muestra en la Figura 1 anterior, el texto extraído se imprime de forma continua. No hay párrafos ni separaciones de frases. Como se indica en la documentación de PyPDF2, todos los datos de texto se devuelven en el orden en que se proporcionan en el flujo de contenido de la página, y confiar en ellos puede llevar a algunas sorpresas. Esto depende principalmente de la estructura interna del documento PDF y de cómo el proceso de escritura de PDF produjo el flujo de instrucciones PDF.

    Extrayendo texto con PyMuPDF

    PyMuPDF está disponible en el sitio web de PyPi e instala el paquete con el siguiente comando en una terminal:

    $ pip3 install PyMuPDF
    

    La visualización de la información del documento, la impresión del número de páginas y la extracción del texto de un documento PDF se realiza de forma similar a la de PyPDF2 (consulte el Listado 2). El módulo a importar se llama fitzy vuelve al nombre anterior de PyMuPDF.

    Listado 2: Extracción de contenido de un documento PDF usando PyMuPDF.

    #!/usr/bin/python
    
    import fitz
    
    pdf_document = "example.pdf"
    doc = fitz.open(pdf_document):
    print ("number of pages: %i" % doc.pageCount)
    print(doc.metadata)
    
    page1 = doc.loadPage(0)
    page1text = page1.getText("text")
    print(page1text)
    

    Lo bueno de PyMuPDF es que mantiene intacta la estructura del documento original: los párrafos completos con saltos de línea se mantienen tal como están en el documento PDF (consulte la Figura 2).

    Fig.2: Datos de texto extraídos

    Extracción de imágenes de archivos PDF con PyMuPDF

    PyMuPDF simplifica la extracción de imágenes de documentos PDF utilizando el método getPageImageList(). El Listado 3 se basa en un ejemplo de la página wiki de PyMuPDF, y extrae y guarda todas las imágenes del PDF como archivos PNG página por página. Si una imagen tiene un espacio de color CMYK, primero se convertirá a RGB.

    Listado 3: Extracción de imágenes.

    #!/usr/bin/python
    
    import fitz
    
    pdf_document = fitz.open("file.pdf")
    for current_page in range(len(pdf_document)):
        for image in pdf_document.getPageImageList(current_page):
            xref = image[0]
            pix = fitz.Pixmap(pdf_document, xref)
            if pix.n < 5:        # this is GRAY or RGB
                pix.writePNG("page%s-%s.png" % (current_page, xref))
            else:                # CMYK: convert to RGB first
                pix1 = fitz.Pixmap(fitz.csRGB, pix)
                pix1.writePNG("page%s-%s.png" % (current_page, xref))
                pix1 = None
            pix = None
    

    Al ejecutar este script de Python en un PDF de 400 páginas, extrajo 117 imágenes en menos de 3 segundos, lo cual es asombroso. Las imágenes individuales se almacenan en formato PNG. Para mantener el formato y tamaño de la imagen original, en lugar de convertir a PNG, eche un vistazo a las versiones extendidas de los scripts en el Wiki de PyMuPDF.

    Fig.3: Imágenes extraídas

    División de archivos PDF en páginas con PyPDF2

    Para este ejemplo, tanto el PdfFileReader y el PdfFileWriter las clases primero deben importarse. Luego abrimos el archivo PDF, creamos un objeto lector y recorremos todas las páginas usando el objeto lector getNumPages método.

    Dentro del for bucle, creamos una nueva instancia de PdfFileWriter, que aún no contiene ninguna página. Luego agregamos la página actual a nuestro objeto escritor usando el pdfWriter.addPage() método. Este método acepta un objeto de página, que obtenemos usando el PdfFileReader.getPage() método.

    El siguiente paso es crear un nombre de archivo único, lo que hacemos usando el nombre del archivo original más la palabra “página”, más el número de página. Agregamos 1 al número de página actual porque PyPDF2 cuenta los números de página que comienzan en cero.

    Finalmente, abrimos el nuevo nombre de archivo en modo “escribir binario” (modo wb), y use el write() método del pdfWriter class para guardar la página extraída en el disco.

    Listado 4: División de un PDF en páginas individuales.

    #!/usr/bin/python
    
    from PyPDF2 import PdfFileReader, PdfFileWriter
    
    pdf_document = "example.pdf"
    pdf = PdfFileReader(pdf_document)
    
    for page in range(pdf.getNumPages()):
        pdf_writer = PdfFileWriter
        current_page = pdf.getPage(page)
        pdf_writer.addPage(current_page)
    
        outputFilename = "example-page-{}.pdf".format(page + 1)
        with open(outputFilename, "wb") as out:
            pdf_writer.write(out)
    
            print("created", outputFilename)
    

    Fig.4: División de un PDF

    Buscar todas las páginas que contienen texto

    Este caso de uso es bastante práctico y funciona de manera similar a pdfgrep. Usando PyMuPDF, el script devuelve todos los números de página que contienen la cadena de búsqueda dada. Las páginas se cargan una tras otra, y con la ayuda del searchFor() método se detectan todas las ocurrencias de la cadena de búsqueda. En caso de una coincidencia, se imprime el mensaje correspondiente stdout.

    Listado 5: Busque un texto dado.

    #!/usr/bin/python
    
    import fitz
    
    filename = "example.pdf"
    search_term = "invoice"
    pdf_document = fitz.open(filename):
    
    for current_page in range(len(pdf_document)):
        page = pdf_document.loadPage(current_page)
        if page.searchFor(search_term):
            print("%s found on page %i" % (search_term, current_page))
    

    La Figura 5 a continuación muestra el resultado de la búsqueda del término “Debian GNU / Linux” en un libro de 400 páginas.

    Fig.5: Búsqueda de un documento PDF

    Conclusión

    Los métodos que se muestran aquí son bastante poderosos. Con un número comparativamente pequeño de líneas de código, se obtiene fácilmente un resultado. Se examinan más casos de uso en la Parte Dos (¡próximamente!) Que cubre cómo agregar una marca de agua a un PDF.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *