Zum Inhalt springen

Python-CLI

Mit dem Befehl nextpdf führen Sie die PDF-Extraktion im Terminal aus. Sie richten ihn auf einen NextPDF Connect-Endpunkt aus, übergeben ein PDF und erhalten eine strukturierte Ausgabe — zitierten Text, Tabellen, den vollständigen semantischen Abstract Syntax Tree (AST) oder eine Metadatenzusammenfassung — auf der Standardausgabe (stdout) oder in einer Datei.

Der Befehl nextpdf ist eine Click-Befehlsgruppe. Verbindungs- und Sitzungsoptionen — --base-url, --api-key, --log-level, --output/-o und --strict — sind an der Gruppe definiert; Sie platzieren sie also vor dem Unterbefehl. Der Unterbefehl und seine eigenen Optionen (etwa --format oder --page) folgen danach:

nextpdf [GROUP OPTIONS] COMMAND [SUBCOMMAND] PDF_PATH [COMMAND OPTIONS]

Eine Gruppenoption hinter dem Unterbefehl schlägt fehl. nextpdf info document.pdf --base-url ... meldet zum Beispiel Error: No such option: --base-url und beendet sich mit Status 2, weil --base-url beim Parsen durch Click bereits dem Unterbefehl info zugeordnet ist, der diese Option nicht definiert.

Der klarste Weg, die Reihenfolgefalle zu vermeiden, besteht darin, die Zugangsdaten über Umgebungsvariablen bereitzustellen (siehe Einmal pro Shell konfigurieren). Die folgenden Beispiele zeigen zuerst die Form mit expliziten Flags, damit die richtige Reihenfolge klar ist.

Text als JSON extrahieren:

Terminal-Fenster
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract text document.pdf

Tabellen als kommagetrennte Werte (CSV) extrahieren:

Terminal-Fenster
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract tables invoice.pdf --format csv

Dokument-Metadaten und -Struktur untersuchen:

Terminal-Fenster
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" info document.pdf

Den vollständigen semantischen AST abrufen:

Terminal-Fenster
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" ast document.pdf

Die installierte SDK-Version ausgeben, ohne einen Server zu kontaktieren:

Terminal-Fenster
nextpdf version

Der Befehl version ist der einzige Befehl, der weder --base-url noch --api-key benötigt. Jeder andere Befehl kontaktiert den Server und benötigt beide.

Jedes Beispiel liest den API-Schlüssel aus der Umgebungsvariablen NEXTPDF_API_KEY, statt ihn in die Kommandozeile einzubetten. Behandeln Sie den Schlüssel als Geheimnis. Ein direkt in der Kommandozeile angegebener Schlüssel ist in Ihrer Shell-Historie und in der Prozessliste (ps) für andere Benutzer auf dem Host sichtbar.

Diese Optionen platzieren Sie vor dem Unterbefehl. Jede Verbindungsoption liest auch aus einer Umgebungsvariablen, sodass Sie das Flag weglassen können, wenn die Variable gesetzt ist.

OptionUmgebungsvariableStandardZweck
--base-urlNEXTPDF_BASE_URL(erforderlich)URL des NextPDF Connect-Servers.
--api-keyNEXTPDF_API_KEY(erforderlich)API-Schlüssel für die Bearer-Authentifizierung.
--log-levelwarningProtokollausführlichkeit: debug, info, warning oder error. Protokolle werden an die Standardfehlerausgabe (stderr) geschrieben.
--output, -ostdoutSchreibt die Befehlsausgabe in eine Datei statt nach stdout.
--strictoffFür zukünftige Verwendung reserviert. Das Flag wird heute geparst, ändert aber das Verhalten nicht.
--help, -hZeigt die Hilfe an und beendet den Befehl.

Die Werte für --base-url und --api-key sind für jeden Befehl außer version erforderlich. Fehlt einer von beiden — weder Flag noch Umgebungsvariable —, gibt der Befehl einen Fehler aus und beendet sich mit Status 1.

Extrahiert zitierte Textblöcke. Jeder Block trägt einen Zitatanker (Knotenbezeichner, Seitenindex, Begrenzungsrahmen und einen Konfidenzwert).

