Sondez un PDF pour obtenir des informations détaillées sur chaque caractère de texte, rectangle et ligne. Plus : Extraction de tables et débogage visuel.
Fonctionne mieux sur les PDF générés automatiquement plutôt que numérisés. Construit sur pdfminer.six
.
Actuellement testé sur Python 3.8, 3.9, 3.10, 3.11.
Les traductions de ce document sont disponibles en : chinois (par @hbh112233abc).
Pour signaler un bug ou demander une fonctionnalité, veuillez signaler un problème. Pour poser une question ou demander de l'aide avec un PDF spécifique, veuillez utiliser le forum de discussions.
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
Le résultat sera un CSV contenant des informations sur chaque caractère, ligne et rectangle du PDF.
Argument | Description |
---|---|
--format [format] | csv ou json . Le format json renvoie plus d'informations ; il comprend des métadonnées au niveau PDF et au niveau de la page, ainsi que des attributs imbriqués dans un dictionnaire. |
--pages [list of pages] | Une liste de pages ou de plages de pages avec trait d'union, délimitées par des espaces et indexées à 1 . Par exemple, 1, 11-15 , qui renverrait les données des pages 1, 11, 12, 13, 14 et 15. |
--types [list of object types to extract] | Les choix sont char , rect , line , curve , image , annot , et cetera. Par défaut, tous sont disponibles. |
--laparams | Une chaîne au format JSON (par exemple, '{"detect_vertical": true}' ) à transmettre à pdfplumber.open(..., laparams=...) . |
--precision [integer] | Le nombre de décimales pour arrondir les nombres à virgule flottante. Par défaut, aucun arrondi. |
import pdfplumber
with pdfplumber . open ( "path/to/file.pdf" ) as pdf :
first_page = pdf . pages [ 0 ]
print ( first_page . chars [ 0 ])
Pour commencer à travailler avec un PDF, appelez pdfplumber.open(x)
, où x
peut être un :
La méthode open
renvoie une instance de la classe pdfplumber.PDF
.
Pour charger un PDF protégé par mot de passe, transmettez l'argument mot-clé password
, par exemple pdfplumber.open("file.pdf", password = "test")
.
Pour définir les paramètres d'analyse de mise en page au moteur de mise en page de pdfminer.six
, transmettez l'argument de mot-clé laparams
, par exemple pdfplumber.open("file.pdf", laparams = { "line_overlap": 0.7 })
.
Pour pré-normaliser le texte Unicode, transmettez unicode_norm=...
, où ...
est l'une des quatre formes de normalisation Unicode : "NFC"
, "NFD"
, "NFKC"
ou "NFKD"
.
Les valeurs de métadonnées non valides sont traitées comme un avertissement par défaut. Si ce n'est pas prévu, transmettez strict_metadata=True
à la méthode open
et pdfplumber.open
déclenchera une exception s'il ne parvient pas à analyser les métadonnées.
pdfplumber.PDF
La classe pdfplumber.PDF
de niveau supérieur représente un seul PDF et possède deux propriétés principales :
Propriété | Description |
---|---|
.metadata | Un dictionnaire de paires clé/valeur de métadonnées, tiré des bandes-annonces Info du PDF. Inclut généralement « CreationDate », « ModDate », « Producteur », etc. |
.pages | Une liste contenant une instance pdfplumber.Page par page chargée. |
... et a également la méthode suivante :
Méthode | Description |
---|---|
.close() | L'appel de cette méthode appelle Page.close() sur chaque page et ferme également le flux de fichiers (sauf dans les cas où le flux est externe, c'est-à-dire déjà ouvert et transmis directement à pdfplumber ). |
pdfplumber.Page
La classe pdfplumber.Page
est au cœur de pdfplumber
. La plupart des choses que vous ferez avec pdfplumber
tourneront autour de ce cours. Il possède ces propriétés principales :
Propriété | Description |
---|---|
.page_number | Le numéro de page séquentiel, commençant par 1 pour la première page, 2 pour la seconde, et ainsi de suite. |
.width | La largeur de la page. |
.height | La hauteur de la page. |
.objects / .chars / .lines / .rects / .curves / .images | Chacune de ces propriétés est une liste et chaque liste contient un dictionnaire pour chacun de ces objets incorporés dans la page. Pour plus de détails, voir « Objets » ci-dessous. |
... et ces principales méthodes :
Méthode | Description |
---|---|
.crop(bounding_box, relative=False, strict=True) | Renvoie une version de la page recadrée dans le cadre de délimitation, qui doit être exprimée sous forme de 4 tuples avec les valeurs (x0, top, x1, bottom) . Les pages recadrées conservent les objets qui se trouvent au moins en partie dans le cadre de délimitation. Si un objet ne rentre que partiellement dans la boîte, ses dimensions sont découpées pour s'adapter à la boîte englobante. Si relative=True , le cadre de délimitation est calculé comme un décalage par rapport au coin supérieur gauche du cadre de délimitation de la page, plutôt que comme un positionnement absolu. (Voir le numéro 245 pour un exemple visuel et une explication.) Lorsque strict=True (valeur par défaut), le cadre de délimitation du recadrage doit être entièrement compris dans le cadre de délimitation de la page. |
.within_bbox(bounding_box, relative=False, strict=True) | Similaire à .crop , mais ne conserve que les objets qui se trouvent entièrement dans le cadre de délimitation. |
.outside_bbox(bounding_box, relative=False, strict=True) | Similaire à .crop et .within_bbox , mais ne conserve que les objets qui se situent entièrement en dehors du cadre de délimitation. |
.filter(test_function) | Renvoie une version de la page avec uniquement les .objects pour lesquels test_function(obj) renvoie True . |
... et a également la méthode suivante :
Méthode | Description |
---|---|
.close() | Par défaut, les objets Page mettent en cache leur mise en page et leurs informations sur les objets pour éviter d'avoir à les retraiter. Cependant, lors de l'analyse de fichiers PDF volumineux, ces propriétés mises en cache peuvent nécessiter beaucoup de mémoire. Vous pouvez utiliser cette méthode pour vider le cache et libérer de la mémoire. |
Des méthodes supplémentaires sont décrites dans les sections ci-dessous :
Chaque instance de pdfplumber.PDF
et pdfplumber.Page
donne accès à plusieurs types d'objets PDF, tous dérivés de l'analyse PDF pdfminer.six
. Les propriétés suivantes renvoient chacune une liste Python des objets correspondants :
.chars
, chacun représentant un seul caractère de texte..lines
, chacun représentant une seule ligne unidimensionnelle..rects
, chacun représentant un seul rectangle bidimensionnel..curves
, chacun représentant une série de points connectés que pdfminer.six
ne reconnaît pas comme une ligne ou un rectangle..images
, chacun représentant une image..annots
, chacun représentant une seule annotation PDF (cf. Section 8.4 de la spécification PDF officielle pour plus de détails).hyperlinks
, chacun représentant une seule annotation PDF du sous-type Link
et ayant un attribut d'action URI
Chaque objet est représenté sous la forme d'un simple dict
Python, avec les propriétés suivantes :
char
Propriété | Description |
---|---|
page_number | Numéro de page sur laquelle ce caractère a été trouvé. |
text | Par exemple, "z", ou "Z" ou " ". |
fontname | Nom de la police du personnage. |
size | Taille de la police. |
adv | Égal à la largeur du texte * à la taille de la police * au facteur d'échelle. |
upright | Si le personnage est debout. |
height | Hauteur du personnage. |
width | Largeur du personnage. |
x0 | Distance entre le côté gauche du caractère et le côté gauche de la page. |
x1 | Distance entre le côté droit du caractère et le côté gauche de la page. |
y0 | Distance entre le bas du caractère et le bas de la page. |
y1 | Distance entre le haut du caractère et le bas de la page. |
top | Distance entre le haut du caractère et le haut de la page. |
bottom | Distance entre le bas du caractère et le haut de la page. |
doctop | Distance entre le haut du caractère et le haut du document. |
matrix | La "matrice de transformation actuelle" pour ce personnage. (Voir ci-dessous pour plus de détails.) |
mcid | L'ID de section de contenu marqué pour ce personnage, le cas échéant (sinon None ). Attribut expérimental. |
tag | La balise de section de contenu marquée pour ce caractère, le cas échéant (sinon None ). Attribut expérimental. |
ncs | TKTK |
stroking_pattern | TKTK |
non_stroking_pattern | TKTK |
stroking_color | La couleur du contour du personnage (c'est-à-dire le trait). Voir docs/colors.md pour plus de détails. |
non_stroking_color | La couleur intérieure du personnage. Voir docs/colors.md pour plus de détails. |
object_type | "carboniser" |
Remarque : la propriété matrix
d'un caractère représente la « matrice de transformation actuelle », comme décrit dans la section 4.2.2 de la référence PDF (6e éd.). La matrice contrôle l'échelle, l'inclinaison et la traduction positionnelle du caractère. La rotation est une combinaison d'échelle et d'inclinaison, mais dans la plupart des cas, elle peut être considérée comme égale à l'inclinaison de l'axe X. Le sous-module pdfplumber.ctm
définit une classe, CTM
, qui facilite ces calculs. Par exemple:
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
Propriété | Description |
---|---|
page_number | Numéro de page sur laquelle cette ligne a été trouvée. |
height | Hauteur de ligne. |
width | Largeur de ligne. |
x0 | Distance entre l'extrémité gauche et le côté gauche de la page. |
x1 | Distance entre l'extrémité droite et le côté gauche de la page. |
y0 | Distance entre l'extrémité inférieure et le bas de la page. |
y1 | Distance de l'extrémité supérieure en bas de page. |
top | Distance entre le haut de la ligne et le haut de la page. |
bottom | Distance entre le bas de la ligne et le haut de la page. |
doctop | Distance entre le haut de la ligne et le haut du document. |
linewidth | Épaisseur du trait. |
stroking_color | La couleur de la ligne. Voir docs/colors.md pour plus de détails. |
non_stroking_color | Couleur sans trait spécifiée pour le tracé de la ligne. Voir docs/colors.md pour plus de détails. |
mcid | L'ID de section de contenu marqué pour cette ligne, le cas échéant (sinon None ). Attribut expérimental. |
tag | La balise de section de contenu marquée pour cette ligne, le cas échéant (sinon None ). Attribut expérimental. |
object_type | "doubler" |
rect
Propriété | Description |
---|---|
page_number | Numéro de page sur laquelle ce rectangle a été trouvé. |
height | Hauteur du rectangle. |
width | Largeur du rectangle. |
x0 | Distance entre le côté gauche du rectangle et le côté gauche de la page. |
x1 | Distance entre le côté droit du rectangle et le côté gauche de la page. |
y0 | Distance entre le bas du rectangle et le bas de la page. |
y1 | Distance entre le haut du rectangle et le bas de la page. |
top | Distance entre le haut du rectangle et le haut de la page. |
bottom | Distance entre le bas du rectangle et le haut de la page. |
doctop | Distance entre le haut du rectangle et le haut du document. |
linewidth | Épaisseur du trait. |
stroking_color | La couleur du contour du rectangle. Voir docs/colors.md pour plus de détails. |
non_stroking_color | La couleur de remplissage du rectangle. Voir docs/colors.md pour plus de détails. |
mcid | L'ID de section de contenu marqué pour ce rect le cas échéant (sinon None ). Attribut expérimental. |
tag | La balise de section de contenu marquée pour ce rect le cas échéant (sinon None ). Attribut expérimental. |
object_type | "correct" |
curve
Propriété | Description |
---|---|
page_number | Numéro de page sur laquelle cette courbe a été trouvée. |
pts | Une liste de tuples (x, top) indiquant les points sur la courbe . |
path | Une liste de tuples (cmd, *(x, top)) décrivant la description complète du chemin , y compris (par exemple) les points de contrôle utilisés dans les courbes de Bézier. |
height | Hauteur du cadre de délimitation de la courbe. |
width | Largeur du cadre de délimitation de la courbe. |
x0 | Distance entre le point le plus à gauche de la courbe et le côté gauche de la page. |
x1 | Distance entre le point le plus à droite de la courbe et le côté gauche de la page. |
y0 | Distance du point le plus bas de la courbe à partir du bas de la page. |
y1 | Distance du point le plus élevé de la courbe à partir du bas de la page. |
top | Distance du point culminant de la courbe depuis le haut de la page. |
bottom | Distance du point le plus bas de la courbe depuis le haut de la page. |
doctop | Distance du point le plus élevé de la courbe depuis le haut du document. |
linewidth | Épaisseur du trait. |
fill | Si la forme définie par le chemin de la courbe est remplie. |
stroking_color | La couleur du contour de la courbe. Voir docs/colors.md pour plus de détails. |
non_stroking_color | La couleur de remplissage de la courbe. Voir docs/colors.md pour plus de détails. |
dash | Un tuple ([dash_array], dash_phase) décrivant le style de tiret de la courbe. Voir le tableau 4.6 de la spécification PDF pour plus de détails. |
mcid | L'ID de section de contenu marqué pour cette courbe, le cas échéant (sinon None ). Attribut expérimental. |
tag | La balise de section de contenu marquée pour cette courbe, le cas échéant (sinon None ). Attribut expérimental. |
object_type | "courbe" |
De plus, pdfplumber.PDF
et pdfplumber.Page
donnent accès à plusieurs listes d'objets dérivées : .rect_edges
(qui décompose chaque rectangle en ses quatre lignes), .curve_edges
(qui fait de même pour les objets curve
) et .edges
(qui combine .rect_edges
, .curve_edges
et .lines
).
image
Remarque : Bien que le positionnement et les caractéristiques des objets image
soient disponibles via pdfplumber
, cette bibliothèque ne fournit pas de support direct pour la reconstruction du contenu de l'image. Pour cela, veuillez consulter cette suggestion.
Propriété | Description |
---|---|
page_number | Numéro de page sur laquelle l'image a été trouvée. |
height | Hauteur de l'image. |
width | Largeur de l'image. |
x0 | Distance entre le côté gauche de l'image et le côté gauche de la page. |
x1 | Distance entre le côté droit de l'image et le côté gauche de la page. |
y0 | Distance entre le bas de l'image et le bas de la page. |
y1 | Distance entre le haut de l'image et le bas de la page. |
top | Distance entre le haut de l'image et le haut de la page. |
bottom | Distance entre le bas de l'image et le haut de la page. |
doctop | Distance entre le haut du rectangle et le haut du document. |
srcsize | Les dimensions d'origine de l'image, sous forme de tuple (width, height) . |
colorspace | Domaine de couleur de l'image (par exemple, RVB). |
bits | Le nombre de bits par composante de couleur ; par exemple, 8 correspond à 255 valeurs possibles pour chaque composante de couleur (R, V et B dans un espace colorimétrique RVB). |
stream | Valeurs de pixels de l'image, en tant qu'objet pdfminer.pdftypes.PDFStream . |
imagemask | Un booléen nullable ; si True , "spécifie que les données de l'image doivent être utilisées comme masque de pochoir pour peindre dans la couleur actuelle." |
mcid | L'ID de section de contenu marqué pour cette image, le cas échéant (sinon None ). Attribut expérimental. |
tag | La balise de section de contenu marquée pour cette image, le cas échéant (sinon None ). Attribut expérimental. |
object_type | "image" |
pdfminer.six
Si vous transmettez le paramètre pdfminer.six
-handling laparams
à pdfplumber.open(...)
, alors le dictionnaire .objects
de chaque page contiendra également les objets de mise en page de niveau supérieur de pdfminer.six
, tels que "textboxhorizontal"
.
Les outils de débogage visuel de pdfplumber
peuvent être utiles pour comprendre la structure d'un PDF et les objets qui en ont été extraits.
PageImage
avec .to_image()
Pour transformer n'importe quelle page (y compris les pages recadrées) en un objet PageImage
, appelez my_page.to_image()
. Vous pouvez éventuellement transmettre l'un des arguments de mot-clé suivants :
resolution
: Le nombre souhaité de pixels par pouce. Par défaut : 72
. Tapez : int
.width
: La largeur de l’image souhaitée en pixels. Par défaut : non défini, déterminé par resolution
. Tapez : int
.height
: La largeur de l’image souhaitée en pixels. Par défaut : non défini, déterminé par resolution
. Tapez : int
.antialias
: s'il faut utiliser l'antialiasing lors de la création de l'image. La valeur True
crée des images avec du texte et des graphiques moins irréguliers, mais avec des fichiers de plus grande taille. Par défaut : False
. Tapez : bool
.force_mediabox
: utilisez les dimensions .mediabox
de la page, plutôt que les dimensions .cropbox
. Par défaut : False
. Tapez : bool
.Par exemple:
im = my_pdf . pages [ 0 ]. to_image ( resolution = 150 )
À partir d'un script ou d'un REPL, im.show()
ouvrira l'image dans votre visionneuse d'images locale. Mais les objets PageImage
fonctionnent également bien avec les notebooks Jupyter ; ils s'affichent automatiquement en tant que sorties de cellule. Par exemple:
Remarque : .to_image(...)
fonctionne comme prévu avec les instances Page.crop(...)
/ CroppedPage
, mais ne peut pas intégrer les modifications apportées via les instances Page.filter(...)
/ FilteredPage
.
PageImage
de baseMéthode | Description |
---|---|
im.reset() | Efface tout ce que vous avez dessiné jusqu'à présent. |
im.copy() | Copie l'image dans un nouvel objet PageImage . |
im.show() | Ouvre l'image dans votre visionneuse d'images locale. |
im.save(path_or_fileobject, format="PNG", quantize=True, colors=256, bits=8) | Enregistre l'image annotée sous forme de fichier PNG. Les arguments par défaut quantifient l'image dans une palette de 256 couleurs, enregistrant le PNG avec une profondeur de couleur de 8 bits. Vous pouvez désactiver la quantification en passant quantize=False ou ajuster la taille de la palette de couleurs en passant colors=N . |
Vous pouvez transmettre des coordonnées explicites ou n'importe quel objet PDF pdfplumber
(par exemple, char, line, rect) à ces méthodes.
Méthode à objet unique | Méthode groupée | Description |
---|---|---|
im.draw_line(line, stroke={color}, stroke_width=1) | im.draw_lines(list_of_lines, **kwargs) | Dessine une ligne à partir d'une line , curve ou d'un 2-uplets de 2-uplets (par exemple, ((x, y), (x, y)) ). |
im.draw_vline(location, stroke={color}, stroke_width=1) | im.draw_vlines(list_of_locations, **kwargs) | Dessine une ligne verticale à la coordonnée x indiquée par location . |
im.draw_hline(location, stroke={color}, stroke_width=1) | im.draw_hlines(list_of_locations, **kwargs) | Dessine une ligne horizontale à la coordonnée y indiquée par location . |
im.draw_rect(bbox_or_obj, fill={color}, stroke={color}, stroke_width=1) | im.draw_rects(list_of_rects, **kwargs) | Dessine un rectangle à partir d'un cadre de délimitation rect , char , etc., ou à 4 tuples. |
im.draw_circle(center_or_obj, radius=5, fill={color}, stroke={color}) | im.draw_circles(list_of_circles, **kwargs) | Dessine un cercle aux coordonnées (x, y) ou au centre d'un char , rect , etc. |
Remarque : Les méthodes ci-dessus sont basées sur les méthodes ImageDraw
de Pillow, mais les paramètres ont été modifiés pour plus de cohérence avec la nomenclature fill
/ stroke
/ stroke_width
de SVG.
im.debug_tablefinder(table_settings={})
renverra une version de PageImage avec les lignes détectées (en rouge), les intersections (cercles) et les tableaux (bleu clair) superposés.
pdfplumber
peut extraire le texte de n'importe quelle page donnée (y compris les pages recadrées et dérivées). Il peut également tenter de préserver la mise en page de ce texte, ainsi que d'identifier les coordonnées des mots et des requêtes de recherche. Les objets Page
peuvent appeler les méthodes d'extraction de texte suivantes :
Méthode | Description |
---|---|
.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) | Rassemble tous les objets caractères de la page en une seule chaîne.
|
.extract_text_simple(x_tolerance=3, y_tolerance=3) | Une version légèrement plus rapide mais moins flexible de .extract_text(...) , utilisant une logique plus 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) | Renvoie une liste de tous les éléments ressemblant à des mots et de leurs cadres de délimitation. Les mots sont considérés comme des séquences de caractères où (pour les caractères "verts") la différence entre le x1 d'un caractère et le x0 du suivant est inférieure ou égale à x_tolerance et où le doctop d'un caractère et le doctop du suivant est inférieur ou égal à y_tolerance . (Si x_tolerance_ratio n'est pas None , l'extracteur utilise une x_tolerance dynamique égale à x_tolerance_ratio * previous_character["size"] .) Une approche similaire est adoptée pour les caractères non verticaux, mais mesurant à la place les distances verticales plutôt qu'horizontales entre eux. Changer keep_blank_chars en True signifie que les caractères vides sont traités comme faisant partie d'un mot, et non comme un espace entre les mots. Changer use_text_flow en True utilisera le flux de caractères sous-jacent du PDF comme guide pour ordonner et segmenter les mots, plutôt que de pré-trier les caractères par position x/y. (Cela imite la façon dont le fait de faire glisser un curseur met en surbrillance le texte dans un PDF ; comme dans ce cas, l'ordre ne semble pas toujours logique.) Les arguments line_dir et char_dir indiquent à cette méthode la direction dans laquelle les lignes/caractères doivent être lus ; les options valides sont « ttb » (de haut en bas), « btt » (de bas en haut), « ltr » (de gauche à droite) et « rtl » (de droite à gauche). Les arguments line_dir_rotated et char_dir_rotated sont similaires, mais pour le texte qui a subi une rotation. Passer une liste d' extra_attrs (par exemple, ["fontname", "size"] limitera chaque mot aux caractères qui partagent exactement la même valeur pour chacun de ces attributs, et les dicts de mots résultants indiqueront ces attributs. Définir split_at_punctuation sur True le fera appliquez des jetons de rupture aux ponctuations spécifiées par string.punctuation ; ou vous pouvez spécifier la liste des signes de ponctuation de séparation en transmettant une chaîne, par exemple, split_at_punctuation='!"&'()*+,.:;<=>?@[]^`{|}~' . Sauf si vous définissez expand_ligatures=False , les ligatures telles que fi seront développées dans leurs lettres constitutives (par exemple , fi ). Passer return_chars=True ajoutera, à chaque dictionnaire de mots, une liste de ses caractères constitutifs, sous forme de liste dans le champ "chars" . |
.extract_text_lines(layout=False, strip=True, return_chars=True, **kwargs) | Fonctionnalité expérimentale qui renvoie une liste de dictionnaires représentant les lignes de texte sur la page. Le paramètre strip fonctionne de manière analogue à la méthode str.strip() de Python et renvoie les attributs text sans leurs espaces environnants. (Uniquement pertinent lorsque layout = True .) Définir return_chars sur False exclura les objets caractères individuels des dicts de ligne de texte renvoyés. Les **kwargs restants sont ceux que vous transmettriez à .extract_text(layout=True, ...) . |
.search(pattern, regex=True, case=True, main_group=0, return_groups=True, return_chars=True, layout=False, **kwargs) | Fonctionnalité expérimentale qui vous permet de rechercher le texte d'une page, renvoyant une liste de toutes les instances correspondant à la requête. Pour chaque instance, l'objet dictionnaire de réponses contient le texte correspondant, toutes les correspondances de groupe regex, les coordonnées du cadre de délimitation et les objets char eux-mêmes. pattern peut être une expression régulière compilée, une expression régulière non compilée ou une chaîne non regex. Si regex est False , le modèle est traité comme une chaîne non regex. Si case est False , la recherche est effectuée sans tenir compte de la casse. La définition main_group restreint les résultats à un groupe d'expressions régulières spécifique dans le pattern (la valeur par défaut 0 signifie la correspondance entière). Définir return_groups et/ou return_chars sur False exclura l'ajout des listes des groupes et/ou caractères regex correspondants (en tant que "groups" et "chars" aux dictionnaires de retour). Le paramètre layout fonctionne comme pour .extract_text(...) . Les **kwargs restants sont ceux que vous transmettriez à .extract_text(layout=True, ...) . Remarque : les correspondances de largeur nulle et entièrement composées d'espaces sont ignorées, car elles n'ont (généralement) pas de position explicite sur la page. |
.dedupe_chars(tolerance=1, extra_attrs=("fontname", "size")) | Renvoie une version de la page avec des caractères en double – ceux partageant le même texte, le même positionnement (dans tolerance x/y) et extra_attrs que les autres caractères – supprimés. (Voir le numéro 71 pour comprendre la motivation.) |
L'approche de pdfplumber
en matière de détection de tables emprunte beaucoup au mémoire de maîtrise d'Anssi Nurminen et s'inspire de Tabula. Cela fonctionne comme ceci :
Les objets pdfplumber.Page
peuvent appeler les méthodes de table suivantes :
Méthode | Description |
---|---|
.find_tables(table_settings={}) | Renvoie une liste d'objets Table . L'objet Table donne accès aux propriétés .cells , .rows , .columns et .bbox , ainsi qu'à la méthode .extract(x_tolerance=3, y_tolerance=3) . |
.find_table(table_settings={}) | Similaire à .find_tables(...) , mais renvoie la plus grande table de la page, en tant qu'objet Table . Si plusieurs tableaux ont la même taille (mesurée par le nombre de cellules), cette méthode renvoie le tableau le plus proche du haut de la page. |
.extract_tables(table_settings={}) | Renvoie le texte extrait de tous les tableaux trouvés sur la page, représenté sous forme de liste de listes de listes, avec la structure table -> row -> cell . |
.extract_table(table_settings={}) | Renvoie le texte extrait du plus grand tableau de la page (voir .find_table(...) ci-dessus), représenté sous forme de liste de listes, avec la structure row -> cell . |
.debug_tablefinder(table_settings={}) | Renvoie une instance de la classe TableFinder , avec accès aux propriétés .edges , .intersections , .cells et .tables . |
Par exemple:
pdf = pdfplumber . open ( "path/to/my.pdf" )
page = pdf . pages [ 0 ]
page . extract_table ()
Cliquez ici pour un exemple plus détaillé.
Par défaut, extract_tables
utilise les lignes verticales et horizontales de la page (ou les bords du rectangle) comme séparateurs de cellules. Mais la méthode est hautement personnalisable via l'argument table_settings
. Les paramètres possibles, et leurs valeurs par défaut :
{
"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
}
Paramètre | Description |
---|---|
"vertical_strategy" | Soit "lines" , "lines_strict" , "text" ou "explicit" . Voir explication ci-dessous. |
"horizontal_strategy" | Soit "lines" , "lines_strict" , "text" ou "explicit" . Voir explication ci-dessous. |
"explicit_vertical_lines" | Liste de lignes verticales qui délimitent explicitement les cellules du tableau. Peut être utilisé en combinaison avec l’une des stratégies ci-dessus. Les éléments de la liste doivent être soit des nombres – indiquant la coordonnée x d'une ligne sur toute la hauteur de la page – soit des objets line / rect / curve . |
"explicit_horizontal_lines" | Liste de lignes horizontales qui délimitent explicitement les cellules du tableau. Peut être utilisé en combinaison avec l’une des stratégies ci-dessus. Les éléments de la liste doivent être soit des nombres – indiquant la coordonnée y d'une ligne sur toute la hauteur de la page – soit des objets line / rect / curve . |
"snap_tolerance" , "snap_x_tolerance" , "snap_y_tolerance" | Les lignes parallèles à l'intérieur des points snap_tolerance seront "alignées" sur la même position horizontale ou verticale. |
"join_tolerance" , "join_x_tolerance" , "join_y_tolerance" | Les segments de ligne sur la même ligne infinie, et dont les extrémités sont à join_tolerance les unes des autres, seront "joints" en un seul segment de ligne. |
"edge_min_length" | Les bords plus courts que edge_min_length seront ignorés avant de tenter de reconstruire la table. |
"min_words_vertical" | Lors de l'utilisation de "vertical_strategy": "text" , au moins les mots min_words_vertical doivent partager le même alignement. |
"min_words_horizontal" | Lors de l'utilisation de "horizontal_strategy": "text" , au moins les mots min_words_horizontal doivent partager le même alignement. |
"intersection_tolerance" , "intersection_x_tolerance" , "intersection_y_tolerance" | Lors de la combinaison d'arêtes dans des cellules, les arêtes orthogonales doivent se trouver à l'intérieur des points intersection_tolerance pour être considérées comme sécantes. |
"text_*" | Tous les paramètres préfixés par text_ sont ensuite utilisés lors de l'extraction du texte de chaque table découverte. Tous les arguments possibles de Page.extract_text(...) sont également valables ici. |
"text_x_tolerance" , "text_y_tolerance" | Ces paramètres avec préfixe text_ s'appliquent également à l'algorithme d'identification de table lorsque la stratégie text est utilisée. Autrement dit, lorsque cet algorithme recherche des mots, il s'attend à ce que les lettres individuelles de chaque mot ne soient pas distantes de plus de points text_x_tolerance / text_y_tolerance . |
vertical_strategy
et horizontal_strategy
acceptent les options suivantes :
Stratégie | Description |
---|---|
"lines" | Utilisez les lignes graphiques de la page, y compris les côtés des objets rectangulaires, comme bordures des cellules potentielles du tableau. |
"lines_strict" | Utilisez les lignes graphiques de la page – mais pas les côtés des objets rectangulaires – comme bordures des cellules potentielles du tableau. |
"text" | Pour vertical_strategy : déduisez les lignes (imaginaires) qui relient la gauche, la droite ou le centre des mots sur la page et utilisez ces lignes comme bordures de cellules de tableau potentielles. Pour horizontal_strategy , pareil mais en utilisant le dessus des mots. |
"explicit" | Utilisez uniquement les lignes explicitement définies dans explicit_vertical_lines / explicit_horizontal_lines . |
Il est souvent utile de recadrer une page — Page.crop(bounding_box)
— avant d'essayer d'extraire le tableau.
L'extraction de table pour pdfplumber
a été radicalement repensée pour v0.5.0
et a introduit des modifications importantes.
Parfois, les fichiers PDF peuvent contenir des formulaires incluant des entrées que les utilisateurs peuvent remplir et enregistrer. Alors que les valeurs des champs de formulaire apparaissent comme le reste du texte dans un fichier PDF, les données du formulaire sont traitées différemment. Si vous voulez des détails sanglants, consultez la page 671 de cette spécification.
pdfplumber
n'a pas d'interface pour travailler avec les données de formulaire, mais vous pouvez y accéder à l'aide des wrappers de pdfplumber
autour de pdfminer
.
Par exemple, cet extrait récupérera les noms et les valeurs des champs de formulaire et les stockera dans un dictionnaire.
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 )
Une fois ce script exécuté, form_data
est une liste contenant un tuple à trois éléments pour chaque élément du formulaire. Par exemple, un formulaire PDF avec un champ ville et état pourrait ressembler à ceci.
[
['STATE.0', 'enter STATE', 'CA'],
['section 2 accident infoRmation.1.0',
'enter city of accident',
'SAN FRANCISCO']
]
Merci à @jeremybmerrill pour avoir aidé à maintenir le code d'analyse de formulaire ci-dessus.
extract_table
sur un rapport de notification d'ajustement et de recyclage des travailleurs de Californie (WARN). Démontre le débogage visuel de base et l’extraction de table.extract_table
sur les fichiers PDF du système national de vérification instantanée des antécédents criminels du FBI. Montre comment utiliser le débogage visuel pour trouver les paramètres d’extraction de table optimaux. Démontre également Page.crop(...)
et Page.extract_text(...).
curve
.Page.extract_text(...)
. Plusieurs autres bibliothèques Python aident les utilisateurs à extraire des informations à partir de PDF. D'une manière générale, pdfplumber
se distingue des autres bibliothèques de traitement PDF en combinant ces fonctionnalités :
Il est également utile de savoir quelles fonctionnalités pdfplumber
ne fournit pas :
pdfminer.six
constitue la base de pdfplumber
. Il se concentre principalement sur l'analyse des PDF, l'analyse des mises en page PDF et du positionnement des objets, ainsi que sur l'extraction de texte. Il ne fournit pas d'outils pour l'extraction de tables ou le débogage visuel.
PyPDF2
est une bibliothèque purement Python "capable de diviser, fusionner, recadrer et transformer les pages de fichiers PDF. Elle peut également ajouter des données personnalisées, des options d'affichage et des mots de passe aux fichiers PDF". Il peut extraire le texte d'une page, mais ne fournit pas un accès facile aux objets de forme (rectangles, lignes, etc.), à l'extraction de tableaux ou aux outils de débogage visuel.
pymupdf
est nettement plus rapide que pdfminer.six
(et donc aussi pdfplumber
) et peut générer et modifier des PDF, mais la bibliothèque nécessite l'installation d'un logiciel non Python (MuPDF). Il ne permet pas non plus d'accéder facilement aux objets de forme (rectangles, lignes, etc.) et ne fournit pas d'outils d'extraction de table ou de débogage visuel.
camelot
, tabula-py
et pdftables
se concentrent tous principalement sur l'extraction de tableaux. Dans certains cas, ils peuvent être mieux adaptés aux tables particulières que vous essayez d'extraire.
Un grand merci aux utilisateurs suivants qui ont contribué à leurs idées, fonctionnalités et correctifs :
Les demandes d'extraction sont les bienvenues, mais veuillez d'abord soumettre une proposition, car la bibliothèque est en développement actif.
Mainteneurs actuels :