Cómo extraer texto, enlaces e imágenes de archivos PDF usando Python

Python es un lenguaje muy versátil y los desarrolladores de Python a menudo tienen que trabajar con una variedad de archivos y almacenar información en ellos para su procesamiento. Un formato de archivo popular que seguramente encontrará como desarrollador de Python es el formato de documento portátil conocido popularmente como PDF.

Los archivos PDF pueden contener texto, imágenes y enlaces. Al procesar datos en un programa Python, es posible que necesite extraer los datos almacenados en un documento PDF. A diferencia de las estructuras de datos como tuplas, listas y diccionarios, almacenar información en un documento PDF puede parecer algo difícil.

Afortunadamente, existen varias bibliotecas que facilitan el trabajo con archivos PDF y la extracción de los datos almacenados en archivos PDF. Para conocer estas diferentes bibliotecas, veamos cómo puede extraer textos, enlaces e imágenes de archivos PDF. Para seguir adelante, descargue el siguiente archivo PDF y guárdelo en el mismo directorio que su archivo de programa Python.

Para extraer texto de archivos PDF usando Python, usaremos el PyPDF2 biblioteca. PyPDF2 es una biblioteca Python gratuita y de código abierto que se puede utilizar para fusionar, recortar y transformar páginas de archivos PDF. Puede agregar datos personalizados, opciones de visualización y contraseñas a archivos PDF. Sin embargo, es importante destacar que PyPDF2 puede recuperar texto de archivos PDF.

Para usar PyPDF2 para extraer texto de archivos PDF, instálelo usando pip, que es un instalador de paquetes para Python. pip le permite instalar diferentes paquetes de Python en su máquina:

1. Verifique si ya tiene pip instalado ejecutando:

pip --version

Si no obtiene un número de versión, significa que pip no está instalado.

2. Para instalar pip, haga clic en obtener pipa para descargar su script de instalación.

El enlace abre una página con el script para instalar pip como se muestra a continuación:

Haga clic derecho en la página y haga clic en Guardar como para guardar el archivo. Por defecto, el nombre del archivo es get-pip.py

Abra la terminal y navegue hasta el directorio con el archivo get-pip.py que acaba de descargar y luego ejecute el comando:

sudo python3 get-pip.py

Esto debería instalar pip como se muestra a continuación:

3. Verifique que pip se haya instalado correctamente ejecutando:

pip --version

Si tiene éxito, debería obtener un número de versión:

Con pip instalado, ahora podemos empezar a trabajar con PyPDF2.

1. Instale PyPDF2 ejecutando el siguiente comando en la terminal:

pip install PyPDF2

2. Cree un archivo Python e importe PdfReader desde PyPDF2 usando la siguiente línea:

from PyPDF2 import PdfReader

La biblioteca PyPDF2 ofrece una variedad de clases para trabajar con archivos PDF. Una de esas clases es PdfReader, que se puede utilizar para abrir archivos PDF, leer el contenido y extraer texto de archivos PDF, entre otras cosas.

3. Para comenzar a trabajar con un archivo PDF, primero debe abrir el archivo. Para hacer esto, cree una instancia de la clase PdfReader y pase el archivo PDF con el que desea trabajar:

reader = PdfReader('games.pdf')

La línea anterior crea una instancia de PdfReader y lo prepara para acceder al contenido del archivo PDF que especifique. La instancia se almacena en una variable llamada lector, que tendrá que acceder a una variedad de métodos y propiedades disponibles en la clase PdfReader.

4. Para ver si todo funciona bien, imprima la cantidad de páginas del PDF que ingresó usando el siguiente código:

print(len(reader.pages))

Producción:

5

5. Dado que nuestro archivo PDF tiene 5 páginas, podemos acceder a cada página disponible en el PDF. Sin embargo, el conteo comienza desde 0, al igual que la convención de indexación de Python. Por lo tanto, la primera página del archivo pdf será la página número 0. Para recuperar la primera página del PDF, agregue la siguiente línea a su código:

page1 = reader.pages[0]

La línea anterior recupera la primera página del archivo PDF y la almacena en una variable denominada página1.

6. Para extraer el texto de la primera página del archivo PDF, agregue la siguiente línea:

textPage1 = page1.extract_text()

Esto extrae el texto de la primera página del PDF y almacena el contenido en una variable denominada textPage1. De este modo, tendrá acceso al texto de la primera página del archivo PDF a través de la variable textPage1.

7. Para confirmar que el texto se extrajo correctamente, puede imprimir el contenido de la variable textPage1. Nuestro código completo, que también imprime el texto en la primera página del archivo PDF, se muestra a continuación:

# import the PdfReader class from PyPDF2
from PyPDF2 import PdfReader

# create an instance of the PdfReader class
reader = PdfReader('games.pdf')

# get the number of pages available in the pdf file
print(len(reader.pages))