nextpdf [GROUP OPTIONS] extract text PDF_PATH [--format FORMAT] [--page N] [--headings-only]
OptionWerteStandardZweck
--formatjson, markdown, plainjsonAusgabeformat.
--pageGanzzahlalle SeitenExtrahiert nur die Seite mit diesem 0-basierten Seitenindex.
--headings-onlyFlagoffExtrahiert nur Überschriftenknoten.

PDF_PATH ist ein Dateipfad oder -, um PDF-Bytes von stdin zu lesen.

Extrahiert jede Tabelle mit Zitatankern und zellgenauer Struktur.

nextpdf [GROUP OPTIONS] extract tables PDF_PATH [--format FORMAT] [--page-start N] [--page-end N]
OptionWerteStandardZweck
--formatjson, csvjsonAusgabeformat.
--page-startGanzzahlerste SeiteStartseitenindex (0-basiert).
--page-endGanzzahlletzte SeiteEndseitenindex (0-basiert).

PDF_PATH ist ein Dateipfad oder -, um von stdin zu lesen.

Gibt den vollständigen semantischen AST als JSON zurück: einen hierarchischen Baum aus Knoten (Überschriften, Absätze, Tabellen, Listen, Abbildungen) mit Begrenzungsrahmen und Textinhalten.

nextpdf [GROUP OPTIONS] ast PDF_PATH [--page-start N] [--page-end N] [--token-budget N]
OptionWerteStandardZweck
--page-startGanzzahlerste SeiteStartseitenindex (0-basiert).
--page-endGanzzahlletzte SeiteEndseitenindex (0-basiert).
--token-budgetGanzzahlunbegrenztUngefähres Tokenlimit für den zurückgegebenen AST.

PDF_PATH ist ein Dateipfad oder -, um von stdin zu lesen. Der Befehl ast erzeugt einen einzelnen Dokumentbaum; er vergleicht keine zwei PDFs. Informationen zum strukturellen Diffing finden Sie unter Recipe: Zwei PDF-Revisionen vergleichen.

Gibt eine kompakte JSON-Zusammenfassung eines Dokuments aus: Schemaversion, Quellhash, Seitenzahl, geschätzte Tokenanzahl, den Typ des Wurzelknotens und die Anzahl der direkten Kindknoten der Wurzel.

nextpdf [GROUP OPTIONS] info PDF_PATH

PDF_PATH ist ein Dateipfad oder -, um von stdin zu lesen.

Gibt die installierte SDK-Version aus (zum Beispiel nextpdf 1.1.0) und beendet den Befehl. Dieser Befehl kontaktiert keinen Server und benötigt keine Zugangsdaten.

nextpdf version

Setzen Sie die Verbindungsoptionen einmal als Umgebungsvariablen und lassen Sie die wiederholten Flags weg. Diese Form vermeidet zudem die Reihenfolgefalle der Optionen vollständig, weil die Zugangsdaten nie auf der Kommandozeile erscheinen.

Terminal-Fenster
export NEXTPDF_BASE_URL=http://localhost:8080
export NEXTPDF_API_KEY=your-key
nextpdf extract text document.pdf

Unter Windows PowerShell:

Terminal-Fenster
$env:NEXTPDF_BASE_URL = "http://localhost:8080"
$env:NEXTPDF_API_KEY = "your-key"
nextpdf extract text document.pdf

Laden Sie den Schlüssel vorzugsweise aus einem Secret-Store oder einer .env-Datei, die Sie aus der Versionsverwaltung heraushalten. Fügen Sie keinen Produktionsschlüssel in eine gemeinsam genutzte Terminalsitzung oder in ein Skript ein, das Sie einchecken.

Sie wählen das Ausgabeformat pro Befehl mit --format. Die Befehle für Text und Tabellen unterstützen mehr als ein Format; ast und info geben immer JSON aus.

BefehlFormateStandard
extract textjson, markdown, plainjson
extract tablesjson, csvjson
astjsonjson
infojsonjson

Wählen Sie JSON, wenn ein nachgelagertes Programm Seitenindizes, Konfidenzwerte oder Knotenbezeichner benötigt. Wählen Sie CSV, wenn eine Tabellenkalkulation oder eine tabellarische Pipeline die Tabellen verarbeitet. Wählen Sie plain oder markdown, wenn eine Person oder ein reines Text-Tool das Ergebnis liest.

