sábado, 10 de abril de 2021

Modificar tabla de propiedades en un PDF con PyMuPDF

Este post es para explicar de manera breve la forma de usar la librería PyMuPDF en Python para modificar la tabla de propiedades de un archivo PDF. Aquí la demostración inicial:


 Podemos ver entonces que nuestro lo que nuestro código de muestra en Python nos permite. Podemos caracterizar sus líneas de forma resumida así:

import fitz
fileName = "c:/Coding Samples/Python/demoYT/myTestDoc.pdf"
doc=fitz.open(fileName)

Al importar la librería fitz nos estamos refiriendo a PyMuPDF y es la que nos permitirá hacer la respectiva modificación de la tabla de propiedades de nuestro archivo PDF. La variable fileName la hemos creado para darle estética y una forma más resumida a la línea en la que se declara el objeto PyMuPDF, es decir en doc=fitz.open(fileName).

Procedemos entonces a la visualización de la tabla de propiedades actual de nuestro archivo PDF con las siguientes líneas:

print("Previo a la consulta...")
print(doc.metadata)
doc.set_metadata({})#Ejecutamos RESET de tabla de propiedades
print("=====")
print("Después de la modificación o RESET de tabla de propiedades...")
print(doc.metadata) #Visualizar tabla de propiedades en blanco

Al ejecutar estas líneas y de acuerdo a la imagen de muestra del inicio de este artículo obtenemos una salida como la siguiente:

Previo a la consulta...
{'format': 'PDF 1.5', 'title': '', 'author': '', 'subject': '', 'keywords': '', 'creator': 'Microsoft® Word 2010', 'producer': 'Microsoft® Word 2010', 'creationDate': "D:20210409214856-05'00'", 'modDate': "D:20210409214856-05'00'", 'trapped': '', 'encryption': None}
=====
Después de la modificación o RESET de tabla de propiedades...
{'format': 'PDF 1.5', 'title': '', 'author': '', 'subject': '', 'keywords': '', 'creator': '', 'producer': '', 'creationDate': '', 'modDate': '', 'trapped': '', 'encryption': None}

Puede verse entonces que la tabla de propiedades consiste en un diccionario y se puede visualizar a partir del atributo metadata que contiene nuestro objeto PyMuPDF con la siguiente línea print(doc.metadata) y acto seguio la línea doc.set_metadata({}) que la usamos en el código para restablecer la tabla de propiedades de nuestro documentos a valores en blanco.

Ya para finalizar nuestra modificación de la tabla de datos, procedemos a crear las variables tipo string con las que cargaremos los nuevos valores del diccionario para el metadata de nuestro documento de prueba PDF y guardar los cambios en un nuevo archivo en el que quedarán reflejados los cambios.

#Agregamos una tabla de propiedades personalizadas
#Definiendo variables tipo string para hacer presentable el diccionario
mytitle="Documento de prueba demostración METADATA"
myformat="PDF 1.5"
meauthor="EVD Click"
mysubject="Code Programming Demo"
mykeywords="Manuales, demostración, puntos de prueba, ensayos"
myapp='Data Center'
#Cargamos la nueva tabla de propiedades
doc.set_metadata({'format': myformat,
                  'title': mytitle,
                  'author': meauthor,
                  'subject': mysubject,
                  'keywords': mykeywords,
                  'creator': myapp,
                  'producer': 'PyMuPDF',
                  'creationDate': '20130917',
                  'modDate': '20210410',
                  'trapped': '',
                  'encryption': None})
#Y guardamos los cambios en un nuevo archivo
doc.save("c:/Coding Samples/Python/demoYT/myNewMetaData.pdf", garbage = 4)
doc.close()
print("Guardado y revise propiedades en nuevo archivo")

Al usar el método save() para el documento, es necesario asignarlos a un nuevo archivo y luego usamos el método close() para liberarlo de la memoria RAM y que esté disponible para otras aplicaciones.

Ya para finalizar la publicación, he aquí el código completo para modificar la tabla de propiedades de un archivo PDF. Quedan eso sí, otros detalles por tener en cuenta como es el caso de si el archivo está encriptado o si necesitamos borrar el archivo anterior y renombrar nuestro nuevo archivo con el nombre original, cuya información está documentada en otros tutoriales y no quiero incurrir en duplicarla más de lo necesario.

#https://pymupdf.readthedocs.io/en/latest/document.html#Document.metadata
import fitz
fileName = "c:/Coding Samples/Python/demoYT/myTestDoc.pdf"
doc=fitz.open(fileName)
print("Previo a la consulta...")
print(doc.metadata)
doc.set_metadata({})#Ejecutamos RESET de tabla de propiedades
print("=====")
print("Después de la modificación o RESET de tabla de propiedades...")
print(doc.metadata)
#Agregamos una tabla de propiedades personalizadas
#Definiendo variables tipo string para hacer presentable el diccionario
mytitle="Documento de prueba demostración METADATA"
myformat="PDF 1.5"
meauthor="EVD Click"
mysubject="Code Programming Demo"
mykeywords="Manuales, demostración, puntos de prueba, ensayos"
myapp='Data Center'
#Cargamos la nueva tabla de propiedades
doc.set_metadata({'format': myformat,
                  'title': mytitle,
                  'author': meauthor,
                  'subject': mysubject,
                  'keywords': mykeywords,
                  'creator': myapp,
                  'producer': 'PyMuPDF',
                  'creationDate': '20130917',
                  'modDate': '20210410',
                  'trapped': '',
                  'encryption': None})