# access the first page in the pdf
page1 = reader.pages[0]

# extract the text in page 1 of the pdf file
textPage1 = page1.extract_text()

# print out the extracted text
print(textPage1)

Producción:

Para extraer enlaces de archivos PDF, vamos a PyMuPDF, que es una biblioteca de Python para extraer, analizar, convertir y manipular los datos almacenados en documentos como los PDF. Para usar PyMuPDF, debes tener Python 3.8 o posterior. Para empezar:

1. Instale PyMuPDF ejecutando la siguiente línea en la terminal:

pip install PyMuPDF

2. Importe PyMuPDF a su archivo Python usando la siguiente declaración:

import fitz

3. Para acceder al PDF del que desea extraer enlaces, primero debe abrirlo. Para abrirlo, ingrese la siguiente línea:

doc = fitz.open("games.pdf")

4. Habiendo abierto el archivo PDF, imprima el número de páginas del PDF usando la siguiente línea:

print(doc.page_count)

Producción:

5

4. Para extraer enlaces de una página en el archivo PDF, debemos cargar la página de la que queremos extraer enlaces. Para cargar una página, ingrese la siguiente línea, donde ingresa el número de página que desea cargar en una función llamada load_page()

page = doc.load_page(0)

Para extraer enlaces de la primera página, pasamos 0 (cero). El recuento de páginas comienza desde cero al igual que en estructuras de datos como matrices y diccionarios.

5. Extraiga los enlaces de la página usando la siguiente línea:

links = page.get_links()

Todos los enlaces en la página que especificaste, en nuestro caso, la página 1, serán extraídos y almacenados en la variable llamada enlaces.

6. Para ver el contenido de la variable de enlaces, imprímalo así:

print(links)

Producción:

En el resultado impreso, observe que los enlaces de variables contienen una lista de diccionarios con pares clave-valor. Cada enlace de la página está representado por un diccionario, y el enlace real se almacena bajo la clave «uri».

7. Para obtener los enlaces de la lista de objetos almacenados bajo los enlaces de nombre de variable, recorra la lista usando una instrucción for in e imprima los enlaces específicos almacenados bajo la clave uri. El código completo que hace esto se muestra a continuación:

import fitz

# Open the PDF file
doc = fitz.open("games.pdf")

# Print out the number of pages
print(doc.page_count)

# load the first page from the PDF
page = doc.load_page(0)

# extract all links from the page and store it under - links
links = page.get_links()

# print the links object
#print(links) 

# print the actual links stored under the key "uri"
for obj in links:
  print(obj["uri"])

Producción:

5
https://www.statista.com/statistics/1292243/software-developers-average-age-when-first-coding/
https://sparkian.com/
https://www.codemonkey.com/

8. Para hacer que nuestro código sea más reutilizable, podemos refactorizarlo definiendo una función para extraer todos los enlaces en un PDF y una función para imprimir todos los enlaces que se encuentran en un PDF. De esta manera, puede llamar a las funciones con cualquier PDF y recuperará todos los enlaces en el PDF. El código que hace esto se muestra a continuación:

import fitz

# Extract all the links in a PDF document
def extract_link(path_to_pdf):
  links = []
  doc = fitz.open(path_to_pdf)

  for page_num in range(doc.page_count):
    page = doc.load_page(page_num)
    page_links = page.get_links()
    links.extend(page_links)
  return links

# print out all the links returned from the PDF document
def print_all_links(links):
  for link in links:
    print(link["uri"])

# Call the function to extract all the links in a pdf
# all the return links are stored under all_links
all_links = extract_link("games.pdf")

# call the function to print all links in the PDF
print_all_links(all_links)

Producción:

https://www.statista.com/statistics/1292243/software-developers-average-age-when-first-coding/
https://sparkian.com/
https://www.codemonkey.com/
https://scratch.mit.edu/
https://www.tynker.com/
https://codecombat.com/
https://lightbot.com/
https://sparkian.com

Del código anterior, la función extract_link() recibe un archivo PDF, recorre en iteración todas las páginas del PDF, extrae todos los enlaces y los devuelve. El resultado de esta función se almacena en una variable llamada all_links

La función print_all_links() toma el resultado de extract_link(), recorre la lista e imprime todos los enlaces reales que se encuentran en el PDF que pasó a la función extract_link().

Para extraer imágenes de un PDF, seguiremos usando PyMuPDF. Para extraer imágenes de un archivo PDF:

1. Importe PyMuPDF, io y PIL. Python Imaging Library (PIL) proporciona herramientas que facilitan la creación y el almacenamiento de imágenes, entre otras funciones. io proporciona clases para un manejo fácil y eficiente de datos binarios.

import fitz
from io import BytesIO
from PIL import Image

2. Abra el archivo PDF del que desea extraer imágenes:

doc = fitz.open("games.pdf")