Der Textbefehl gibt ein JSON-Array zitierter Blöcke aus. Jeder Block hat text, ein citation-Objekt (node_id, page_index, bbox, confidence) und ein optionales node_type. Schreiben Sie die Ausgabe mit --output in eine Datei (oder leiten Sie stdout um) und parsen Sie sie anschließend.

Dieses Shell-Beispiel verwendet jq, um nur Überschriften auf Seite 0 zu behalten:

Terminal-Fenster
nextpdf --output blocks.json extract text report.pdf --format json
jq '[.[] | select(.citation.page_index == 0 and .node_type == "heading") | .text]' blocks.json

Dieselben Daten lassen sich sauber in Python parsen. Die CLI schreibt ein JSON-Array; Sie laden es also mit der Standardbibliothek und lesen die typisierten Felder:

"""Parse cited text blocks emitted by `nextpdf extract text --format json`."""
import json
from pathlib import Path
def load_headings(blocks_path: Path) -> list[str]:
"""Return the text of every heading block on page 0.
Args:
blocks_path: Path to the JSON file written by `nextpdf extract text`.
Returns:
The text of each heading-type block whose citation is on page 0.
"""
raw = blocks_path.read_text(encoding="utf-8")
blocks: list[dict[str, object]] = json.loads(raw)
headings: list[str] = []
for block in blocks:
citation = block["citation"]
if block.get("node_type") == "heading" and citation["page_index"] == 0:
headings.append(str(block["text"]))
return headings
if __name__ == "__main__":
for heading in load_headings(Path("blocks.json")):
print(heading)

Wenn Sie die validierten, typisierten Modelle statt roher Dictionaries benötigen, rufen Sie das SDK direkt auf, anstatt die CLI-Ausgabe zu parsen. Siehe die Python-Übersicht für den NextPDF-Client und seinen Rückgabetyp CitedTextBlock.

Mit --format csv schreibt der Tabellenbefehl einen CSV-Block pro Tabelle. Eine Kommentarzeile, # Table N (pM), steht vor jeder Tabelle und nennt ihre 1-basierte Tabellennummer und ihren 0-basierten Seitenindex. Eine Leerzeile trennt aufeinanderfolgende Tabellen. Die CLI maskiert Zellwerte und escaped sie mit Pythons csv-Modul, sodass Werte mit Kommas, Anführungszeichen oder Zeilenumbrüchen sicher erhalten bleiben.

Terminal-Fenster
nextpdf --output tables.csv extract tables statement.pdf --format csv

Da die Datei mehrere CSV-Blöcke enthält, teilen Sie sie an den Kommentarzeilen auf, bevor Sie jeden Block als eigenständige Tabelle parsen:

"""Split multi-table CSV output from `nextpdf extract tables --format csv`."""
import csv
import io
from pathlib import Path
def read_tables(csv_path: Path) -> list[list[list[str]]]:
"""Parse the multi-block CSV file into a list of tables.
Each table is a list of rows; each row is a list of cell strings.
The leading `# Table N (pM)` comment row is dropped from every table.
Args:
csv_path: Path to the file written by `nextpdf extract tables`.
Returns:
One parsed table per `# Table` block in the file.
"""
text = csv_path.read_text(encoding="utf-8")
tables: list[list[list[str]]] = []
current: list[str] = []
for line in text.splitlines(keepends=True):
if line.startswith("# Table ") and current:
tables.append(_parse_block(current))
current = []
current.append(line)
if current:
tables.append(_parse_block(current))
return tables
def _parse_block(lines: list[str]) -> list[list[str]]:
"""Parse one CSV block, discarding its leading comment row."""
reader = csv.reader(io.StringIO("".join(lines)))
rows = [row for row in reader if row]
return rows[1:] if rows and rows[0] and rows[0][0].startswith("# Table ") else rows
if __name__ == "__main__":
for index, table in enumerate(read_tables(Path("tables.csv")), start=1):
print(f"table {index}: {len(table)} rows")

Die CLI verwendet drei Exit-Codes. Prüfen Sie $? in Shell-Skripten (oder $LASTEXITCODE in PowerShell), um auf Erfolg oder Fehler zu verzweigen, und lesen Sie Diagnosemeldungen von stderr, das von den Daten auf stdout getrennt bleibt.