#Y guardamos los cambios en un nuevo archivo
doc.save("c:/Coding Samples/Python/demoYT/myNewMetaData.pdf", garbage = 4)
doc.close()
print("Guardado y revise propiedades en nuevo archivo")

jueves, 8 de abril de 2021

Wordcloud simple con python usando variable tipo texto

Fuente original:  https://towardsdatascience.com/simple-wordcloud-in-python-2ae54a9f58e5

La idea de wordcloud o "nube de palabras" se basa en una técnica de visualización de palabras en un texto de acuerdo a la frecuencia con que aparecen en el mismo. Aunque el ejemplo original citado en la fuente se refiere a textos que se consultan en la Internet, para efectos de este post se busca entender lo mismo a partir de una variable y luego un archivo de texto.

En los requisitos plantearemos entonces:

1. Python: Instalar una versión reciente de Python, es decir versión 3 o superior. Se requieren las librerías wordcloud, PIL (para aplicar la nube de palabras a la forma de una imagen PNG).

from wordcloud import WordCloud, STOPWORDS
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

2. Datos: Inicialmente una variable en forma de texto para demostrar y luego un archivo de texto

3. Nube de palabras: El concepto final de este post en términos demostrativos.

Se comienza definiendo una función para lanzar la nube de palabras:

def plot_cloud(wordcloud):
  print("Nube de palabras generada!")
  plt.figure(figsize=(20,20)) 
 #Set figure size (ancho x largo en pulgadas)
  plt.imshow(wordcloud)        
#Display image
  plt.axis("off");            
 #No axis details
  plt.show()                   #Show the plot image

Luego procedemos a definir una variable tipo texto y separada por     para iniciar con el concepto:

texto= "Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza nube, nube palabras, ola nube ola ola ola ola , ola, ola, ola, palabras, palabras"

En este sentido ya tenemos la materia prima para definir la nube de palabras, por lo que necesitamos solamente definir el objeto tipo wordcloud así:

wordcloud = WordCloud(width=640, height=480, random_state=1,
                      background_color='black', colormap='Set2',
                      collocations=False,
                      stopwords=STOPWORDS).generate(texto)

Y ya con esta definición entenderemos las propiedades o atributos de este objeto wordcloud definidos de la siguiente manera:

  • width/height: Hace referencia a las dimensiones finales del wordcloud generado. Esto es Ancho/Alto en número de pixeles. 1pixel = 0.2645833mm.
  • random_state: Se ajusta a un valor de 1 con el fin de asegurar que la nube de palabras generada sea repetitiva. Se puede jugar o probar con valores distintos hasta encontrar el de su preferencia.
  • background_color: Los colores black y white son los más usados pero en la página de colores para TKinter encuentra una lista completa para su preferencia.
  • colormap: Con este argumento puede escoger una paleta de colores en la cual se distribuirá la nube de palabras generada. Puede encontrar una lista completa en el mapa de colores de matplotlib.
  • collocations: Este valor se debe poner en False para evitar que en la nube de palabras parezca como si tuviera duplicados. En caso contrario verás palabras como 'web', 'scrapping' y 'web scrapping' como un set dentro de la misma nube de palabras.
  • stopwords: Es la lista de palabras anexadas que no ameritan importancia dentro del conteo para visualización por frecuencia. Por ejemplo: 'nosotros', 'los', 'las', etc. Son palabras innecesarias para un wordcloud. La lista de palabras incluidas en stopwords se pueden visualizar en código con print(STOPWORDS) y se le puede agregar en código mediante STOPWORDS.update(['palabra1', 'palabra2', 'los', 'las'])

Y con ello estamos así listos para generar nuestro wordcloud con la siguiente línea:

plot_cloud(wordcloud)

El resultado es como el de la siguiente imagen:


Para finalizar la primera parte de esta publicación presentamos a continuación el código completo:

from wordcloud import WordCloud, STOPWORDS
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

def plot_cloud(wordcloud):
  print("Nube de palabras generada!")
  plt.figure(figsize=(10,10))  #Set figure size in inches weight height
  plt.imshow(wordcloud)        #Display image
  plt.axis("off");             #No axis details
  plt.show()                   #Show the plot image

text = "Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza Liza nube, nube palabras, ola nube ola ola ola ola , ola, ola, ola, palabras, palabras"

wordcloud = WordCloud(width=640, height=480, random_state=1,
                      background_color='black', colormap='Set2',
                      collocations=False, stopwords=STOPWORDS).generate(text)

plot_cloud(wordcloud)


miércoles, 7 de abril de 2021

Modificar tabla de propiedades en un PDF con PyMuPDF

Este post es para explicar de manera breve la forma de usar la librería PyMuPDF en Python para modificar la tabla de propiedades de un archi...