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 *