Exit-CodeBedeutungBeispiele
0Erfolg.Ein Befehl wurde erfolgreich abgeschlossen; version wurde ausgegeben.
1Laufzeitfehler. Die CLI gibt Error: <message> nach stderr aus.Eingabedatei nicht gefunden oder keine reguläre Datei, leeres stdin, fehlendes oder ungültiges --base-url/--api-key, jeder serverseitige Fehler (Lizenz erforderlich, Kontingent überschritten, ungetaggtes PDF, Build-Timeout oder ein anderer API-Fehler).
2Verwendungsfehler, von Click gemeldet.Unbekannter Befehl oder unbekannte Option (einschließlich einer Gruppenoption hinter dem Unterbefehl), ein fehlendes erforderliches Argument wie PDF_PATH.

Jeder serverseitige Fehler erscheint als Exit-Code 1 mit einer menschenlesbaren Meldung auf stderr. Das SDK löst eine typisierte Ausnahme aus — NextPDFLicenseError (HTTP 402), QuotaExceededError (HTTP 429), AstNoStructTreeError (HTTP 422, ungetaggtes PDF), AstBuildTimeoutError (HTTP 504) oder die Basisklasse NextPDFAPIError. Die CLI fängt sie alle über ihre gemeinsame Basisklasse NextPDFError ab, gibt die Meldung aus und beendet sich mit 1. Die CLI stellt keine eigenen Exit-Codes pro Fehlertyp bereit. Um in einem Skript etwa einen Kontingentfehler von einem Lizenzfehler zu unterscheiden, prüfen Sie den Meldungstext auf stderr oder rufen Sie das SDK direkt auf (siehe die Python-Übersicht für die Ausnahmeklassen).

Ein Skriptmuster, das Daten und Diagnosen trennt:

#!/usr/bin/env bash
set -euo pipefail
# Credentials come from the environment, not the command line.
: "${NEXTPDF_BASE_URL:?set NEXTPDF_BASE_URL}"
: "${NEXTPDF_API_KEY:?set NEXTPDF_API_KEY}"
if nextpdf --output contract.ast.json ast contract.pdf; then
echo "AST written to contract.ast.json"
else
status=$?
echo "nextpdf failed with exit code ${status}" >&2
exit "${status}"
fi

Beachten Sie, dass --output die Daten in die genannte Datei schreibt und nur die Bestätigungszeile Written to <path> nach stderr ausgibt, sodass stdout leer bleibt. Ohne --output gehen die Daten nach stdout, und Sie können sie umleiten.

Jedes der folgenden Recipes verwendet ausschließlich verifizierte Befehle und Flags. Die Zugangsdaten kommen in jedem Fall aus der Umgebung.

Verwandeln Sie einen Ordner voller Rechnungen für eine Tabellenkalkulations- oder Buchhaltungs-Pipeline in je eine CSV-Datei pro Dokument:

