CLI de Python
CLI de Python
Sección titulada «CLI de Python»El comando nextpdf ejecuta la extracción de PDF desde la terminal. Se le indica un endpoint de NextPDF Connect, se le pasa un PDF y se obtiene una salida estructurada (texto con citas, tablas, el árbol de sintaxis abstracta (AST) semántico completo o un resumen de metadatos) en la salida estándar (stdout) o en un archivo.
Estructura del comando
Sección titulada «Estructura del comando»El comando nextpdf es un grupo de comandos de Click. Las opciones de conexión y de sesión (--base-url, --api-key, --log-level, --output/-o y --strict) se definen en el grupo, por lo que deben colocarse antes del subcomando. El subcomando y sus propias opciones (como --format o --page) van después:
nextpdf [GROUP OPTIONS] COMMAND [SUBCOMMAND] PDF_PATH [COMMAND OPTIONS]Colocar una opción del grupo después del subcomando falla. Por ejemplo, nextpdf info document.pdf --base-url ... informa Error: No such option: --base-url y termina con el estado 2, porque cuando Click analiza --base-url ya está dentro del subcomando info, que no define esa opción.
La forma más clara de evitar el problema del orden es proporcionar las credenciales mediante variables de entorno (consulta Configurar una vez por shell). Los ejemplos siguientes muestran primero el uso explícito de opciones para que el orden correcto quede claro.
Referencia rápida
Sección titulada «Referencia rápida»Extraer texto como JSON:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract text document.pdfExtraer tablas como valores separados por comas (CSV):
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract tables invoice.pdf --format csvInspeccionar los metadatos y la estructura del documento:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" info document.pdfObtener el AST semántico completo:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" ast document.pdfImprimir la versión del SDK instalada sin contactar con un servidor:
nextpdf versionEl comando version es el único comando que no necesita ni --base-url ni --api-key. Cualquier otro comando se comunica con el servidor y requiere ambos.
En cada ejemplo, la clave de API se lee desde la variable de entorno NEXTPDF_API_KEY en lugar de incrustarse en la línea de comandos. La clave debe tratarse como un secreto. Una clave literal en la línea de comandos queda visible en el historial del shell y en la lista de procesos (ps) para otros usuarios del host.
Comandos y opciones
Sección titulada «Comandos y opciones»Opciones del grupo
Sección titulada «Opciones del grupo»Deben colocarse antes del subcomando. Cada opción de conexión también lee de una variable de entorno, por lo que el indicador puede omitirse cuando la variable está definida.
| Opción | Variable de entorno | Predeterminado | Propósito |
|---|---|---|---|
--base-url | NEXTPDF_BASE_URL | (obligatorio) | URL del servidor NextPDF Connect. |
--api-key | NEXTPDF_API_KEY | (obligatorio) | Clave de API para la autenticación bearer. |
--log-level | — | warning | Verbosidad del registro: debug, info, warning o error. Los registros van a la salida de error estándar (stderr). |
--output, -o | — | stdout | Escribe la salida del comando en un archivo en lugar de en stdout. |
--strict | — | desactivado | Reservado para uso futuro. Actualmente el indicador se analiza, pero no cambia el comportamiento. |
--help, -h | — | — | Muestra la ayuda y termina. |
Los valores de --base-url y --api-key son obligatorios para todos los comandos excepto version. Si falta alguno de los dos (sin indicador y sin variable de entorno), el comando imprime un error y termina con estado 1.
nextpdf extract text
Sección titulada «nextpdf extract text»Extrae bloques de texto con citas. Cada bloque incluye un ancla de cita (identificador de nodo, índice de página, cuadro delimitador y puntuación de confianza).
nextpdf [GROUP OPTIONS] extract text PDF_PATH [--format FORMAT] [--page N] [--headings-only]| Opción | Valores | Predeterminado | Propósito |
|---|---|---|---|
--format | json, markdown, plain | json | Formato de salida. |
--page | entero | todas las páginas | Extrae solo este índice de página con base 0. |
--headings-only | indicador | desactivado | Extrae solo los nodos de encabezado. |
PDF_PATH es una ruta de archivo o - para leer los bytes del PDF desde stdin.
nextpdf extract tables
Sección titulada «nextpdf extract tables»Extrae todas las tablas con anclas de cita y estructura a nivel de celdas.
nextpdf [GROUP OPTIONS] extract tables PDF_PATH [--format FORMAT] [--page-start N] [--page-end N]| Opción | Valores | Predeterminado | Propósito |
|---|---|---|---|
--format | json, csv | json | Formato de salida. |
--page-start | entero | primera página | Índice de la página inicial (con base 0). |
--page-end | entero | última página | Índice de la página final (con base 0). |
PDF_PATH es una ruta de archivo o - para leer desde stdin.
nextpdf ast
Sección titulada «nextpdf ast»Devuelve el AST semántico completo como JSON: un árbol jerárquico de nodos (encabezados, párrafos, tablas, listas, figuras) con cuadros delimitadores y contenido de texto.
nextpdf [GROUP OPTIONS] ast PDF_PATH [--page-start N] [--page-end N] [--token-budget N]| Opción | Valores | Predeterminado | Propósito |
|---|---|---|---|
--page-start | entero | primera página | Índice de la página inicial (con base 0). |
--page-end | entero | última página | Índice de la página final (con base 0). |
--token-budget | entero | sin límite | Límite aproximado de tokens para el AST devuelto. |
PDF_PATH es una ruta de archivo o - para leer desde stdin. El comando ast produce un único árbol del documento; no compara dos PDF. Para la comparación estructural, consulta Recipe: comparar dos revisiones de PDF.
nextpdf info
Sección titulada «nextpdf info»Imprime un resumen JSON compacto de un documento: la versión del esquema, el hash de origen, el número de páginas, el número estimado de tokens, el tipo del nodo raíz y el número de hijos de la raíz.
nextpdf [GROUP OPTIONS] info PDF_PATHPDF_PATH es una ruta de archivo o - para leer desde stdin.
nextpdf version
Sección titulada «nextpdf version»Imprime la versión del SDK instalada (por ejemplo, nextpdf 1.1.0) y termina. Este comando no se comunica con ningún servidor y no necesita credenciales.
nextpdf versionConfigurar una vez por shell
Sección titulada «Configurar una vez por shell»Definir las opciones de conexión una sola vez como variables de entorno permite omitir los indicadores repetidos. Esta forma también evita por completo el problema del orden de las opciones, porque las credenciales nunca aparecen en la línea de comandos.
export NEXTPDF_BASE_URL=http://localhost:8080export NEXTPDF_API_KEY=your-keynextpdf extract text document.pdfEn Windows PowerShell:
$env:NEXTPDF_BASE_URL = "http://localhost:8080"$env:NEXTPDF_API_KEY = "your-key"nextpdf extract text document.pdfEs preferible cargar la clave desde un almacén de secretos o desde un archivo .env que se mantenga fuera del control de versiones. No debe pegarse una clave de producción en una sesión de terminal compartida ni en un script que se confirme en el repositorio.
Formatos de salida
Sección titulada «Formatos de salida»El formato de salida se selecciona por comando con --format. Los comandos de texto y de tablas admiten más de un formato; ast e info siempre emiten JSON.
| Comando | Formatos | Predeterminado |
|---|---|---|
extract text | json, markdown, plain | json |
extract tables | json, csv | json |
ast | json | json |
info | json | json |
Conviene elegir JSON cuando un programa posterior necesite índices de página, puntuaciones de confianza o identificadores de nodo. Conviene elegir CSV cuando una hoja de cálculo o una canalización tabular consuma las tablas. Conviene elegir texto plain o markdown cuando vaya a leerlo una persona o una herramienta de solo texto.
Análisis de la salida JSON
Sección titulada «Análisis de la salida JSON»El comando de texto emite un arreglo JSON de bloques con citas. Cada bloque tiene text, un objeto citation (node_id, page_index, bbox, confidence) y un node_type opcional. Enviar la salida a un archivo con --output (o redirigir stdout) permite analizarla después.
Este ejemplo de shell usa jq para conservar solo los encabezados de la página 0:
nextpdf --output blocks.json extract text report.pdf --format jsonjq '[.[] | select(.citation.page_index == 0 and .node_type == "heading") | .text]' blocks.jsonLos mismos datos pueden analizarse sin problemas en Python. La CLI escribe un arreglo JSON, por lo que se carga con la biblioteca estándar y se leen los campos tipados:
"""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)Cuando se necesitan modelos validados y tipados en lugar de diccionarios sin procesar, conviene llamar al SDK directamente en vez de analizar la salida de la CLI. Consulta la introducción a Python para conocer el cliente NextPDF y su tipo de retorno CitedTextBlock.
Análisis de la salida CSV
Sección titulada «Análisis de la salida CSV»Con --format csv, el comando de tablas escribe un bloque CSV por tabla. Una fila de comentario, # Table N (pM), precede a cada tabla e indica su número de tabla con base 1 y su índice de página con base 0. Una línea en blanco separa las tablas consecutivas. La CLI entrecomilla y escapa los valores de las celdas con el módulo csv de Python, por lo que los valores que contienen comas, comillas o saltos de línea se conservan de forma segura al leerlos y escribirlos.
nextpdf --output tables.csv extract tables statement.pdf --format csvComo el archivo contiene varios bloques CSV, debe dividirse por las filas de comentario antes de analizar cada bloque como una tabla independiente:
"""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")Códigos de salida y detección de errores
Sección titulada «Códigos de salida y detección de errores»La CLI usa tres códigos de salida. En scripts de shell, comprobar $? (o $LASTEXITCODE en PowerShell) permite ramificar según el éxito o el fallo, y leer los mensajes de diagnóstico de stderr, que se mantiene separado de los datos de stdout.
| Código de salida | Significado | Ejemplos |
|---|---|---|
0 | Éxito. | Un comando se completó; se imprimió version. |
1 | Error en tiempo de ejecución. La CLI imprime Error: <message> en stderr. | Archivo de entrada no encontrado o no es un archivo normal, stdin vacío, --base-url/--api-key ausente o no válido, cualquier error del lado del servidor (licencia requerida, cuota superada, PDF sin etiquetar, tiempo de espera de la compilación agotado u otro fallo de la API). |
2 | Error de uso, informado por Click. | Comando u opción desconocidos (incluida una opción del grupo colocada después del subcomando), falta un argumento obligatorio como PDF_PATH. |
Cada fallo del lado del servidor se manifiesta como el código de salida 1 con un mensaje legible para personas en stderr. El SDK lanza una excepción tipada: NextPDFLicenseError (HTTP 402), QuotaExceededError (HTTP 429), AstNoStructTreeError (HTTP 422, PDF sin etiquetar), AstBuildTimeoutError (HTTP 504) o la base NextPDFAPIError. La CLI las captura todas a través de su base compartida NextPDFError, imprime el mensaje y termina con 1. La CLI no expone códigos de salida distintos por tipo de fallo. Para distinguir, por ejemplo, un error de cuota de un error de licencia en un script, se puede inspeccionar el texto del mensaje en stderr o llamar al SDK directamente (consulta la introducción a Python para conocer las clases de excepción).
Patrón de scripting para separar los datos de los diagnósticos:
#!/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}"fiDebe tenerse en cuenta que --output escribe los datos en el archivo indicado e imprime solo la línea de confirmación Written to <path> en stderr, por lo que stdout queda vacío. Sin --output, los datos van a stdout y es posible redirigirlos.
Recipes
Sección titulada «Recipes»Las siguientes recetas usan solo comandos e indicadores verificados. Las credenciales provienen del entorno en cada caso.
Recipe: extraer tablas de facturas a CSV
Sección titulada «Recipe: extraer tablas de facturas a CSV»Convertir una carpeta de facturas en un archivo CSV por documento para una hoja de cálculo o una canalización de contabilidad:
#!/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 csvdoneCada out/<name>.csv contiene un bloque CSV por cada tabla detectada, con un encabezado # Table N (pM) que precede a cada bloque. Analizar los bloques con el lector de CSV mostrado arriba.
Recipe: crear un esquema del documento
Sección titulada «Recipe: crear un esquema del documento»Combinar --headings-only con el formato markdown permite producir un esquema rápido que se pueda leer o pegar en notas:
nextpdf --output outline.md extract text whitepaper.pdf --headings-only --format markdownRecipe: comparar dos revisiones de PDF
Sección titulada «Recipe: comparar dos revisiones de PDF»El comando ast de la CLI devuelve el árbol de un único documento; no tiene un subcomando de comparación. La comparación estructural está disponible en el SDK como client.ast.get_ast_diff(...) y en el servidor Model Context Protocol (MCP) como la herramienta nextpdf_diff. Ejecutar la comparación a través del 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"))Para ejecutar la misma comparación desde un agente de IA en lugar de un script, registrar el servidor MCP y llamar a la herramienta nextpdf_diff. Consulta la página servidor MCP de Python.
Recipe: transmitir un PDF desde otra herramienta
Sección titulada «Recipe: transmitir un PDF desde otra herramienta»Leer los bytes del PDF desde stdin con - permite encadenar nextpdf después de una herramienta que emite un PDF en su propio stdout:
curl --silent https://example.com/report.pdf | nextpdf info -El argumento - indica al comando que lea el documento desde stdin. Si no llega ningún byte, el comando informa un error y termina con 1.
Notas de rendimiento
Sección titulada «Notas de rendimiento»La CLI construye cada respuesta en memoria y la escribe de una sola vez, por lo que redirigir o canalizar la salida es sencillo, pero la salida no se produce de forma incremental. Un AST o un conjunto de tablas grande se almacena por completo en búfer antes de que el primer byte llegue a stdout o al archivo de --output. Planificar la memoria y la latencia para respuestas de documento completo, no para una transmisión.
Cada invocación de nextpdf crea un cliente y una conexión HTTP nuevos, por lo que un bucle sobre muchos archivos abre y cierra una conexión por archivo. El costo de la conexión suele ser pequeño frente al tiempo de extracción del lado del servidor, pero es una sobrecarga real a gran escala.
- Reutilizar un solo endpoint. Dirigir cada invocación al mismo despliegue de NextPDF Connect permite que el servidor reutilice las cachés precalentadas y los pools de conexiones. Evitar repartir un lote entre varios endpoints a menos que se esté balanceando la carga a propósito.
- Acotar el trabajo por llamada. Usar
--page,--page-start/--page-endo--token-budgetpara procesar solo las páginas que se necesitan. Los rangos de páginas más pequeños reducen tanto el tiempo del servidor como el tamaño de la respuesta;--token-budgetlimita el AST que el agente debe leer. - Agrupar en un solo proceso los trabajos grandes. Para lotes de gran volumen, es preferible el SDK de Python frente a llamadas repetidas a la CLI. Un único cliente
NextPDF(oAsyncNextPDF) persistente reutiliza una conexión HTTP mantenida en un pool para cada documento, lo que elimina el arranque por proceso y la configuración de la conexión que un bucle de la CLI paga cada vez. La introducción a Python muestra el ciclo de vida del cliente, yAsyncNextPDFadmite la extracción concurrente en muchos PDF. - Mantener los registros fuera de la ruta de datos. Dejar
--log-levelen su valor predeterminado para las ejecuciones por lotes. Los registros de diagnóstico van a stderr y no corrompen los datos de stdout, pero subir el nivel adebugañade ruido y una sobrecarga menor.