3. Cargue la página de la que desea extraer imágenes:

page = doc.load_page(0)

4. PyMuPdf identifica imágenes en un archivo PDF utilizando un número de referencia cruzada (xref), que suele ser un número entero. Cada imagen de un archivo PDF tiene una referencia externa única. Por lo tanto, para extraer una imagen de un PDF, primero tenemos que obtener el número xref que la identifica. Para obtener el número de referencia externa de las imágenes en una página, usamos la función get_images() así:

image_xref = page.get_images()
print(image_xref)

Producción:

[(7, 0, 699, 407, 8, 'DeviceRGB', '', 'X7', 'FlateDecode')]

get_images() devuelve una lista de tuplas con información sobre la imagen. Como solo tenemos una imagen en la primera página, solo hay una tupla. El primer elemento de la tupla representa la referencia externa de la imagen en la página. Por lo tanto, la referencia externa de la imagen de la primera página es 7.

5. Para extraer el valor xref de la imagen de la lista de tuplas, utilizamos el siguiente código:

# get xref value of the image
xref_value = image_xref[0][0]
print(xref_value)

Producción:

[(7, 0, 699, 407, 8, 'DeviceRGB', '', 'X7', 'FlateDecode')]
7

6. Como ahora tiene la referencia externa que identifica una imagen en el PDF, puede extraer la imagen usando la función extract_image() de esta manera:

img_dictionary = doc.extract_image(xref_value)

Esta función, sin embargo, no devuelve la imagen real. En su lugar, devuelve un diccionario que contiene los datos binarios de la imagen y los metadatos sobre la imagen, entre otras cosas.

7. Desde el diccionario devuelto por la función extract_image(), verifique la extensión del archivo de la imagen extraída. La extensión del archivo se almacena bajo la clave «ext»:

# get file extenstion
img_extension = img_dictionary["ext"]
print(img_extension)

Producción:

png

8. Extraiga los binarios de imágenes del diccionario almacenado en img_dictionary. Los binarios de las imágenes se almacenan bajo la clave «imagen».

# get the actual image binary data
img_binary = img_dictionary["image"]

9. Cree un objeto BytesIO e inicialícelo con los datos de la imagen binaria que representa la imagen. Esto crea un objeto similar a un archivo que puede ser procesado por bibliotecas de Python como PIL para que pueda guardar la imagen.

# create a BytesIO object to work with the image bytes
image_io = BytesIO(img_binary)

10. Abra y analice los datos de imagen almacenados en el objeto BytesIO llamado image_io usando la biblioteca PIL. Esto es importante ya que permite que la biblioteca PIL determine el formato de imagen de la imagen con la que está intentando trabajar, en este caso, un PNG. Después de detectar el formato de la imagen, PIL crea un objeto de imagen que se puede manipular con funciones y métodos de PIL, como el método save(), para guardar la imagen en el almacenamiento local.

# open the image using Pillow
image = Image.open(image_io)

11. Especifique la ruta donde desea guardar la imagen.

output_path = "image_1.png"

Dado que la ruta anterior contiene solo el nombre del archivo con su extensión, la imagen extraída se guardará en el mismo directorio que el archivo Python que contiene este programa. La imagen se guardará como image_1.png. La extensión PNG es importante para que coincida con la extensión original de la imagen.

12. Guarde la imagen y cierre el objeto ByteIO.

# save the image
image.save(output_path)

# Close the BytesIO object 
image_io.close()

El código completo para extraer una imagen de un archivo PDF se muestra a continuación:

import fitz
from io import BytesIO
from PIL import Image

doc = fitz.open("games.pdf")
page = doc.load_page(0)

# get a cross reference(xref) to the image
image_xref = page.get_images()

# get the actual xref value of the image
xref_value = image_xref[0][0]

# extract the image
img_dictionary = doc.extract_image(xref_value)

# get file extenstion
img_extension = img_dictionary["ext"]

# get the actual image binary data
img_binary = img_dictionary["image"]

# create a BytesIO object to work with the image bytes
image_io = BytesIO(img_binary)

# open the image using PIL library 
image = Image.open(image_io)

#specify the path where you want to save the image
output_path = "image_1.png"

# save the image
image.save(output_path)

# Close the BytesIO object 
image_io.close()

Ejecute el código y vaya a la carpeta que contiene su archivo Python; Deberías ver la imagen extraída llamada image_1.png, como se muestra a continuación:

Conclusión

Para practicar más la extracción de enlaces, imágenes y textos de archivos PDF, intente refactorizar el código de los ejemplos para hacerlos más reutilizables, como se muestra en el ejemplo de enlaces. De esta manera, solo necesitará pasar un archivo PDF y su programa Python extraerá todos los enlaces, imágenes o texto del PDF completo. ¡Feliz codificación!

También puede explorar algunas de las mejores API de PDF para cada necesidad empresarial.