#!/usr/bin/env bash
set -euo pipefail
: "${NEXTPDF_BASE_URL:?set NEXTPDF_BASE_URL}"
: "${NEXTPDF_API_KEY:?set NEXTPDF_API_KEY}"
mkdir -p out
for pdf in invoices/*.pdf; do
name="$(basename "${pdf}" .pdf)"
nextpdf --output "out/${name}.csv" extract tables "${pdf}" --format csv
done

Jede out/<name>.csv enthält einen CSV-Block pro erkannter Tabelle, mit einem vorangestellten # Table N (pM)-Header. Parsen Sie die Blöcke mit dem oben gezeigten CSV-Reader.

Kombinieren Sie --headings-only mit dem Format markdown, um schnell eine Gliederung zu erzeugen, die Sie lesen oder in Notizen einfügen können:

Terminal-Fenster
nextpdf --output outline.md extract text whitepaper.pdf --headings-only --format markdown

Der Befehl ast der CLI gibt den Baum für ein einzelnes Dokument zurück; er hat keinen Diff-Unterbefehl. Strukturelles Diffing liegt im SDK als client.ast.get_ast_diff(...) und im Model Context Protocol (MCP)-Server als Tool nextpdf_diff vor. Führen Sie den Diff über das SDK aus:

"""Compare two PDF revisions structurally with the NextPDF SDK.
The API key is read from the environment, never hard-coded.
"""
import os
from pathlib import Path
from nextpdf import NextPDF
def diff_revisions(original: Path, modified: Path) -> None:
"""Print a structural diff summary between two PDF revisions.
Args:
original: Path to the earlier PDF revision.
modified: Path to the later PDF revision.
"""
base_url = os.environ["NEXTPDF_BASE_URL"]
api_key = os.environ["NEXTPDF_API_KEY"]
client = NextPDF(base_url=base_url, api_key=api_key)
result = client.ast.get_ast_diff(
original.read_bytes(),
modified.read_bytes(),
)
summary = result.summary
print(f"added: {summary.added_node_count}")
print(f"removed: {summary.removed_node_count}")
print(f"changed: {summary.changed_node_count}")
for entry in result.diff:
preview = entry.text_preview or ""
print(f" {entry.type:<8} {entry.node_type:<12} p{entry.page_index} {preview}")
if __name__ == "__main__":
diff_revisions(Path("contract-v1.pdf"), Path("contract-v2.pdf"))

Um denselben Diff aus einem KI-Agenten statt aus einem Skript auszuführen, registrieren Sie den MCP-Server und rufen Sie das Tool nextpdf_diff auf. Siehe die Seite Python-MCP-Server.

Lesen Sie PDF-Bytes mit - von stdin, um nextpdf an ein Tool anzuschließen, das ein PDF auf stdout ausgibt:

Terminal-Fenster
curl --silent https://example.com/report.pdf | nextpdf info -

Das Argument - weist den Befehl an, das Dokument von stdin zu lesen. Gehen keine Bytes ein, meldet der Befehl einen Fehler und beendet sich mit 1.

Die CLI baut jede Antwort im Speicher auf und schreibt sie einmal, sodass das Umleiten oder Weiterleiten der Ausgabe unkompliziert ist, die Ausgabe aber nicht inkrementell erzeugt wird. Ein großer AST oder Tabellensatz wird vollständig gepuffert, bevor das erste Byte stdout oder die --output-Datei erreicht. Planen Sie Speicher und Latenz für Antworten über das gesamte Dokument ein, nicht für einen Stream.

Jeder Aufruf von nextpdf erstellt einen frischen Client und eine frische HTTP-Verbindung, sodass eine Schleife über viele Dateien pro Datei eine Verbindung öffnet und schließt. Die Verbindungskosten sind neben der serverseitigen Extraktionszeit meist gering, verursachen im großen Maßstab aber realen Overhead.

  • Einen Endpunkt wiederverwenden. Richten Sie jeden Aufruf auf dasselbe NextPDF Connect-Deployment, damit der Server aufgewärmte Caches und Connection-Pools wiederverwendet. Vermeiden Sie es, einen Batch über mehrere Endpunkte zu verteilen, sofern Sie nicht bewusst Lastverteilung betreiben.
  • Begrenzen Sie die Arbeit pro Aufruf. Verwenden Sie --page, --page-start/--page-end oder --token-budget, um nur die Seiten zu verarbeiten, die Sie benötigen. Kleinere Seitenbereiche senken sowohl die Serverzeit als auch die Antwortgröße; --token-budget begrenzt den AST, den Ihr Agent lesen muss.
  • Große Jobs in einem Prozess bündeln. Bevorzugen Sie für umfangreiche Batches das Python-SDK gegenüber wiederholten CLI-Aufrufen. Ein einzelner langlebiger NextPDF- (oder AsyncNextPDF-)Client verwendet für mehrere Dokumente eine gepoolte HTTP-Verbindung wieder. Dadurch entfallen Prozessstart und Verbindungsaufbau, die eine CLI-Schleife jedes Mal tragen muss. Die Python-Übersicht zeigt den Lebenszyklus des Clients, und AsyncNextPDF unterstützt nebenläufige Extraktion über viele PDFs hinweg.
  • Halten Sie Protokolle aus dem Datenpfad heraus. Belassen Sie --log-level für Batch-Läufe auf seinem Standardwert. Diagnoseprotokolle gehen an stderr und beschädigen die stdout-Daten nicht, doch das Anheben des Levels auf debug erzeugt Rauschen und einen geringen Overhead.