Descargue un PDF para obtener información detallada sobre cada carácter de texto, rectángulo y línea. Además: extracción de tablas y depuración visual.
Funciona mejor en archivos PDF generados por máquina, en lugar de escaneados. Construido en pdfminer.six
.
Actualmente probado en Python 3.8, 3.9, 3.10, 3.11.
Las traducciones de este documento están disponibles en: chino (por @hbh112233abc).
Para informar un error o solicitar una función, presente un problema. Para hacer una pregunta o solicitar ayuda con un PDF específico, utilice el foro de discusión.
pip install pdfplumber
curl " https://raw.githubusercontent.com/jsvine/pdfplumber/stable/examples/pdfs/background-checks.pdf " > background-checks.pdf
pdfplumber < background-checks.pdf > background-checks.csv
El resultado será un CSV que contendrá información sobre cada carácter, línea y rectángulo del PDF.
Argumento | Descripción |
---|---|
--format [format] | csv o json . El formato json devuelve más información; incluye metadatos a nivel de PDF y de página, además de atributos anidados en el diccionario. |
--pages [list of pages] | Una lista de páginas indexadas en 1 y delimitadas por espacios o rangos de páginas con guiones. Por ejemplo, 1, 11-15 , que devolvería datos de las páginas 1, 11, 12, 13, 14 y 15. |
--types [list of object types to extract] | Las opciones son char , rect , line , curve , image , annot , etcétera. El valor predeterminado es todos los disponibles. |
--laparams | Una cadena con formato JSON (por ejemplo, '{"detect_vertical": true}' ) para pasar a pdfplumber.open(..., laparams=...) . |
--precision [integer] | El número de decimales para redondear números de punto flotante. El valor predeterminado es sin redondeo. |
import pdfplumber
with pdfplumber . open ( "path/to/file.pdf" ) as pdf :
first_page = pdf . pages [ 0 ]
print ( first_page . chars [ 0 ])
Para comenzar a trabajar con un PDF, llame a pdfplumber.open(x)
, donde x
puede ser:
El método open
devuelve una instancia de la clase pdfplumber.PDF
.
Para cargar un PDF protegido con contraseña, pase el argumento de la palabra clave password
, por ejemplo, pdfplumber.open("file.pdf", password = "test")
.
Para configurar los parámetros de análisis de diseño para el motor de diseño de pdfminer.six
, pase el argumento de la palabra clave laparams
, por ejemplo, pdfplumber.open("file.pdf", laparams = { "line_overlap": 0.7 })
.
Para normalizar previamente el texto Unicode, pase unicode_norm=...
, donde ...
es una de las cuatro formas de normalización Unicode: "NFC"
, "NFD"
, "NFKC"
o "NFKD"
.
Los valores de metadatos no válidos se tratan como una advertencia de forma predeterminada. Si no es así, pase strict_metadata=True
al método open
y pdfplumber.open
generará una excepción si no puede analizar los metadatos.
pdfplumber.PDF
La clase pdfplumber.PDF
de nivel superior representa un único PDF y tiene dos propiedades principales:
Propiedad | Descripción |
---|---|
.metadata | Un diccionario de pares clave/valor de metadatos, extraído de los avances Info del PDF. Normalmente incluye "CreationDate", "ModDate", "Producer", etc. |
.pages | Una lista que contiene una instancia pdfplumber.Page por página cargada. |
... y además tiene el siguiente método:
Método | Descripción |
---|---|
.close() | Llamar a este método llama Page.close() en cada página y también cierra la secuencia del archivo (excepto en los casos en que la secuencia es externa, es decir, ya está abierta y pasada directamente a pdfplumber ). |
pdfplumber.Page
La clase pdfplumber.Page
es el núcleo de pdfplumber
. La mayoría de las cosas que harás con pdfplumber
girarán en torno a esta clase. Tiene estas propiedades principales:
Propiedad | Descripción |
---|---|
.page_number | El número de página secuencial, comenzando con 1 para la primera página, 2 para la segunda, y así sucesivamente. |
.width | El ancho de la página. |
.height | La altura de la página. |
.objects / .chars / .lines / .rects / .curves / .images | Cada una de estas propiedades es una lista, y cada lista contiene un diccionario para cada objeto incrustado en la página. Para obtener más detalles, consulte "Objetos" a continuación. |
... y estos métodos principales:
Método | Descripción |
---|---|
.crop(bounding_box, relative=False, strict=True) | Devuelve una versión de la página recortada en el cuadro delimitador, que debe expresarse como 4 tuplas con los valores (x0, top, x1, bottom) . Las páginas recortadas retienen objetos que se encuentran al menos parcialmente dentro del cuadro delimitador. Si un objeto se encuentra sólo parcialmente dentro del cuadro, sus dimensiones se cortan para ajustarse al cuadro delimitador. Si relative=True , el cuadro delimitador se calcula como un desplazamiento desde la parte superior izquierda del cuadro delimitador de la página, en lugar de una posición absoluta. (Consulte el número 245 para obtener un ejemplo visual y una explicación). Cuando strict=True (el valor predeterminado), el cuadro delimitador del recorte debe estar completamente dentro del cuadro delimitador de la página. |
.within_bbox(bounding_box, relative=False, strict=True) | Similar a .crop , pero solo retiene los objetos que se encuentran completamente dentro del cuadro delimitador. |
.outside_bbox(bounding_box, relative=False, strict=True) | Similar a .crop y .within_bbox , pero solo retiene los objetos que quedan completamente fuera del cuadro delimitador. |
.filter(test_function) | Devuelve una versión de la página con solo los .objects para los cuales test_function(obj) devuelve True . |
... y además tiene el siguiente método:
Método | Descripción |
---|---|
.close() | De forma predeterminada, los objetos Page almacenan en caché su diseño y la información del objeto para evitar tener que reprocesarlo. Sin embargo, al analizar archivos PDF de gran tamaño, estas propiedades almacenadas en caché pueden requerir mucha memoria. Puede utilizar este método para vaciar el caché y liberar la memoria. |
Los métodos adicionales se describen en las secciones siguientes:
Cada instancia de pdfplumber.PDF
y pdfplumber.Page
proporciona acceso a varios tipos de objetos PDF, todos derivados del análisis de PDF pdfminer.six
. Cada una de las siguientes propiedades devuelve una lista de Python de los objetos coincidentes:
.chars
, cada uno de los cuales representa un único carácter de texto..lines
, cada una de las cuales representa una única línea unidimensional..rects
, cada uno de los cuales representa un único rectángulo bidimensional..curves
, cada una de las cuales representa cualquier serie de puntos conectados que pdfminer.six
no reconoce como una línea o un rectángulo..images
, cada uno de los cuales representa una imagen..annots
, cada uno de los cuales representa una única anotación PDF (consulte la Sección 8.4 de la especificación oficial de PDF para obtener más detalles).hyperlinks
, cada uno de los cuales representa una única anotación PDF del subtipo Link
y tiene un atributo de acción URI
Cada objeto se representa como un simple dict
de Python, con las siguientes propiedades:
char
Propiedad | Descripción |
---|---|
page_number | Número de página en la que se encontró este carácter. |
text | Por ejemplo, "z", o "Z" o " ". |
fontname | Nombre de la fuente del personaje. |
size | Tamaño de fuente. |
adv | Igual al ancho del texto * tamaño de fuente * factor de escala. |
upright | Si el personaje es erguido. |
height | Altura del personaje. |
width | Ancho del personaje. |
x0 | Distancia del lado izquierdo del carácter desde el lado izquierdo de la página. |
x1 | Distancia del lado derecho del carácter desde el lado izquierdo de la página. |
y0 | Distancia entre la parte inferior del carácter y la parte inferior de la página. |
y1 | Distancia entre la parte superior del carácter y la parte inferior de la página. |
top | Distancia entre la parte superior del carácter y la parte superior de la página. |
bottom | Distancia desde la parte inferior del carácter desde la parte superior de la página. |
doctop | Distancia entre la parte superior del carácter y la parte superior del documento. |
matrix | La "matriz de transformación actual" para este personaje. (Consulte a continuación para obtener más detalles). |
mcid | El ID de la sección de contenido marcado para este carácter, si lo hay (de lo contrario, None ). Atributo experimental. |
tag | La etiqueta de la sección de contenido marcada para este personaje, si la hay (de lo contrario, None ). Atributo experimental. |
ncs | TKTK |
stroking_pattern | TKTK |
non_stroking_pattern | TKTK |
stroking_color | El color del contorno del personaje (es decir, trazo). Consulte docs/colors.md para obtener más detalles. |
non_stroking_color | El color interior del personaje. Consulte docs/colors.md para obtener más detalles. |
object_type | "carbonizarse" |
Nota : La propiedad matrix
de un carácter representa la “matriz de transformación actual”, como se describe en la Sección 4.2.2 de la Referencia PDF (6.ª edición). La matriz controla la escala, la inclinación y la traducción posicional del personaje. La rotación es una combinación de escala y desviación, pero en la mayoría de los casos se puede considerar igual a la desviación del eje x. El submódulo pdfplumber.ctm
define una clase, CTM
, que ayuda con estos cálculos. Por ejemplo:
from pdfplumber . ctm import CTM
my_char = pdf . pages [ 0 ]. chars [ 3 ]
my_char_ctm = CTM ( * my_char [ "matrix" ])
my_char_rotation = my_char_ctm . skew_x
line
Propiedad | Descripción |
---|---|
page_number | Número de página en la que se encontró esta línea. |
height | Altura de la línea. |
width | Ancho de línea. |
x0 | Distancia del extremo izquierdo desde el lado izquierdo de la página. |
x1 | Distancia del extremo derecho desde el lado izquierdo de la página. |
y0 | Distancia del extremo inferior desde la parte inferior de la página. |
y1 | Distancia del extremo superior al final de la página. |
top | Distancia desde la parte superior de la línea desde la parte superior de la página. |
bottom | Distancia desde la parte inferior de la línea desde la parte superior de la página. |
doctop | Distancia desde la parte superior de la línea desde la parte superior del documento. |
linewidth | Grosor de línea. |
stroking_color | El color de la línea. Consulte docs/colors.md para obtener más detalles. |
non_stroking_color | El color sin trazo especificado para el trazado de la línea. Consulte docs/colors.md para obtener más detalles. |
mcid | El ID de sección de contenido marcado para esta línea, si corresponde (de lo contrario, None ). Atributo experimental. |
tag | La etiqueta de la sección de contenido marcada para esta línea, si la hay (de lo contrario, None ). Atributo experimental. |
object_type | "línea" |
rect
Propiedad | Descripción |
---|---|
page_number | Número de página en la que se encontró este rectángulo. |
height | Altura del rectángulo. |
width | Ancho del rectángulo. |
x0 | Distancia del lado izquierdo del rectángulo desde el lado izquierdo de la página. |
x1 | Distancia del lado derecho del rectángulo desde el lado izquierdo de la página. |
y0 | Distancia de la parte inferior del rectángulo desde la parte inferior de la página. |
y1 | Distancia desde la parte superior del rectángulo desde la parte inferior de la página. |
top | Distancia desde la parte superior del rectángulo desde la parte superior de la página. |
bottom | Distancia desde la parte inferior del rectángulo desde la parte superior de la página. |
doctop | Distancia desde la parte superior del rectángulo desde la parte superior del documento. |
linewidth | Grosor de línea. |
stroking_color | El color del contorno del rectángulo. Consulte docs/colors.md para obtener más detalles. |
non_stroking_color | El color de relleno del rectángulo. Consulte docs/colors.md para obtener más detalles. |
mcid | El ID de la sección de contenido marcada para este rect, si corresponde (de lo contrario, None ). Atributo experimental. |
tag | La etiqueta de la sección de contenido marcada para este rect, si corresponde (de lo contrario, None ). Atributo experimental. |
object_type | "recto" |
curve
Propiedad | Descripción |
---|---|
page_number | Número de página en la que se encontró esta curva. |
pts | Una lista de tuplas (x, top) que indican los puntos de la curva . |
path | Una lista de tuplas (cmd, *(x, top)) que describen la descripción completa de la ruta , incluidos (por ejemplo) los puntos de control utilizados en las curvas de Bézier. |
height | Altura del cuadro delimitador de la curva. |
width | Ancho del cuadro delimitador de la curva. |
x0 | Distancia del punto más a la izquierda de la curva desde el lado izquierdo de la página. |
x1 | Distancia del punto más a la derecha de la curva desde el lado izquierdo de la página. |
y0 | Distancia del punto más bajo de la curva desde la parte inferior de la página. |
y1 | Distancia del punto más alto de la curva desde la parte inferior de la página. |
top | Distancia del punto más alto de la curva desde la parte superior de la página. |
bottom | Distancia del punto más bajo de la curva desde la parte superior de la página. |
doctop | Distancia del punto más alto de la curva desde la parte superior del documento. |
linewidth | Grosor de línea. |
fill | Si la forma definida por la trayectoria de la curva está rellena. |
stroking_color | El color del contorno de la curva. Consulte docs/colors.md para obtener más detalles. |
non_stroking_color | El color de relleno de la curva. Consulte docs/colors.md para obtener más detalles. |
dash | Una tupla ([dash_array], dash_phase) que describe el estilo de guión de la curva. Consulte la Tabla 4.6 de la especificación PDF para obtener más detalles. |
mcid | El ID de sección de contenido marcado para esta curva, si corresponde (de lo contrario, None ). Atributo experimental. |
tag | La etiqueta de la sección de contenido marcada para esta curva, si la hay (de lo contrario, None ). Atributo experimental. |
object_type | "curva" |
Además, tanto pdfplumber.PDF
como pdfplumber.Page
brindan acceso a varias listas derivadas de objetos: .rect_edges
(que descompone cada rectángulo en sus cuatro líneas), .curve_edges
(que hace lo mismo para objetos curve
) y .edges
(que combina .rect_edges
, .curve_edges
y .lines
).
image
Nota: Aunque la posición y las características de los objetos image
están disponibles a través de pdfplumber
, esta biblioteca no proporciona soporte directo para reconstruir el contenido de la imagen. Para eso, consulte esta sugerencia.
Propiedad | Descripción |
---|---|
page_number | Número de página en la que se encontró la imagen. |
height | Altura de la imagen. |
width | Ancho de la imagen. |
x0 | Distancia del lado izquierdo de la imagen desde el lado izquierdo de la página. |
x1 | Distancia del lado derecho de la imagen desde el lado izquierdo de la página. |
y0 | Distancia desde la parte inferior de la imagen desde la parte inferior de la página. |
y1 | Distancia desde la parte superior de la imagen desde la parte inferior de la página. |
top | Distancia desde la parte superior de la imagen desde la parte superior de la página. |
bottom | Distancia desde la parte inferior de la imagen desde la parte superior de la página. |
doctop | Distancia desde la parte superior del rectángulo desde la parte superior del documento. |
srcsize | Las dimensiones originales de la imagen, como una tupla (width, height) . |
colorspace | Dominio de color de la imagen (p. ej., RGB). |
bits | El número de bits por componente de color; por ejemplo, 8 corresponde a 255 valores posibles para cada componente de color (R, G y B en un espacio de color RGB). |
stream | Valores de píxeles de la imagen, como un objeto pdfminer.pdftypes.PDFStream . |
imagemask | Un booleano que acepta valores NULL; Si es True , "especifica que los datos de la imagen se utilizarán como máscara de plantilla para pintar en el color actual". |
mcid | El ID de la sección de contenido marcado para esta imagen, si corresponde (de lo contrario, None ). Atributo experimental. |
tag | La etiqueta de la sección de contenido marcada para esta imagen, si corresponde (de lo contrario, None ). Atributo experimental. |
object_type | "imagen" |
pdfminer.six
Si pasa el parámetro pdfminer.six
-handling laparams
a pdfplumber.open(...)
, el diccionario .objects
de cada página también contendrá los objetos de diseño de nivel superior de pdfminer.six
, como "textboxhorizontal"
.
Las herramientas de depuración visual de pdfplumber
pueden resultar útiles para comprender la estructura de un PDF y los objetos que se han extraído de él.
PageImage
con .to_image()
Para convertir cualquier página (incluidas las páginas recortadas) en un objeto PageImage
, llame my_page.to_image()
. Opcionalmente, puede pasar uno de los siguientes argumentos de palabras clave:
resolution
: El número deseado de píxeles por pulgada. Predeterminado: 72
. Tipo: int
.width
: El ancho de imagen deseado en píxeles. Valor predeterminado: no configurado, determinado por resolution
. Tipo: int
.height
: el ancho de imagen deseado en píxeles. Valor predeterminado: no configurado, determinado por resolution
. Tipo: int
.antialias
: si se debe utilizar antialiasing al crear la imagen. Establecer en True
crea imágenes con texto y gráficos menos irregulares, pero con tamaños de archivo más grandes. Valor predeterminado: False
. Tipo: bool
.force_mediabox
: utiliza las dimensiones .mediabox
de la página, en lugar de las dimensiones .cropbox
. Valor predeterminado: False
. Tipo: bool
.Por ejemplo:
im = my_pdf . pages [ 0 ]. to_image ( resolution = 150 )
Desde un script o REPL, im.show()
abrirá la imagen en su visor de imágenes local. Pero los objetos PageImage
también funcionan muy bien con los cuadernos Jupyter; se representan automáticamente como salidas de celda. Por ejemplo:
Nota : .to_image(...)
funciona como se esperaba con instancias Page.crop(...)
/ CroppedPage
, pero no puede incorporar cambios realizados a través de instancias Page.filter(...)
/ FilteredPage
.
PageImage
Método | Descripción |
---|---|
im.reset() | Borra todo lo que hayas dibujado hasta ahora. |
im.copy() | Copia la imagen a un nuevo objeto PageImage . |
im.show() | Abre la imagen en su visor de imágenes local. |
im.save(path_or_fileobject, format="PNG", quantize=True, colors=256, bits=8) | Guarda la imagen anotada como un archivo PNG. Los argumentos predeterminados cuantifican la imagen en una paleta de 256 colores, guardando el PNG con una profundidad de color de 8 bits. Puede deshabilitar la cuantificación pasando quantize=False o ajustar el tamaño de la paleta de colores pasando colors=N . |
Puede pasar coordenadas explícitas o cualquier objeto PDF pdfplumber
(por ejemplo, char, line, rect) a estos métodos.
Método de un solo objeto | método a granel | Descripción |
---|---|---|
im.draw_line(line, stroke={color}, stroke_width=1) | im.draw_lines(list_of_lines, **kwargs) | Dibuja una línea a partir de una line , curve o una tupla de dos tuplas (por ejemplo, ((x, y), (x, y)) ). |
im.draw_vline(location, stroke={color}, stroke_width=1) | im.draw_vlines(list_of_locations, **kwargs) | Dibuja una línea vertical en la coordenada x indicada por location . |
im.draw_hline(location, stroke={color}, stroke_width=1) | im.draw_hlines(list_of_locations, **kwargs) | Dibuja una línea horizontal en la coordenada y indicada por location . |
im.draw_rect(bbox_or_obj, fill={color}, stroke={color}, stroke_width=1) | im.draw_rects(list_of_rects, **kwargs) | Dibuja un rectángulo a partir de un rect , char , etc., o un cuadro delimitador de 4 tuplas. |
im.draw_circle(center_or_obj, radius=5, fill={color}, stroke={color}) | im.draw_circles(list_of_circles, **kwargs) | Dibuja un círculo en las coordenadas (x, y) o en el centro de un char , rect , etc. |
Nota: Los métodos anteriores se basan en los métodos ImageDraw
de Pillow, pero los parámetros se han modificado para que sean coherentes con la nomenclatura de fill
/ stroke
/ stroke_width
de SVG.
im.debug_tablefinder(table_settings={})
devolverá una versión de PageImage con las líneas detectadas (en rojo), intersecciones (círculos) y tablas (azul claro) superpuestas.
pdfplumber
puede extraer texto de cualquier página determinada (incluidas las páginas recortadas y derivadas). También puede intentar preservar el diseño de ese texto, así como identificar las coordenadas de palabras y consultas de búsqueda. Los objetos Page
pueden llamar a los siguientes métodos de extracción de texto:
Método | Descripción |
---|---|
.extract_text(x_tolerance=3, x_tolerance_ratio=None, y_tolerance=3, layout=False, x_density=7.25, y_density=13, line_dir_render=None, char_dir_render=None, **kwargs) | Recopila todos los objetos de caracteres de la página en una sola cadena.
|
.extract_text_simple(x_tolerance=3, y_tolerance=3) | Una versión ligeramente más rápida pero menos flexible de .extract_text(...) , que utiliza una lógica más simple. |
.extract_words(x_tolerance=3, x_tolerance_ratio=None, y_tolerance=3, keep_blank_chars=False, use_text_flow=False, line_dir="ttb", char_dir="ltr", line_dir_rotated="ttb", char_dir_rotated="ltr", extra_attrs=[], split_at_punctuation=False, expand_ligatures=True, return_chars=False) | Devuelve una lista de todos los elementos que parecen palabras y sus cuadros delimitadores. Las palabras se consideran secuencias de caracteres donde (para caracteres "verticales") la diferencia entre el x1 de un carácter y el x0 del siguiente es menor o igual a x_tolerance y donde el doctop de un carácter y el doctop del siguiente es menor o igual que y_tolerance . (Si x_tolerance_ratio no es None , el extractor usa una x_tolerance dinámica igual a x_tolerance_ratio * previous_character["size"] .) Se adopta un enfoque similar para los caracteres que no son verticales, pero en lugar de medir las distancias verticales, en lugar de horizontales, entre ellos. Cambiar keep_blank_chars a True significará que los caracteres en blanco se tratan como parte de una palabra, no como un espacio entre palabras. Cambiar use_text_flow a True utilizará el flujo de caracteres subyacente del PDF como guía para ordenar y segmentar las palabras, en lugar de preclasificar los caracteres por posición x/y. (Esto imita cómo arrastrar un cursor resalta el texto en un PDF; al igual que con eso, el orden no siempre parece ser lógico). Los argumentos line_dir y char_dir le indican a este método la dirección en la que se espera que se lean las líneas/caracteres; Las opciones válidas son "ttb" (de arriba a abajo), "btt" (de abajo hacia arriba), "ltr" (de izquierda a derecha) y "rtl" (de derecha a izquierda). Los argumentos line_dir_rotated y char_dir_rotated son similares, pero para texto que ha sido rotado. Pasar una lista de extra_attrs (por ejemplo, ["fontname", "size"] restringirá cada palabra a caracteres que comparten exactamente el mismo valor para cada uno de esos atributos, y los dictados de palabras resultantes indicarán esos atributos. Establecer split_at_punctuation en True lo hará imponer tokens de separación en las puntuaciones especificadas por string.punctuation o puede especificar la lista de puntuación de separación pasando una cadena, por ejemplo, split_at_punctuation='!"&'()*+,.:;<=>?@[]^`{|}~' . A menos que establezca expand_ligatures=False , las ligaduras como fi se expandirán en sus letras constituyentes (p. ej. , fi ). Al pasar return_chars=True se agregará, a cada diccionario de palabras, una lista de sus caracteres constituyentes, como una lista en el campo "chars" . |
.extract_text_lines(layout=False, strip=True, return_chars=True, **kwargs) | Característica experimental que devuelve una lista de diccionarios que representan las líneas de texto de la página. El parámetro strip funciona de manera análoga al método str.strip() de Python y devuelve atributos text sin los espacios en blanco circundantes. (Solo es relevante cuando layout = True ). Establecer return_chars en False excluirá los objetos de caracteres individuales de los dictados de línea de texto devueltos. Los **kwargs restantes son aquellos a los que pasarías .extract_text(layout=True, ...) . |
.search(pattern, regex=True, case=True, main_group=0, return_groups=True, return_chars=True, layout=False, **kwargs) | Característica experimental que le permite buscar el texto de una página y devolver una lista de todas las instancias que coinciden con la consulta. Para cada instancia, el objeto del diccionario de respuesta contiene el texto coincidente, cualquier coincidencia de grupo de expresiones regulares, las coordenadas del cuadro delimitador y los propios objetos char. pattern puede ser una expresión regular compilada, una expresión regular no compilada o una cadena sin expresiones regulares. Si regex es False , el patrón se trata como una cadena que no es una expresión regular. Si case es False , la búsqueda se realiza sin distinguir entre mayúsculas y minúsculas. La configuración main_group restringe los resultados a un grupo de expresiones regulares específico dentro del pattern (el valor predeterminado de 0 significa toda la coincidencia). Establecer return_groups y/o return_chars en False excluirá la posibilidad de agregar las listas de grupos y/o caracteres de expresiones regulares coincidentes (como "groups" y "chars" a los dictados de retorno). El parámetro layout funciona como lo hace para .extract_text(...) . Los **kwargs restantes son aquellos a los que pasarías .extract_text(layout=True, ...) . Nota : Las coincidencias de ancho cero y todos los espacios en blanco se descartan porque (generalmente) no tienen una posición explícita en la página. |
.dedupe_chars(tolerance=1, extra_attrs=("fontname", "size")) | Devuelve una versión de la página con caracteres duplicados (aquellos que comparten el mismo texto, posición (dentro de tolerance x/y) y extra_attrs como otros caracteres) eliminados. (Consulte el número 71 para comprender la motivación). |
El enfoque de pdfplumber
para la detección de tablas se basa en gran medida en la tesis de maestría de Anssi Nurminen y está inspirado en Tabula. Funciona así:
Los objetos pdfplumber.Page
pueden llamar a los siguientes métodos de tabla:
Método | Descripción |
---|---|
.find_tables(table_settings={}) | Devuelve una lista de objetos Table . El objeto Table proporciona acceso a las propiedades .cells , .rows , .columns y .bbox , así como al método .extract(x_tolerance=3, y_tolerance=3) . |
.find_table(table_settings={}) | Similar a .find_tables(...) , pero devuelve la tabla más grande de la página, como un objeto Table . Si varias tablas tienen el mismo tamaño (medido por el número de celdas), este método devuelve la tabla más cercana a la parte superior de la página. |
.extract_tables(table_settings={}) | Devuelve el texto extraído de todas las tablas que se encuentran en la página, representado como una lista de listas, con la estructura table -> row -> cell . |
.extract_table(table_settings={}) | Devuelve el texto extraído de la tabla más grande de la página (ver .find_table(...) arriba), representado como una lista de listas, con la estructura row -> cell . |
.debug_tablefinder(table_settings={}) | Devuelve una instancia de la clase TableFinder , con acceso a las propiedades .edges , .intersections , .cells y .tables . |
Por ejemplo:
pdf = pdfplumber . open ( "path/to/my.pdf" )
page = pdf . pages [ 0 ]
page . extract_table ()
Haga clic aquí para ver un ejemplo más detallado.
De forma predeterminada, extract_tables
utiliza las líneas verticales y horizontales de la página (o bordes del rectángulo) como separadores de celdas. Pero el método es altamente personalizable mediante el argumento table_settings
. Las configuraciones posibles y sus valores predeterminados:
{
"vertical_strategy" : "lines" ,
"horizontal_strategy" : "lines" ,
"explicit_vertical_lines" : [],
"explicit_horizontal_lines" : [],
"snap_tolerance" : 3 ,
"snap_x_tolerance" : 3 ,
"snap_y_tolerance" : 3 ,
"join_tolerance" : 3 ,
"join_x_tolerance" : 3 ,
"join_y_tolerance" : 3 ,
"edge_min_length" : 3 ,
"min_words_vertical" : 3 ,
"min_words_horizontal" : 1 ,
"intersection_tolerance" : 3 ,
"intersection_x_tolerance" : 3 ,
"intersection_y_tolerance" : 3 ,
"text_tolerance" : 3 ,
"text_x_tolerance" : 3 ,
"text_y_tolerance" : 3 ,
"text_*" : …, # See below
}
Configuración | Descripción |
---|---|
"vertical_strategy" | Ya sea "lines" , "lines_strict" , "text" o "explicit" . Vea la explicación a continuación. |
"horizontal_strategy" | Ya sea "lines" , "lines_strict" , "text" o "explicit" . Vea la explicación a continuación. |
"explicit_vertical_lines" | Una lista de líneas verticales que delimitan explícitamente las celdas de la tabla. Se puede utilizar en combinación con cualquiera de las estrategias anteriores. Los elementos de la lista deben ser números (que indican la coordenada x de una línea que ocupa toda la altura de la página) u objetos line , rect o curve . |
"explicit_horizontal_lines" | Una lista de líneas horizontales que delimitan explícitamente las celdas de la tabla. Se puede utilizar en combinación con cualquiera de las estrategias anteriores. Los elementos de la lista deben ser números, que indican la coordenada y de una línea que ocupa toda la altura de la página, u objetos line , rect o curve . |
"snap_tolerance" , "snap_x_tolerance" , "snap_y_tolerance" | Las líneas paralelas dentro de los puntos snap_tolerance se "ajustarán" a la misma posición horizontal o vertical. |
"join_tolerance" , "join_x_tolerance" , "join_y_tolerance" | Los segmentos de línea en la misma línea infinita, y cuyos extremos están dentro de join_tolerance entre sí, se "unirán" en un solo segmento de línea. |
"edge_min_length" | Los bordes más cortos que edge_min_length se descartarán antes de intentar reconstruir la tabla. |
"min_words_vertical" | Cuando se utiliza "vertical_strategy": "text" , al menos las palabras min_words_vertical deben compartir la misma alineación. |
"min_words_horizontal" | Cuando se utiliza "horizontal_strategy": "text" , al menos las palabras min_words_horizontal deben compartir la misma alineación. |
"intersection_tolerance" , "intersection_x_tolerance" , "intersection_y_tolerance" | Al combinar bordes en celdas, los bordes ortogonales deben estar dentro de los puntos intersection_tolerance para que se consideren intersecantes. |
"text_*" | Todas las configuraciones con el prefijo text_ se utilizan al extraer texto de cada tabla descubierta. Todos los argumentos posibles para Page.extract_text(...) también son válidos aquí. |
"text_x_tolerance" , "text_y_tolerance" | Estas configuraciones con prefijo text_ también se aplican al algoritmo de identificación de tablas cuando se utiliza la estrategia text . Es decir, cuando ese algoritmo busca palabras, esperará que las letras individuales de cada palabra no estén separadas más que puntos text_x_tolerance / text_y_tolerance . |
Tanto vertical_strategy
como horizontal_strategy
aceptan las siguientes opciones:
Estrategia | Descripción |
---|---|
"lines" | Utilice las líneas gráficas de la página, incluidos los lados de los objetos rectangulares, como bordes de posibles celdas de la tabla. |
"lines_strict" | Utilice las líneas gráficas de la página, pero no los lados de los objetos rectangulares, como bordes de posibles celdas de la tabla. |
"text" | Para vertical_strategy : deduzca las líneas (imaginarias) que conectan la izquierda, la derecha o el centro de las palabras en la página y use esas líneas como bordes de posibles celdas de la tabla. Para horizontal_strategy , lo mismo pero usando la parte superior de las palabras. |
"explicit" | Utilice únicamente las líneas definidas explícitamente en explicit_vertical_lines / explicit_horizontal_lines . |
A menudo resulta útil recortar una página ( Page.crop(bounding_box)
) antes de intentar extraer la tabla.
La extracción de tablas para pdfplumber
se rediseñó radicalmente para v0.5.0
e introdujo cambios importantes.
A veces, los archivos PDF pueden contener formularios que incluyen entradas que las personas pueden completar y guardar. Si bien los valores de los campos del formulario aparecen como cualquier otro texto en un archivo PDF, los datos del formulario se manejan de manera diferente. Si desea conocer los detalles sangrientos, consulte la página 671 de esta especificación.
pdfplumber
no tiene una interfaz para trabajar con datos de formulario, pero puede acceder a ella utilizando los contenedores de pdfplumber
en pdfminer
.
Por ejemplo, este fragmento recuperará los nombres y valores de los campos del formulario y los almacenará en un diccionario.
import pdfplumber
from pdfplumber . utils . pdfinternals import resolve_and_decode , resolve
pdf = pdfplumber . open ( "document_with_form.pdf" )
def parse_field_helper ( form_data , field , prefix = None ):
""" appends any PDF AcroForm field/value pairs in `field` to provided `form_data` list
if `field` has child fields, those will be parsed recursively.
"""
resolved_field = field . resolve ()
field_name = '.' . join ( filter ( lambda x : x , [ prefix , resolve_and_decode ( resolved_field . get ( "T" ))]))
if "Kids" in resolved_field :
for kid_field in resolved_field [ "Kids" ]:
parse_field_helper ( form_data , kid_field , prefix = field_name )
if "T" in resolved_field or "TU" in resolved_field :
# "T" is a field-name, but it's sometimes absent.
# "TU" is the "alternate field name" and is often more human-readable
# your PDF may have one, the other, or both.
alternate_field_name = resolve_and_decode ( resolved_field . get ( "TU" )) if resolved_field . get ( "TU" ) else None
field_value = resolve_and_decode ( resolved_field [ "V" ]) if 'V' in resolved_field else None
form_data . append ([ field_name , alternate_field_name , field_value ])
form_data = []
fields = resolve ( resolve ( pdf . doc . catalog [ "AcroForm" ])[ "Fields" ])
for field in fields :
parse_field_helper ( form_data , field )
Una vez que ejecute este script, form_data
es una lista que contiene una tupla de tres elementos para cada elemento del formulario. Por ejemplo, un formulario PDF con un campo de ciudad y estado podría verse así.
[
['STATE.0', 'enter STATE', 'CA'],
['section 2 accident infoRmation.1.0',
'enter city of accident',
'SAN FRANCISCO']
]
Gracias a @jeremybmerrill por ayudar a mantener el código de análisis de formularios anterior.
extract_table
en un informe de Notificación de ajuste y reentrenamiento de trabajadores de California (WARN). Demuestra la depuración visual básica y la extracción de tablas.extract_table
en los archivos PDF del Sistema Nacional Instantáneo de Verificación de Antecedentes Penales del FBI. Demuestra cómo utilizar la depuración visual para encontrar la configuración óptima de extracción de tablas. También demuestra Page.crop(...)
y Page.extract_text(...).
curve
.Page.extract_text(...)
. Varias otras bibliotecas de Python ayudan a los usuarios a extraer información de archivos PDF. En general, pdfplumber
se distingue de otras bibliotecas de procesamiento de PDF por combinar estas características:
También es útil saber qué funciones no ofrece pdfplumber
:
pdfminer.six
proporciona la base para pdfplumber
. Se centra principalmente en analizar archivos PDF, analizar diseños de PDF y posicionamiento de objetos, y extraer texto. No proporciona herramientas para la extracción de tablas o la depuración visual.
PyPDF2
es una biblioteca pura de Python "capaz de dividir, fusionar, recortar y transformar las páginas de archivos PDF. También puede agregar datos personalizados, opciones de visualización y contraseñas a archivos PDF". Puede extraer texto de página, pero no proporciona fácil acceso a objetos de forma (rectángulos, líneas, etc.), extracción de tablas o herramientas de depuración visual.
pymupdf
es sustancialmente más rápido que pdfminer.six
(y por lo tanto también pdfplumber
) y puede generar y modificar archivos PDF, pero la biblioteca requiere la instalación de un software que no sea Python (MuPDF). Tampoco permite un fácil acceso a objetos de forma (rectángulos, líneas, etc.) y no proporciona herramientas de extracción de tablas o depuración visual.
camelot
, tabula-py
y pdftables
se centran principalmente en extraer tablas. En algunos casos, pueden adaptarse mejor a las tablas particulares que está intentando extraer.
Muchas gracias a los siguientes usuarios que contribuyeron con ideas, funciones y correcciones:
Las solicitudes de extracción son bienvenidas, pero primero envíe una propuesta, ya que la biblioteca está en desarrollo activo.
Mantenedores actuales: