CLI Python
CLI Python
Section intitulée « CLI Python »La commande nextpdf lance l’extraction de PDF depuis le terminal. Tu la fais pointer vers un endpoint NextPDF Connect, tu lui passes un PDF, puis tu reçois une sortie structurée — texte cité, tableaux, arbre syntaxique abstrait (AST) sémantique complet ou résumé de métadonnées — sur la sortie standard (stdout) ou dans un fichier.
Structure de la commande
Section intitulée « Structure de la commande »La commande nextpdf est un groupe de commandes Click. Les options de connexion et de session — --base-url, --api-key, --log-level, --output/-o et --strict — sont définies au niveau du groupe : tu les places donc avant la sous-commande. La sous-commande et ses propres options (comme --format ou --page) viennent après :
nextpdf [GROUP OPTIONS] COMMAND [SUBCOMMAND] PDF_PATH [COMMAND OPTIONS]Placer une option de groupe après la sous-commande échoue. Par exemple, nextpdf info document.pdf --base-url ... renvoie Error: No such option: --base-url et se termine avec le statut 2, car au moment où Click analyse --base-url, il se trouve déjà dans la sous-commande info, qui ne définit pas cette option.
Le moyen le plus clair d’éviter le piège de l’ordre consiste à fournir les identifiants via des variables d’environnement (voir Configurer une fois par shell). Les exemples ci-dessous montrent d’abord la forme avec les options explicites, afin que le bon ordre soit clair.
Référence rapide
Section intitulée « Référence rapide »Extraire le texte en JSON :
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract text document.pdfExtraire les tableaux en valeurs séparées par des virgules (CSV) :
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract tables invoice.pdf --format csvInspecter les métadonnées et la structure du document :
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" info document.pdfObtenir l’AST sémantique complet :
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" ast document.pdfAfficher la version du SDK installé sans contacter de serveur :
nextpdf versionLa commande version est la seule commande qui n’a besoin ni de --base-url ni de --api-key. Toutes les autres commandes contactent le serveur et exigent les deux.
Chaque exemple lit la clé d’API depuis la variable d’environnement NEXTPDF_API_KEY au lieu de l’inscrire sur la ligne de commande. Traite cette clé comme un secret. Une clé en clair sur la ligne de commande est visible dans l’historique de ton shell et dans la liste des processus (ps) pour les autres utilisateurs de la machine.
Commandes et options
Section intitulée « Commandes et options »Options de groupe
Section intitulée « Options de groupe »Place-les avant la sous-commande. Chaque option de connexion peut aussi être lue depuis une variable d’environnement ; tu peux donc omettre le flag quand la variable est définie.
| Option | Variable d’environnement | Valeur par défaut | Rôle |
|---|---|---|---|
--base-url | NEXTPDF_BASE_URL | (obligatoire) | URL du serveur NextPDF Connect. |
--api-key | NEXTPDF_API_KEY | (obligatoire) | Clé d’API pour l’authentification Bearer. |
--log-level | — | warning | Niveau de verbosité des logs : debug, info, warning ou error. Les logs vont vers la sortie d’erreur standard (stderr). |
--output, -o | — | stdout | Écrit la sortie de la commande dans un fichier au lieu de stdout. |
--strict | — | off | Réservé à un usage futur. Le flag est analysé aujourd’hui mais ne change pas le comportement. |
--help, -h | — | — | Affiche l’aide et quitte. |
Les valeurs --base-url et --api-key sont obligatoires pour chaque commande sauf version. Si l’une des deux manque — ni flag ni variable d’environnement — la commande affiche une erreur et se termine avec le statut 1.
nextpdf extract text
Section intitulée « nextpdf extract text »Extrait les blocs de texte cités. Chaque bloc porte une ancre de citation (identifiant de nœud, index de page, boîte englobante et score de confiance).
nextpdf [GROUP OPTIONS] extract text PDF_PATH [--format FORMAT] [--page N] [--headings-only]| Option | Valeurs | Valeur par défaut | Rôle |
|---|---|---|---|
--format | json, markdown, plain | json | Format de sortie. |
--page | entier | toutes les pages | Extrait uniquement cet index de page à base 0. |
--headings-only | flag | off | Extrait uniquement les nœuds de titre. |
PDF_PATH est un chemin de fichier, ou - pour lire les octets du PDF depuis stdin.
nextpdf extract tables
Section intitulée « nextpdf extract tables »Extrait chaque tableau avec ses ancres de citation et sa structure au niveau des cellules.
nextpdf [GROUP OPTIONS] extract tables PDF_PATH [--format FORMAT] [--page-start N] [--page-end N]| Option | Valeurs | Valeur par défaut | Rôle |
|---|---|---|---|
--format | json, csv | json | Format de sortie. |
--page-start | entier | première page | Index de la page de début (à base 0). |
--page-end | entier | dernière page | Index de la page de fin (à base 0). |
PDF_PATH est un chemin de fichier, ou - pour lire depuis stdin.
nextpdf ast
Section intitulée « nextpdf ast »Renvoie l’AST sémantique complet en JSON : un arbre hiérarchique de nœuds (titres, paragraphes, tableaux, listes, figures) avec leurs boîtes englobantes et leur contenu textuel.
nextpdf [GROUP OPTIONS] ast PDF_PATH [--page-start N] [--page-end N] [--token-budget N]| Option | Valeurs | Valeur par défaut | Rôle |
|---|---|---|---|
--page-start | entier | première page | Index de la page de début (à base 0). |
--page-end | entier | dernière page | Index de la page de fin (à base 0). |
--token-budget | entier | sans limite | Limite approximative de tokens pour l’AST renvoyé. |
PDF_PATH est un chemin de fichier, ou - pour lire depuis stdin. La commande ast produit un seul arbre de document ; elle ne compare pas deux PDF. Pour comparer des structures, voir Recipe : comparer deux révisions de PDF.
nextpdf info
Section intitulée « nextpdf info »Affiche un résumé JSON compact d’un document : version du schéma, hash de la source, nombre de pages, nombre estimé de tokens, type du nœud racine et nombre d’enfants de la racine.
nextpdf [GROUP OPTIONS] info PDF_PATHPDF_PATH est un chemin de fichier, ou - pour lire depuis stdin.
nextpdf version
Section intitulée « nextpdf version »Affiche la version du SDK installé (par exemple, nextpdf 1.1.0) et quitte. Cette commande ne contacte aucun serveur et n’a besoin d’aucun identifiant.
nextpdf versionConfigurer une fois par shell
Section intitulée « Configurer une fois par shell »Définis les options de connexion une seule fois sous forme de variables d’environnement et omets les flags répétés. Cette forme évite aussi complètement le piège de l’ordre des options, car les identifiants n’apparaissent jamais sur la ligne de commande.
export NEXTPDF_BASE_URL=http://localhost:8080export NEXTPDF_API_KEY=your-keynextpdf extract text document.pdfSous Windows PowerShell :
$env:NEXTPDF_BASE_URL = "http://localhost:8080"$env:NEXTPDF_API_KEY = "your-key"nextpdf extract text document.pdfPréfère charger la clé depuis un coffre à secrets ou un fichier .env que tu gardes hors du système de gestion de versions. Ne colle pas de clé de production dans une session de terminal partagée ni dans un script que tu commites.
Formats de sortie
Section intitulée « Formats de sortie »Tu choisis le format de sortie par commande avec --format. Les commandes de texte et de tableaux prennent en charge plusieurs formats ; ast et info émettent toujours du JSON.
| Commande | Formats | Valeur par défaut |
|---|---|---|
extract text | json, markdown, plain | json |
extract tables | json, csv | json |
ast | json | json |
info | json | json |
Choisis JSON quand un programme en aval a besoin des index de page, des scores de confiance ou des identifiants de nœud. Choisis CSV quand un tableur ou un pipeline tabulaire consomme les tableaux. Choisis le texte plain ou markdown quand une personne, ou un outil en mode texte uniquement, lit le résultat.
Analyser la sortie JSON
Section intitulée « Analyser la sortie JSON »La commande d’extraction de texte émet un tableau JSON de blocs cités. Chaque bloc contient un champ text, un objet citation (node_id, page_index, bbox, confidence) et un champ node_type facultatif. Écris la sortie dans un fichier avec --output (ou redirige stdout), puis analyse-la.
Cet exemple shell utilise jq pour ne garder que les titres de la page 0 :
nextpdf --output blocks.json extract text report.pdf --format jsonjq '[.[] | select(.citation.page_index == 0 and .node_type == "heading") | .text]' blocks.jsonLes mêmes données peuvent s’analyser proprement en Python. La CLI écrit un tableau JSON : tu le charges donc avec la bibliothèque standard et tu lis les champs typés :
"""Parse cited text blocks emitted by `nextpdf extract text --format json`."""
import jsonfrom 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)Quand tu as besoin de modèles validés et typés plutôt que de dictionnaires bruts, appelle directement le SDK au lieu d’analyser la sortie de la CLI. Consulte la vue d’ensemble Python pour le client NextPDF et son type de retour CitedTextBlock.
Analyser la sortie CSV
Section intitulée « Analyser la sortie CSV »Avec --format csv, la commande de tableaux écrit un bloc CSV par tableau. Une ligne de commentaire, # Table N (pM), précède chaque tableau et indique son numéro de tableau à base 1 et son index de page à base 0. Une ligne vide sépare les tableaux consécutifs. La CLI met les valeurs des cellules entre guillemets et les échappe avec le module csv de Python ; les valeurs qui contiennent des virgules, des guillemets ou des sauts de ligne sont donc préservées intactes à l’aller-retour.
nextpdf --output tables.csv extract tables statement.pdf --format csvComme le fichier contient plusieurs blocs CSV, découpe-le sur les lignes de commentaire avant d’analyser chaque bloc comme un tableau autonome :
"""Split multi-table CSV output from `nextpdf extract tables --format csv`."""
import csvimport iofrom 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")Codes de sortie et détection d’erreurs
Section intitulée « Codes de sortie et détection d’erreurs »La CLI utilise trois codes de sortie. Vérifie $? dans les scripts shell (ou $LASTEXITCODE sous PowerShell) pour distinguer succès et échec, et lis les messages de diagnostic depuis stderr, qui reste séparé des données sur stdout.
| Code de sortie | Signification | Exemples |
|---|---|---|
0 | Succès. | Une commande s’est terminée ; version a affiché sa sortie. |
1 | Erreur d’exécution. La CLI affiche Error: <message> sur stderr. | Fichier d’entrée introuvable ou qui n’est pas un fichier régulier, stdin vide, --base-url/--api-key manquant ou invalide, toute erreur côté serveur (licence requise, quota dépassé, PDF non balisé, délai de build dépassé ou autre échec de l’API). |
2 | Erreur d’utilisation, signalée par Click. | Commande ou option inconnue (y compris une option de groupe placée après la sous-commande), un argument obligatoire manquant tel que PDF_PATH. |
Chaque échec côté serveur se manifeste par le code de sortie 1 avec un message lisible par un humain sur stderr. Le SDK lève une exception typée — NextPDFLicenseError (HTTP 402), QuotaExceededError (HTTP 429), AstNoStructTreeError (HTTP 422, PDF non balisé), AstBuildTimeoutError (HTTP 504) ou l’exception de base NextPDFAPIError. La CLI les intercepte toutes via leur base partagée NextPDFError, affiche le message et se termine avec le code 1. La CLI n’expose pas de codes de sortie distincts par type d’échec. Pour distinguer, par exemple, une erreur de quota d’une erreur de licence dans un script, inspecte le texte du message sur stderr ou appelle directement le SDK (voir la vue d’ensemble Python pour les classes d’exception).
Un modèle de script qui sépare les données des diagnostics :
#!/usr/bin/env bashset -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}"fiNote que --output écrit les données dans le fichier nommé et n’affiche que la ligne de confirmation Written to <path> sur stderr ; stdout reste donc vide. Sans --output, les données vont vers stdout et tu peux les rediriger.
Les exemples ci-dessous utilisent uniquement des commandes et des flags vérifiés. Les identifiants viennent de l’environnement dans chaque cas.
Recipe : extraire les tableaux de factures en CSV
Section intitulée « Recipe : extraire les tableaux de factures en CSV »Transforme un dossier de factures en un fichier CSV par document pour un tableur ou un pipeline comptable :
#!/usr/bin/env bashset -euo pipefail
: "${NEXTPDF_BASE_URL:?set NEXTPDF_BASE_URL}": "${NEXTPDF_API_KEY:?set NEXTPDF_API_KEY}"
mkdir -p outfor pdf in invoices/*.pdf; do name="$(basename "${pdf}" .pdf)" nextpdf --output "out/${name}.csv" extract tables "${pdf}" --format csvdoneChaque out/<name>.csv contient un bloc CSV par tableau détecté, avec un en-tête # Table N (pM) avant chacun. Analyse les blocs avec le lecteur CSV présenté ci-dessus.
Recipe : construire un plan de document
Section intitulée « Recipe : construire un plan de document »Combine --headings-only avec le format markdown pour produire rapidement un plan que tu peux lire ou coller dans des notes :
nextpdf --output outline.md extract text whitepaper.pdf --headings-only --format markdownRecipe : comparer deux révisions de PDF
Section intitulée « Recipe : comparer deux révisions de PDF »La commande ast de la CLI renvoie l’arbre d’un seul document ; elle n’a pas de sous-commande de comparaison. La comparaison structurelle est disponible dans le SDK via client.ast.get_ast_diff(...) et dans le serveur Model Context Protocol (MCP) via l’outil nextpdf_diff. Lance la comparaison via le SDK :
"""Compare two PDF revisions structurally with the NextPDF SDK.
The API key is read from the environment, never hard-coded."""
import osfrom 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"))Pour lancer la même comparaison depuis un agent IA plutôt qu’un script, enregistre le serveur MCP et appelle l’outil nextpdf_diff. Consulte la page serveur MCP Python.
Recipe : envoyer un PDF en flux depuis un autre outil
Section intitulée « Recipe : envoyer un PDF en flux depuis un autre outil »Lis les octets du PDF depuis stdin avec - pour chaîner nextpdf après un outil qui émet un PDF sur sa propre sortie stdout :
curl --silent https://example.com/report.pdf | nextpdf info -L’argument - indique à la commande de lire le document depuis stdin. Si aucun octet n’arrive, la commande signale une erreur et se termine avec le code 1.
Notes de performance
Section intitulée « Notes de performance »La CLI construit chaque réponse en mémoire et l’écrit en une seule fois : rediriger ou envoyer la sortie dans un pipe est donc simple, mais la sortie n’est pas produite de façon incrémentale. Un AST volumineux ou un grand ensemble de tableaux est entièrement mis en mémoire tampon avant que le premier octet n’atteigne stdout ou le fichier --output. Prévois la mémoire et la latence pour des réponses portant sur le document entier, pas pour un flux.
Chaque invocation de nextpdf crée un nouveau client et une nouvelle connexion HTTP ; une boucle sur plusieurs fichiers ouvre et ferme donc une connexion par fichier. Le coût de connexion est généralement faible par rapport au temps d’extraction côté serveur, mais il devient réel à grande échelle.
- Réutilise un seul endpoint. Pointe chaque invocation vers le même déploiement NextPDF Connect pour que le serveur réutilise les caches déjà chauds et les pools de connexions. Évite de répartir un lot sur plusieurs endpoints sauf si tu fais volontairement de l’équilibrage de charge.
- Borne le travail par appel. Utilise
--page,--page-start/--page-endou--token-budgetpour ne traiter que les pages dont tu as besoin. Des plages de pages plus petites réduisent à la fois le temps serveur et la taille de la réponse ;--token-budgetplafonne l’AST que ton agent doit lire. - Regroupe les gros travaux dans un seul processus. Pour les lots à fort volume, préfère le SDK Python aux appels CLI répétés. Un seul client
NextPDF(ouAsyncNextPDF) à longue durée de vie réutilise une connexion HTTP du pool d’un document à l’autre, ce qui supprime le coût de démarrage du processus et de mise en place de la connexion qu’une boucle CLI paie à chaque fois. La vue d’ensemble Python montre le cycle de vie du client, etAsyncNextPDFprend en charge l’extraction concurrente sur plusieurs PDF. - Garde les logs hors du chemin des données. Laisse
--log-levelà sa valeur par défaut pour les exécutions par lots. Les logs de diagnostic vont vers stderr et ne corrompent pas les données de stdout, mais passer au niveaudebugajoute du bruit et un léger surcoût.