Durchsuchen Sie ein PDF nach detaillierten Informationen zu den einzelnen Textzeichen, Rechtecken und Zeilen. Plus: Tabellenextraktion und visuelles Debuggen.
Funktioniert am besten mit maschinell generierten und nicht mit gescannten PDFs. Basierend auf pdfminer.six
.
Derzeit getestet auf Python 3.8, 3.9, 3.10, 3.11.
Übersetzungen dieses Dokuments sind verfügbar in: Chinesisch (von @hbh112233abc).
Um einen Fehler zu melden oder eine Funktion anzufordern, reichen Sie bitte ein Problem ein. Um eine Frage zu stellen oder Hilfe zu einem bestimmten PDF anzufordern, nutzen Sie bitte das Diskussionsforum.
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
Die Ausgabe ist eine CSV-Datei mit Informationen zu jedem Zeichen, jeder Zeile und jedem Rechteck im PDF.
Argument | Beschreibung |
---|---|
--format [format] | csv oder json . Das json -Format gibt mehr Informationen zurück; Es umfasst Metadaten auf PDF- und Seitenebene sowie im Wörterbuch verschachtelte Attribute. |
--pages [list of pages] | Eine durch Leerzeichen getrennte, durch 1 indizierte Liste von Seiten oder Seitenbereichen mit Bindestrich. Beispiel: 1, 11-15 , was Daten für die Seiten 1, 11, 12, 13, 14 und 15 zurückgeben würde. |
--types [list of object types to extract] | Zur Auswahl stehen char , rect , line , curve , image , annot usw. Standardmäßig sind alle verfügbaren verfügbar. |
--laparams | Eine JSON-formatierte Zeichenfolge (z. B. '{"detect_vertical": true}' ), die an pdfplumber.open(..., laparams=...) übergeben werden soll. |
--precision [integer] | Die Anzahl der Dezimalstellen zum Runden von Gleitkommazahlen. Standardmäßig wird keine Rundung vorgenommen. |
import pdfplumber
with pdfplumber . open ( "path/to/file.pdf" ) as pdf :
first_page = pdf . pages [ 0 ]
print ( first_page . chars [ 0 ])
Um mit der Arbeit mit einer PDF-Datei zu beginnen, rufen Sie pdfplumber.open(x)
auf, wobei x
Folgendes sein kann:
Die open
-Methode gibt eine Instanz der Klasse pdfplumber.PDF
zurück.
Um eine passwortgeschützte PDF-Datei zu laden, übergeben Sie das Schlüsselwortargument password
, z. B. pdfplumber.open("file.pdf", password = "test")
.
Um Layout-Analyseparameter für die Layout-Engine von pdfminer.six
festzulegen, übergeben Sie das Schlüsselwortargument laparams
, z. B. pdfplumber.open("file.pdf", laparams = { "line_overlap": 0.7 })
.
Um Unicode-Text vorzunormalisieren, übergeben Sie unicode_norm=...
, wobei ...
eine der vier Unicode-Normalisierungsformen ist: "NFC"
, "NFD"
, "NFKC"
oder "NFKD"
.
Ungültige Metadatenwerte werden standardmäßig als Warnung behandelt. Wenn dies nicht beabsichtigt ist, übergeben Sie strict_metadata=True
an die Methode open
und pdfplumber.open
löst eine Ausnahme aus, wenn die Metadaten nicht analysiert werden können.
pdfplumber.PDF
-Klasse Die oberste Klasse pdfplumber.PDF
stellt ein einzelnes PDF dar und verfügt über zwei Haupteigenschaften:
Eigentum | Beschreibung |
---|---|
.metadata | Ein Wörterbuch mit Metadaten-Schlüssel/Wert-Paaren, das aus den Info Trailern der PDF-Datei stammt. Enthält normalerweise „Erstellungsdatum“, „ModDatum“, „Produzent“ usw. |
.pages | Eine Liste mit einer pdfplumber.Page -Instanz pro geladener Seite. |
... und hat auch die folgende Methode:
Verfahren | Beschreibung |
---|---|
.close() | Der Aufruf dieser Methode ruft Page.close() auf jeder Seite auf und schließt auch den Dateistream (außer in Fällen, in denen der Stream extern ist, also bereits geöffnet und direkt an pdfplumber übergeben wurde). |
pdfplumber.Page
-Klasse Die Klasse pdfplumber.Page
ist das Herzstück von pdfplumber
. Die meisten Dinge, die Sie mit pdfplumber
tun werden, drehen sich um diese Klasse. Es hat diese Haupteigenschaften:
Eigentum | Beschreibung |
---|---|
.page_number | Die fortlaufende Seitennummer, beginnend mit 1 für die erste Seite, 2 für die zweite und so weiter. |
.width | Die Breite der Seite. |
.height | Die Höhe der Seite. |
.objects / .chars / .lines / .rects / .curves / .images | Jede dieser Eigenschaften ist eine Liste, und jede Liste enthält ein Wörterbuch für jedes dieser auf der Seite eingebetteten Objekte. Weitere Einzelheiten finden Sie weiter unten unter „Objekte“. |
... und diese Hauptmethoden:
Verfahren | Beschreibung |
---|---|
.crop(bounding_box, relative=False, strict=True) | Gibt eine auf den Begrenzungsrahmen zugeschnittene Version der Seite zurück, die als 4-Tupel mit den Werten (x0, top, x1, bottom) ausgedrückt werden sollte. Zugeschnittene Seiten behalten Objekte bei, die zumindest teilweise innerhalb des Begrenzungsrahmens liegen. Wenn ein Objekt nur teilweise in den Rahmen fällt, werden seine Abmessungen so zerschnitten, dass sie in den Begrenzungsrahmen passen. Wenn relative=True , wird der Begrenzungsrahmen als Versatz vom oberen linken Rand des Begrenzungsrahmens der Seite und nicht als absolute Positionierung berechnet. (Ein visuelles Beispiel und eine Erklärung finden Sie in Ausgabe Nr. 245.) Bei strict=True (Standardeinstellung) muss der Begrenzungsrahmen des Zuschnitts vollständig innerhalb des Begrenzungsrahmens der Seite liegen. |
.within_bbox(bounding_box, relative=False, strict=True) | Ähnlich wie .crop , behält jedoch nur Objekte bei, die vollständig innerhalb des Begrenzungsrahmens liegen. |
.outside_bbox(bounding_box, relative=False, strict=True) | Ähnlich wie .crop und .within_bbox , behält jedoch nur Objekte bei, die vollständig außerhalb des Begrenzungsrahmens liegen. |
.filter(test_function) | Gibt eine Version der Seite zurück, die nur die .objects enthält, für die test_function(obj) True zurückgibt. |
... und hat auch die folgende Methode:
Verfahren | Beschreibung |
---|---|
.close() | Standardmäßig speichern Page ihre Layout- und Objektinformationen im Cache, um eine erneute Verarbeitung zu vermeiden. Beim Parsen großer PDF-Dateien können diese zwischengespeicherten Eigenschaften jedoch viel Speicher beanspruchen. Mit dieser Methode können Sie den Cache leeren und den Speicher freigeben. |
Weitere Methoden werden in den folgenden Abschnitten beschrieben:
Jede Instanz von pdfplumber.PDF
und pdfplumber.Page
bietet Zugriff auf verschiedene Arten von PDF-Objekten, die alle aus der PDF-Analyse pdfminer.six
abgeleitet sind. Die folgenden Eigenschaften geben jeweils eine Python-Liste der passenden Objekte zurück:
.chars
, die jeweils ein einzelnes Textzeichen darstellen..lines
, die jeweils eine einzelne eindimensionale Linie darstellen..rects
, die jeweils ein einzelnes zweidimensionales Rechteck darstellen..curves
, die jeweils eine Reihe verbundener Punkte darstellen, die pdfminer.six
nicht als Linie oder Rechteck erkennt..images
, die jeweils ein Bild darstellen..annots
, die jeweils eine einzelne PDF-Anmerkung darstellen (Einzelheiten finden Sie in Abschnitt 8.4 der offiziellen PDF-Spezifikation)..hyperlinks
, die jeweils eine einzelne PDF-Anmerkung des Untertyps Link
darstellen und über ein URI
Aktionsattribut verfügen Jedes Objekt wird als einfaches Python- dict
mit den folgenden Eigenschaften dargestellt:
char
EigenschaftenEigentum | Beschreibung |
---|---|
page_number | Seitenzahl, auf der dieses Zeichen gefunden wurde. |
text | Zum Beispiel „z“ oder „Z“ oder „ “. |
fontname | Name der Schriftart des Charakters. |
size | Schriftgröße. |
adv | Entspricht der Textbreite * der Schriftgröße * Skalierungsfaktor. |
upright | Ob der Charakter aufrecht ist. |
height | Größe des Charakters. |
width | Breite des Zeichens. |
x0 | Abstand der linken Zeichenseite von der linken Seitenseite. |
x1 | Abstand der rechten Seite des Zeichens von der linken Seite der Seite. |
y0 | Abstand des unteren Randes des Zeichens vom unteren Rand der Seite. |
y1 | Abstand des oberen Zeichenrands vom unteren Rand der Seite. |
top | Abstand des oberen Zeichenrands vom oberen Rand der Seite. |
bottom | Abstand des unteren Randes des Zeichens vom oberen Rand der Seite. |
doctop | Abstand des oberen Zeichenrands vom oberen Rand des Dokuments. |
matrix | Die „aktuelle Transformationsmatrix“ für diesen Charakter. (Einzelheiten siehe unten.) |
mcid | Die markierte Inhaltsabschnitts-ID für dieses Zeichen, falls vorhanden (sonst None ). Experimentelles Attribut. |
tag | Das markierte Inhaltsabschnitts-Tag für dieses Zeichen, falls vorhanden (ansonsten None ). Experimentelles Attribut. |
ncs | TKTK |
stroking_pattern | TKTK |
non_stroking_pattern | TKTK |
stroking_color | Die Farbe des Umrisses des Zeichens (d. h. Strich). Weitere Informationen finden Sie unter docs/colors.md. |
non_stroking_color | Die Innenfarbe des Charakters. Weitere Informationen finden Sie unter docs/colors.md. |
object_type | "verkohlen" |
Hinweis : Die matrix
eines Zeichens stellt die „aktuelle Transformationsmatrix“ dar, wie in Abschnitt 4.2.2 der PDF-Referenz (6. Auflage) beschrieben. Die Matrix steuert die Skalierung, Neigung und Positionsverschiebung des Zeichens. Die Drehung ist eine Kombination aus Skalierung und Neigung, kann jedoch in den meisten Fällen als gleichwertig mit der Neigung der x-Achse angesehen werden. Das Untermodul pdfplumber.ctm
definiert eine Klasse, CTM
, die bei diesen Berechnungen hilft. Zum Beispiel:
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
Eigentum | Beschreibung |
---|---|
page_number | Seitenzahl, auf der diese Zeile gefunden wurde. |
height | Höhe der Linie. |
width | Breite der Linie. |
x0 | Abstand des linken Endes von der linken Seite der Seite. |
x1 | Abstand des rechten Endes von der linken Seite der Seite. |
y0 | Abstand des unteren Endes vom unteren Rand der Seite. |
y1 | Abstand des oberen Endes zum unteren Ende der Seite. |
top | Abstand des Zeilenanfangs vom Seitenanfang. |
bottom | Abstand des unteren Randes der Zeile vom oberen Rand der Seite. |
doctop | Abstand des Zeilenanfangs vom oberen Rand des Dokuments. |
linewidth | Linienstärke. |
stroking_color | Die Farbe der Linie. Weitere Informationen finden Sie unter docs/colors.md. |
non_stroking_color | Die für den Linienpfad angegebene Nicht-Strichfarbe. Weitere Informationen finden Sie unter docs/colors.md. |
mcid | Die markierte Inhaltsabschnitts-ID für diese Zeile, falls vorhanden (sonst None ). Experimentelles Attribut. |
tag | Das markierte Inhaltsabschnitts-Tag für diese Zeile, falls vorhanden (ansonsten None ). Experimentelles Attribut. |
object_type | "Linie" |
rect
EigenschaftenEigentum | Beschreibung |
---|---|
page_number | Seitenzahl, auf der dieses Rechteck gefunden wurde. |
height | Höhe des Rechtecks. |
width | Breite des Rechtecks. |
x0 | Abstand der linken Seite des Rechtecks von der linken Seite der Seite. |
x1 | Abstand der rechten Seite des Rechtecks von der linken Seite der Seite. |
y0 | Abstand des unteren Randes des Rechtecks vom unteren Rand der Seite. |
y1 | Abstand des oberen Randes des Rechtecks vom unteren Rand der Seite. |
top | Abstand der Oberkante des Rechtecks von der Oberkante der Seite. |
bottom | Abstand des unteren Randes des Rechtecks vom oberen Rand der Seite. |
doctop | Abstand der Oberkante des Rechtecks von der Oberkante des Dokuments. |
linewidth | Linienstärke. |
stroking_color | Die Farbe des Umrisses des Rechtecks. Weitere Informationen finden Sie unter docs/colors.md. |
non_stroking_color | Die Füllfarbe des Rechtecks. Weitere Informationen finden Sie unter docs/colors.md. |
mcid | Die markierte Inhaltsabschnitts-ID für dieses Rect, falls vorhanden (sonst None ). Experimentelles Attribut. |
tag | Das markierte Inhaltsabschnitts-Tag für dieses Rechteck, falls vorhanden (ansonsten None ). Experimentelles Attribut. |
object_type | „richtig“ |
curve
Eigentum | Beschreibung |
---|---|
page_number | Seitenzahl, auf der diese Kurve gefunden wurde. |
pts | Eine Liste von (x, top) -Tupeln, die die Punkte auf der Kurve angeben. |
path | Eine Liste von (cmd, *(x, top)) Tupeln , die die vollständige Pfadbeschreibung beschreiben , einschließlich (zum Beispiel) Kontrollpunkten, die in Bezier-Kurven verwendet werden. |
height | Höhe des Begrenzungsrahmens der Kurve. |
width | Breite des Begrenzungsrahmens der Kurve. |
x0 | Abstand des äußersten linken Punkts der Kurve von der linken Seite der Seite. |
x1 | Abstand des äußersten rechten Punkts der Kurve von der linken Seite der Seite. |
y0 | Abstand des tiefsten Punkts der Kurve vom unteren Rand der Seite. |
y1 | Abstand des höchsten Punktes der Kurve vom unteren Rand der Seite. |
top | Abstand des höchsten Punktes der Kurve vom oberen Rand der Seite. |
bottom | Abstand des tiefsten Punkts der Kurve vom oberen Rand der Seite. |
doctop | Abstand des höchsten Punktes der Kurve vom oberen Rand des Dokuments. |
linewidth | Linienstärke. |
fill | Ob die durch den Kurvenpfad definierte Form gefüllt ist. |
stroking_color | Die Farbe des Kurvenumrisses. Weitere Informationen finden Sie unter docs/colors.md. |
non_stroking_color | Die Füllfarbe der Kurve. Weitere Informationen finden Sie unter docs/colors.md. |
dash | Ein ([dash_array], dash_phase) -Tupel, das den Strichstil der Kurve beschreibt. Einzelheiten finden Sie in Tabelle 4.6 der PDF-Spezifikation. |
mcid | Die markierte Inhaltsabschnitts-ID für diese Kurve, falls vorhanden (sonst None ). Experimentelles Attribut. |
tag | Das markierte Inhaltsabschnitts-Tag für diese Kurve, falls vorhanden (sonst None ). Experimentelles Attribut. |
object_type | "Kurve" |
Darüber hinaus bieten sowohl pdfplumber.PDF
als auch pdfplumber.Page
Zugriff auf mehrere abgeleitete Listen von Objekten: .rect_edges
(das jedes Rechteck in seine vier Linien zerlegt), .curve_edges
(das dasselbe für curve
tut) und .edges
(das kombiniert .rect_edges
, .curve_edges
und .lines
).
image
Hinweis: Obwohl die Positionierung und Eigenschaften von image
über pdfplumber
verfügbar sind, bietet diese Bibliothek keine direkte Unterstützung für die Rekonstruktion von Bildinhalten. Sehen Sie sich hierzu bitte diesen Vorschlag an.
Eigentum | Beschreibung |
---|---|
page_number | Seitenzahl, auf der das Bild gefunden wurde. |
height | Höhe des Bildes. |
width | Breite des Bildes. |
x0 | Abstand der linken Bildseite vom linken Seitenrand. |
x1 | Abstand der rechten Seite des Bildes von der linken Seite der Seite. |
y0 | Abstand des unteren Bildrandes vom unteren Rand der Seite. |
y1 | Abstand des oberen Bildrandes vom unteren Rand der Seite. |
top | Abstand des oberen Bildrandes vom oberen Seitenrand. |
bottom | Abstand des unteren Bildrandes vom oberen Seitenrand. |
doctop | Abstand der Oberkante des Rechtecks von der Oberkante des Dokuments. |
srcsize | Die Originalabmessungen des Bildes als (width, height) -Tupel. |
colorspace | Farbdomäne des Bildes (z. B. RGB). |
bits | Die Anzahl der Bits pro Farbkomponente; Beispielsweise entspricht 8 255 möglichen Werten für jede Farbkomponente (R, G und B in einem RGB-Farbraum). |
stream | Pixelwerte des Bildes als pdfminer.pdftypes.PDFStream Objekt. |
imagemask | Ein boolescher Wert, der NULL-Werte zulässt; Wenn True , „gibt an, dass die Bilddaten als Schablonenmaske zum Malen in der aktuellen Farbe verwendet werden sollen.“ |
mcid | Die markierte Inhaltsabschnitts-ID für dieses Bild, falls vorhanden (sonst None ). Experimentelles Attribut. |
tag | Das markierte Inhaltsabschnitts-Tag für dieses Bild, falls vorhanden (ansonsten None ). Experimentelles Attribut. |
object_type | "Bild" |
pdfminer.six
Wenn Sie den laparams
-Parameter pdfminer.six
-handling an pdfplumber.open(...)
übergeben, enthält das .objects
-Wörterbuch jeder Seite auch die übergeordneten Layoutobjekte von pdfminer.six
, z. B. "textboxhorizontal"
.
Die visuellen Debugging-Tools von pdfplumber
können hilfreich sein, um die Struktur einer PDF-Datei und die daraus extrahierten Objekte zu verstehen.
PageImage
mit .to_image()
Um eine beliebige Seite (einschließlich zugeschnittener Seiten) in ein PageImage
Objekt umzuwandeln, rufen Sie my_page.to_image()
auf. Sie können optional eines der folgenden Schlüsselwortargumente übergeben:
resolution
: Die gewünschte Anzahl Pixel pro Zoll. Standard: 72
. Typ: int
.width
: Die gewünschte Bildbreite in Pixel. Standard: nicht gesetzt, abhängig von resolution
. Typ: int
.height
: Die gewünschte Bildbreite in Pixel. Standard: nicht gesetzt, abhängig von resolution
. Typ: int
.antialias
: Legt fest, ob beim Erstellen des Bildes Antialiasing verwendet werden soll. Bei der Einstellung True
werden Bilder mit weniger gezackten Texten und Grafiken, aber mit größeren Dateigrößen erstellt. Standard: False
. Typ: bool
.force_mediabox
: Verwenden Sie die .mediabox
-Abmessungen der Seite anstelle der .cropbox
Abmessungen. Standard: False
. Typ: bool
.Zum Beispiel:
im = my_pdf . pages [ 0 ]. to_image ( resolution = 150 )
Über ein Skript oder eine REPL öffnet im.show()
das Bild in Ihrem lokalen Bildbetrachter. Aber auch PageImage
Objekte funktionieren gut mit Jupyter-Notebooks; Sie werden automatisch als Zellenausgaben gerendert. Zum Beispiel:
Hinweis : .to_image(...)
funktioniert wie erwartet mit Page.crop(...)
/ CroppedPage
Instanzen, kann jedoch keine Änderungen übernehmen, die über Page.filter(...)
/ FilteredPage
Instanzen vorgenommen wurden.
PageImage
MethodenVerfahren | Beschreibung |
---|---|
im.reset() | Löscht alles, was Sie bisher gezeichnet haben. |
im.copy() | Kopiert das Bild in ein neues PageImage Objekt. |
im.show() | Öffnet das Bild in Ihrem lokalen Bildbetrachter. |
im.save(path_or_fileobject, format="PNG", quantize=True, colors=256, bits=8) | Speichert das mit Anmerkungen versehene Bild als PNG-Datei. Die Standardargumente quantisieren das Bild auf eine Palette von 256 Farben und speichern das PNG mit 8-Bit-Farbtiefe. Sie können die Quantisierung deaktivieren, indem Sie quantize=False übergeben, oder die Größe der Farbpalette anpassen, indem Sie colors=N übergeben. |
Sie können diesen Methoden explizite Koordinaten oder jedes beliebige pdfplumber
PDF-Objekt (z. B. char, line, rect) übergeben.
Einzelobjektmethode | Massenmethode | Beschreibung |
---|---|---|
im.draw_line(line, stroke={color}, stroke_width=1) | im.draw_lines(list_of_lines, **kwargs) | Zeichnet eine Linie aus einer line , curve oder einem 2-Tupel von 2-Tupeln (z. B. ((x, y), (x, y)) ). |
im.draw_vline(location, stroke={color}, stroke_width=1) | im.draw_vlines(list_of_locations, **kwargs) | Zeichnet eine vertikale Linie an der durch location angegebenen x-Koordinate. |
im.draw_hline(location, stroke={color}, stroke_width=1) | im.draw_hlines(list_of_locations, **kwargs) | Zeichnet eine horizontale Linie an der durch location angegebenen Y-Koordinate. |
im.draw_rect(bbox_or_obj, fill={color}, stroke={color}, stroke_width=1) | im.draw_rects(list_of_rects, **kwargs) | Zeichnet ein Rechteck aus einem rect , char usw. oder einem 4-Tupel-Begrenzungsrahmen. |
im.draw_circle(center_or_obj, radius=5, fill={color}, stroke={color}) | im.draw_circles(list_of_circles, **kwargs) | Zeichnet einen Kreis an der (x, y) -Koordinate oder in der Mitte eines char , rect usw. |
Hinweis: Die oben genannten Methoden basieren auf ImageDraw
Methoden von Pillow, die Parameter wurden jedoch aus Gründen der Konsistenz mit fill
/ stroke
/ stroke_width
-Nomenklatur von SVG optimiert.
im.debug_tablefinder(table_settings={})
gibt eine Version des PageImage mit den erkannten Linien (in Rot), Schnittpunkten (Kreisen) und Tabellen (hellblau) überlagert zurück.
pdfplumber
kann Text aus jeder beliebigen Seite extrahieren (einschließlich beschnittener und abgeleiteter Seiten). Es kann auch versuchen, das Layout dieses Textes beizubehalten und die Koordinaten von Wörtern und Suchanfragen zu identifizieren. Page
können die folgenden Textextraktionsmethoden aufrufen:
Verfahren | Beschreibung |
---|---|
.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) | Fasst alle Zeichenobjekte der Seite in einer einzigen Zeichenfolge zusammen.
|
.extract_text_simple(x_tolerance=3, y_tolerance=3) | Eine etwas schnellere, aber weniger flexible Version von .extract_text(...) mit einer einfacheren Logik. |
.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) | Gibt eine Liste aller wortähnlichen Dinge und ihrer Begrenzungsrahmen zurück. Als Wörter werden Zeichenfolgen betrachtet, bei denen (bei „aufrechten“ Zeichen) die Differenz zwischen x1 eines Zeichens und x0 des nächsten kleiner oder gleich x_tolerance ist und bei denen der doctop eines Zeichens und der doctop des nächsten Zeichens kleiner oder gleich x_tolerance ist ist kleiner oder gleich y_tolerance . (Wenn x_tolerance_ratio nicht None ist, verwendet der Extraktor eine dynamische x_tolerance gleich x_tolerance_ratio * previous_character["size"] .) Ein ähnlicher Ansatz wird für nicht aufrechte Zeichen gewählt, wobei jedoch stattdessen die vertikalen und nicht die horizontalen Abstände zwischen ihnen gemessen werden. Wenn Sie keep_blank_chars auf True ändern, werden Leerzeichen als Teil eines Wortes und nicht als Leerzeichen zwischen Wörtern behandelt. Wenn Sie use_text_flow auf True ändern, wird der zugrunde liegende Zeichenfluss der PDF-Datei als Leitfaden für die Reihenfolge und Segmentierung der Wörter verwendet, anstatt die Zeichen nach x/y-Position vorzusortieren. (Dies ahmt nach, wie das Ziehen eines Cursors Text in einer PDF-Datei hervorhebt; dabei erscheint die Reihenfolge nicht immer logisch.) Die Argumente line_dir und char_dir teilen dieser Methode die Richtung mit, in der Zeilen/Zeichen voraussichtlich gelesen werden; Gültige Optionen sind „ttb“ (von oben nach unten), „btt“ (von unten nach oben), „ltr“ (von links nach rechts) und „rtl“ (von rechts nach links). Die Argumente line_dir_rotated und char_dir_rotated sind ähnlich, jedoch für Text, der gedreht wurde. Die Übergabe einer Liste von extra_attrs (z. B. ["fontname", "size"] beschränkt jedes Wort auf Zeichen, die für jedes dieser Attribute genau den gleichen Wert haben, und die resultierenden Wortdiktate geben diese Attribute an. Wenn Sie split_at_punctuation auf True setzen, wird dies geschehen Erzwingen Sie Trennzeichen bei Satzzeichen, die durch string.punctuation angegeben werden, oder Sie können die Liste der trennenden Satzzeichen angeben, indem Sie eine Zeichenfolge übergeben, z. B. split_at_punctuation='!"&'()*+,.:;<=>?@[]^`{|}~' . Sofern Sie nicht expand_ligatures=False festlegen, werden Ligaturen wie fi in ihre konstituierenden Buchstaben erweitert (z. B , fi ). Durch die Übergabe von return_chars=True wird zu jedem Wortwörterbuch eine Liste seiner konstituierenden Zeichen als Liste im Feld "chars" hinzugefügt. |
.extract_text_lines(layout=False, strip=True, return_chars=True, **kwargs) | Experimentelle Funktion , die eine Liste von Wörterbüchern zurückgibt, die die Textzeilen auf der Seite darstellen. Der Parameter strip funktioniert analog zur Methode str.strip() von Python und gibt text ohne die sie umgebenden Leerzeichen zurück. (Nur relevant, wenn layout = True .) Wenn Sie return_chars auf False setzen, werden die einzelnen Zeichenobjekte von den zurückgegebenen Textzeilen-Dikten ausgeschlossen. Die verbleibenden **kwargs sind diejenigen, die Sie an .extract_text(layout=True, ...) übergeben würden. |
.search(pattern, regex=True, case=True, main_group=0, return_groups=True, return_chars=True, layout=False, **kwargs) | Experimentelle Funktion , mit der Sie den Text einer Seite durchsuchen und eine Liste aller Instanzen zurückgeben können, die mit der Abfrage übereinstimmen. Für jede Instanz enthält das Antwortwörterbuchobjekt den übereinstimmenden Text, alle Übereinstimmungen der Regex-Gruppe, die Koordinaten des Begrenzungsrahmens und die char-Objekte selbst. pattern kann ein kompilierter regulärer Ausdruck, ein nicht kompilierter regulärer Ausdruck oder eine Nicht-Regex-Zeichenfolge sein. Wenn regex False hat, wird das Muster als Nicht-Regex-Zeichenfolge behandelt. Wenn case False hat, wird die Suche ohne Berücksichtigung der Groß- und Kleinschreibung durchgeführt. Durch das Festlegen von main_group werden die Ergebnisse auf eine bestimmte Regex-Gruppe innerhalb des pattern beschränkt (der Standardwert 0 bedeutet die gesamte Übereinstimmung). Wenn Sie return_groups und/oder return_chars auf False setzen, werden die Listen der übereinstimmenden Regex-Gruppen und/oder Zeichen vom Hinzufügen ausgeschlossen (als "groups" und "chars" zu den Rückgabedikten). Der layout Parameter funktioniert wie für .extract_text(...) . Die verbleibenden **kwargs sind diejenigen, die Sie an .extract_text(layout=True, ...) übergeben würden. Hinweis : Übereinstimmungen mit einer Breite von Null und ausschließlich Leerzeichen werden verworfen, da sie (im Allgemeinen) keine explizite Position auf der Seite haben. |
.dedupe_chars(tolerance=1, extra_attrs=("fontname", "size")) | Gibt eine Version der Seite zurück, bei der doppelte Zeichen – solche mit demselben Text, derselben Positionierung (innerhalb tolerance x/y) und extra_attrs wie andere Zeichen – entfernt wurden. (Siehe Ausgabe Nr. 71, um die Motivation zu verstehen.) |
Der Ansatz von pdfplumber
zur Tabellenerkennung lehnt sich stark an Anssi Nurminens Masterarbeit an und ist von Tabula inspiriert. Es funktioniert so:
pdfplumber.Page
-Objekte können die folgenden Tabellenmethoden aufrufen:
Verfahren | Beschreibung |
---|---|
.find_tables(table_settings={}) | Gibt eine Liste von Table -Objekten zurück. Das Table Objekt bietet Zugriff auf die Eigenschaften .cells , .rows , .columns und .bbox sowie auf die Methode .extract(x_tolerance=3, y_tolerance=3) . |
.find_table(table_settings={}) | Ähnlich wie .find_tables(...) , gibt jedoch die größte Tabelle auf der Seite als Table -Objekt zurück. Wenn mehrere Tabellen die gleiche Größe haben – gemessen an der Anzahl der Zellen – gibt diese Methode die Tabelle zurück, die sich am nächsten am oberen Rand der Seite befindet. |
.extract_tables(table_settings={}) | Gibt den aus allen auf der Seite gefundenen Tabellen extrahierten Text zurück, dargestellt als Liste von Listen mit der Struktur table -> row -> cell . |
.extract_table(table_settings={}) | Gibt den Text zurück, der aus der größten Tabelle auf der Seite extrahiert wurde (siehe .find_table(...) oben), dargestellt als Liste von Listen, mit der Struktur row -> cell . |
.debug_tablefinder(table_settings={}) | Gibt eine Instanz der TableFinder -Klasse mit Zugriff auf die Eigenschaften .edges , .intersections , .cells und .tables zurück. |
Zum Beispiel:
pdf = pdfplumber . open ( "path/to/my.pdf" )
page = pdf . pages [ 0 ]
page . extract_table ()
Klicken Sie hier für ein detaillierteres Beispiel.
Standardmäßig verwendet extract_tables
die vertikalen und horizontalen Linien (oder Rechteckkanten) der Seite als Zelltrennzeichen. Die Methode ist jedoch über das Argument table_settings
in hohem Maße anpassbar. Die möglichen Einstellungen und ihre Standardeinstellungen:
{
"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
}
Einstellung | Beschreibung |
---|---|
"vertical_strategy" | Entweder "lines" , "lines_strict" , "text" oder "explicit" . Siehe Erklärung unten. |
"horizontal_strategy" | Entweder "lines" , "lines_strict" , "text" oder "explicit" . Siehe Erklärung unten. |
"explicit_vertical_lines" | Eine Liste vertikaler Linien, die Zellen in der Tabelle explizit abgrenzen. Kann in Kombination mit einer der oben genannten Strategien verwendet werden. Elemente in der Liste sollten entweder Zahlen sein – die die x -Koordinate einer Linie über die gesamte Höhe der Seite angeben – oder line / rect / curve sein. |
"explicit_horizontal_lines" | Eine Liste horizontaler Linien, die Zellen in der Tabelle explizit abgrenzen. Kann in Kombination mit einer der oben genannten Strategien verwendet werden. Elemente in der Liste sollten entweder Zahlen sein – die die y -Koordinate einer Linie über die gesamte Höhe der Seite angeben – oder line / rect / curve sein. |
"snap_tolerance" , "snap_x_tolerance" , "snap_y_tolerance" | Parallele Linien innerhalb von snap_tolerance -Punkten werden an derselben horizontalen oder vertikalen Position „eingefangen“. |
"join_tolerance" , "join_x_tolerance" , "join_y_tolerance" | Liniensegmente auf derselben unendlichen Linie, deren Enden innerhalb join_tolerance voneinander liegen, werden zu einem einzigen Liniensegment „verbunden“. |
"edge_min_length" | Kanten, die kürzer als edge_min_length sind, werden verworfen, bevor versucht wird, die Tabelle wiederherzustellen. |
"min_words_vertical" | Bei Verwendung von "vertical_strategy": "text" müssen mindestens min_words_vertical Wörter dieselbe Ausrichtung haben. |
"min_words_horizontal" | Bei Verwendung von "horizontal_strategy": "text" müssen mindestens min_words_horizontal Wörter die gleiche Ausrichtung haben. |
"intersection_tolerance" , "intersection_x_tolerance" , "intersection_y_tolerance" | Beim Kombinieren von Kanten zu Zellen müssen orthogonale Kanten innerhalb von intersection_tolerance liegen, um als sich schneidend zu gelten. |
"text_*" | Alle Einstellungen mit dem Präfix text_ werden dann beim Extrahieren von Text aus jeder erkannten Tabelle verwendet. Alle möglichen Argumente für Page.extract_text(...) sind auch hier gültig. |
"text_x_tolerance" , "text_y_tolerance" | Diese text_ -präfixierten Einstellungen gelten auch für den Tabellenidentifikationsalgorithmus, wenn die text verwendet wird. Wenn dieser Algorithmus beispielsweise nach Wörtern sucht, geht er davon aus, dass die einzelnen Buchstaben in jedem Wort nicht mehr als text_x_tolerance / text_y_tolerance Punkte voneinander entfernt sind. |
Sowohl vertical_strategy
als auch horizontal_strategy
akzeptieren die folgenden Optionen:
Strategie | Beschreibung |
---|---|
"lines" | Verwenden Sie die grafischen Linien der Seite – einschließlich der Seiten rechteckiger Objekte – als Ränder potenzieller Tabellenzellen. |
"lines_strict" | Verwenden Sie die grafischen Linien der Seite – jedoch nicht die Seiten von Rechteckobjekten – als Ränder potenzieller Tabellenzellen. |
"text" | Für vertical_strategy : Leiten Sie die (imaginären) Linien ab, die die linke, rechte oder die Mitte der Wörter auf der Seite verbinden, und verwenden Sie diese Linien als Ränder potenzieller Tabellenzellen. Für horizontal_strategy das Gleiche, jedoch unter Verwendung der Anfangsbuchstaben der Wörter. |
"explicit" | Verwenden Sie nur die Linien, die explizit in explicit_vertical_lines / explicit_horizontal_lines definiert sind. |
Oft ist es hilfreich, eine Seite zuzuschneiden – Page.crop(bounding_box)
– bevor Sie versuchen, die Tabelle zu extrahieren.
Die Tabellenextraktion für pdfplumber
wurde für v0.5.0
grundlegend überarbeitet und führte zu wichtigen Änderungen.
Manchmal können PDF-Dateien Formulare enthalten, die Eingaben enthalten, die Benutzer ausfüllen und speichern können. Während Werte in Formularfeldern wie anderer Text in einer PDF-Datei aussehen, werden Formulardaten anders gehandhabt. Wenn Sie die blutrünstigen Details erfahren möchten, lesen Sie Seite 671 dieser Spezifikation.
pdfplumber
verfügt nicht über eine Schnittstelle zum Arbeiten mit Formulardaten, Sie können jedoch über die Wrapper von pdfplumber
rund um pdfminer
darauf zugreifen.
Dieses Snippet ruft beispielsweise Formularfeldnamen und -werte ab und speichert sie in einem Wörterbuch.
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 )
Sobald Sie dieses Skript ausführen, ist form_data
eine Liste, die für jedes Formularelement ein Tupel mit drei Elementen enthält. Ein PDF-Formular mit einem Stadt- und Bundeslandfeld könnte beispielsweise so aussehen.
[
['STATE.0', 'enter STATE', 'CA'],
['section 2 accident infoRmation.1.0',
'enter city of accident',
'SAN FRANCISCO']
]
Vielen Dank an @jeremybmerrill für die Hilfe bei der Pflege des obigen Formularparsing-Codes.
extract_table
in einem WARN-Bericht (California Worker Adjustment and Retraining Notification). Demonstriert grundlegendes visuelles Debuggen und Tabellenextraktion.extract_table
in den PDFs des National Instant Criminal Background Check System des FBI. Demonstriert, wie Sie mithilfe des visuellen Debuggens optimale Einstellungen für die Tabellenextraktion finden. Demonstriert außerdem Page.crop(...)
und Page.extract_text(...).
curve
prüfen und visualisieren.Page.extract_text(...)
. Mehrere andere Python-Bibliotheken helfen Benutzern beim Extrahieren von Informationen aus PDFs. Im Großen und Ganzen unterscheidet sich pdfplumber
von anderen PDF-Verarbeitungsbibliotheken durch die Kombination dieser Funktionen:
Es ist auch hilfreich zu wissen, welche Funktionen pdfplumber
nicht bietet:
pdfminer.six
bildet die Grundlage für pdfplumber
. Es konzentriert sich hauptsächlich auf das Parsen von PDFs, die Analyse von PDF-Layouts und Objektpositionierung sowie das Extrahieren von Text. Es bietet keine Tools zum Extrahieren von Tabellen oder zum visuellen Debuggen.
PyPDF2
ist eine reine Python-Bibliothek, „die in der Lage ist, die Seiten von PDF-Dateien zu teilen, zusammenzuführen, zuzuschneiden und zu transformieren. Sie kann PDF-Dateien auch benutzerdefinierte Daten, Anzeigeoptionen und Passwörter hinzufügen.“ Es kann Seitentext extrahieren, bietet jedoch keinen einfachen Zugriff auf Formobjekte (Rechtecke, Linien usw.), Tabellenextraktion oder visuelle Debugging-Tools.
pymupdf
ist wesentlich schneller als pdfminer.six
(und damit auch pdfplumber
) und kann PDFs generieren und ändern, aber die Bibliothek erfordert die Installation von Nicht-Python-Software (MuPDF). Es ermöglicht außerdem keinen einfachen Zugriff auf Formobjekte (Rechtecke, Linien usw.) und bietet keine Tabellenextraktions- oder visuellen Debugging-Tools.
camelot
, tabula-py
und pdftables
konzentrieren sich alle hauptsächlich auf das Extrahieren von Tabellen. In einigen Fällen sind sie möglicherweise besser für die jeweiligen Tabellen geeignet, die Sie extrahieren möchten.
Vielen Dank an die folgenden Benutzer, die Ideen, Funktionen und Korrekturen beigesteuert haben:
Pull-Requests sind willkommen, aber bitte reichen Sie zuerst ein Vorschlagsproblem ein, da sich die Bibliothek in der aktiven Entwicklung befindet.
Aktuelle Betreuer: