====== Trabajar en Python con PDF ======
Los PDFs son documentos binarios que albergan una gran cantidad de información, y que son mucho más complejos que los documentos de texto plano.\\
Para trabajar con documentos PDF desde Python se usará el módulo PyPDF2. Es un módulo qde terceros que hay que instalar, en estas notas se usará la versión 1.26.0: **pip install --user PyPDF2==1.26.0**\\
\\
El formato PDF es muy particular y cabe la posibilidad que se produzcan fallos a la hora de extraer texto. Es algo que hay que tener en cuenta y que es inevitable.
===== Extraer texto de PDF =====
El módulo PyPDF2 no tiene ninguna función para extraer elementos multimedia, pero puede extraer texto y retornarlo a Python como un string.\\
\\
Los pasos para extraer texto de un pdf son los siguientes:
- Importar el módulo PyPDF2.
- Abrimos el documento PDF con **open()**, que devuelve un objeto tipo pdfFileObj:
- El primer argumento es el nombre del propio documento.
- El segundo argumento es 'rb': lectura en modo binario.
- A continuación, usamos el método PyPDF.**FileReader()**, al que se le pasa como argumento el objeto pdfFileObj obtenido anteriormente, para obtener un objeto pdfReader que representa el documento PDF leíble.
- Podemos obtener el número de páginas del documento con el atributo pdfReader**.numPages**.
- Para extraer el texto debemos obtener la página del texto a extraer, usando el método objetoPdfReader**.getPage()**, pasando como argumento el número de página (la primera responde al índice 0 en lugar de 1). El objeto obtenido es de tipo pageObj.
- Con el último objeto obtenido, usamos el método objetoPageObj.**extractText()** para extrer un string con el texto completo de la página.
import PyPDF2
docPdf = open('miDocumento.pdf', 'rb')
docPdfLeible = PyPDF2.PdfFileReader(docPdf)
docPdfLeible.numpages # Devuelve el número de páginas del PDF
paginaPDF = docPdfLeible.getPage(3) # Extraemos la página 4 de la que queremos obtener el texto.
textoPDF = paginaPDF.extractText()
# ... # Cosas que hacer con el texto
docPdf.close()
===== Desencriptar PDFs =====
Spoiler: Hay que conocer la contraseña con la que han sido encriptados. Lógicamente.\\
\\
- Abrir el documento y obtener el objeto que lo hace leíble: import PyPDF2
docPdf = pyPDF2.PdfFileReader(open('DocumentoEncriptado.pdf', 'rb'))
- Para comprobar si el documento está encriptado, podemos comprobar el atributo **.isEncrypted**:docPdf.isEncrypted # True
- Desencriptamos con la función decrypt('//contraseña//'). Si el documento se desencripta correctamente, devuelve 1. docPdf.decrypt('//contraseña//')
- Una vez desencriptado el documento, extraemos la página.pagina = docPdf.getPage(0)
Debido a un //bug// en la versión 1.26.0 de PyDF2, se produce un error //IndexError: list index out of range// cuando se llama a getPage(), si ésta ha sido llamada anteriormente, antes de decrypt(). Si se diese el Caso, para evitar ese error, es necesario volver a abrir el documento.
===== Crear PDFs =====
PyPDF2 no permite crear PDSFs editándolos manualmente. Lo que hace es crear un PDF, a aprtir de pegar, rotar, sobreponer o encriptar otros PDFs:\\
- Abrir los archivos PDF de los que se extraerá la información, obteniendo los objetos PdfFileReader correspondientes.
- Crear un nuevo objeto tipo PdfFileWriter.
- Copiar las págins que nos interesen de los objetos abiertos, al objeto PdfFileWriter.
- Usar éste último para escribir en el PDF.
==== Copiar páginas ====
- Se abren los PDFs de los que se copiarán las páginas en modo 'rb'.
- Obtenemos los objetos leíbles de los documentos abiertos anteriormente con la función PyPDF2.PdfFileReader(//Objeto_pdf_abierto//)
- Creamos el objeto tipo //PdfFileWriter// que creará el nuevo PDF con el método **PyPDF2.PdfFileWriter()**.
- Añadimos al objeto tipo PdfFileWriter las páginas de cada PDF con la función pagina=objeto_pdf_abierto.getPage(pageNum), con **pdfWriter.addPage(pagina)**.
- Para crear definitivamente el nuevo PDF, abrimos el nuevo PDF hasta ahora inexistente, con open() e indicando en el segundo argumento 'wb'. nuevoPDF = open('nuevo.pdf', 'wb')
- Se pasa como argumento del método **pdfWriter.write(nuevoPDF)**, que copia al información contenida en este (páginas copiadas de los otros PDFs).
- Se cierra con close() el documento creado y el resto de documentos abiertos.
==== Rotar páginas ====
Del mismo modo que antes, cuando se extrae la página a copiar, se la aplica el método //pagina//**.rotateClockwise(//nº_grados_rotación//)**.
\\
Continuaría igual: Creando un nuevo PDF y escribiendo las págias rotadas.
==== Sobreponiendo páginas ====
Útil, por ejemplo, para añadir marcas de agua.\\
La metodología es la misma que anteriormente: Una vez se han abierto las 2 páginas a unir, se utiliza el método **merge()** de la que va a ser "sobrepuesta" (queda debajo). primeraPagina**.mergePage(**pdfMarcaAguaReader.getPage(0)**)**
===== Encriptación de PDFs =====
Una vez se le han añadido todas las páginas al objeto pdfWriter, se encripta con: pdfWriter**.encrypt(**//clave//**)**.\\
El método encrypt() permite tener 2 argumentos: el primero es el //user password// (sólo permite ver el PDF) y el segundo el //owner password// (permite realizar otras acciones, como por ejemplo, extraer texto). Si sólo se pasa una clave, se usa para ambos usuarios.\\
Después el siguiente paso es crear el PDF, como se vió anteriormente.