콘텐츠로 이동

Python CLI 도구

nextpdf 명령은 터미널에서 PDF 추출을 실행합니다. NextPDF Connect 엔드포인트를 지정하고 PDF를 전달하면, 인용된 텍스트, 표, 전체 의미 추상 구문 트리(AST) 또는 메타데이터 요약 같은 구조화된 출력을 표준 출력(stdout)이나 파일로 받을 수 있습니다.

nextpdf 명령은 Click 명령 그룹입니다. 연결 및 세션 옵션 — --base-url, --api-key, --log-level, --output/-o, --strict — 은 그룹에 정의되어 있으므로 하위 명령 에 배치합니다. 하위 명령과 자체 옵션(예: --format 또는 --page)은 에 둡니다.

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

그룹 옵션을 하위 명령 뒤에 두면 실패합니다. 예를 들어 nextpdf info document.pdf --base-url ...Error: No such option: --base-url를 보고하고 상태 2로 종료합니다. Click이 --base-url를 구문 분석할 시점에는 이미 해당 옵션을 정의하지 않는 info 하위 명령 안에 있기 때문입니다.

옵션 순서 문제를 피하는 가장 확실한 방법은 환경 변수를 통해 자격 증명을 제공하는 것입니다(셸마다 한 번 구성 참조). 아래 예제는 올바른 순서가 분명히 드러나도록 명시적 플래그 형식을 먼저 보여 줍니다.

텍스트를 JSON으로 추출:

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

표를 쉼표로 구분된 값(CSV) 형식으로 추출:

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

문서 메타데이터 및 구조 검사:

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

전체 의미 AST 가져오기:

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

서버에 연결하지 않고 설치된 SDK 버전 출력:

Terminal window
nextpdf version

version 명령은 --base-url--api-key도 필요하지 않은 유일한 명령입니다. 그 외 모든 명령은 서버에 연결하며 두 가지가 모두 필요합니다.

각 예제는 API 키를 명령줄에 포함하는 대신 NEXTPDF_API_KEY 환경 변수에서 읽어옵니다. 키는 비밀로 취급하십시오. 명령줄에 직접 입력한 리터럴 키는 셸 기록과 프로세스 목록(ps)에서 같은 호스트의 다른 사용자에게 노출됩니다.

다음 옵션은 하위 명령 앞에 배치합니다. 각 연결 옵션은 환경 변수에서도 읽으므로, 변수가 설정되어 있으면 플래그를 생략할 수 있습니다.

옵션환경 변수기본값용도
--base-urlNEXTPDF_BASE_URL(필수)NextPDF Connect 서버 URL.
--api-keyNEXTPDF_API_KEY(필수)베어러 인증용 API 키.
--log-levelwarning로깅 상세도: debug, info, warning, 또는 error. 로그는 표준 오류(stderr)로 전달됩니다.
--output, -ostdout명령 출력을 stdout이 아닌 파일에 씁니다.
--strictoff향후 사용을 위해 예약되었습니다. 현재 이 플래그는 구문 분석되지만 동작을 변경하지 않습니다.
--help, -h도움말을 표시하고 종료합니다.

--base-url--api-key 값은 version을 제외한 모든 명령에 필요합니다. 둘 중 하나라도 누락되면 — 플래그도 없고 환경 변수도 없으면 — 명령은 오류를 출력하고 상태 1로 종료합니다.

인용된 텍스트 블록을 추출합니다. 각 블록에는 인용 앵커(노드 식별자, 페이지 인덱스, 경계 상자, 신뢰도 점수)가 포함됩니다.

nextpdf [GROUP OPTIONS] extract text PDF_PATH [--format FORMAT] [--page N] [--headings-only]
옵션기본값용도
--formatjson, markdown, plainjson출력 형식.
--page정수모든 페이지이 0 기반 페이지 인덱스의 페이지만 추출합니다.
--headings-only플래그off제목 노드만 추출합니다.

PDF_PATH는 파일 경로입니다. stdin에서 PDF 바이트를 읽으려면 -를 사용합니다.

모든 표를 인용 앵커 및 셀 수준 구조와 함께 추출합니다.

nextpdf [GROUP OPTIONS] extract tables PDF_PATH [--format FORMAT] [--page-start N] [--page-end N]
옵션기본값용도
--formatjson, csvjson출력 형식.
--page-start정수첫 페이지시작 페이지 인덱스(0 기반).
--page-end정수마지막 페이지끝 페이지 인덱스(0 기반).

PDF_PATH는 파일 경로입니다. stdin에서 읽으려면 -를 사용합니다.

전체 의미 AST를 JSON으로 반환합니다. 경계 상자와 텍스트 내용을 포함하는 노드(제목, 단락, 표, 목록, 그림)로 이루어진 계층 트리입니다.

nextpdf [GROUP OPTIONS] ast PDF_PATH [--page-start N] [--page-end N] [--token-budget N]
옵션기본값용도
--page-start정수첫 페이지시작 페이지 인덱스(0 기반).
--page-end정수마지막 페이지끝 페이지 인덱스(0 기반).
--token-budget정수무제한반환되는 AST의 대략적인 토큰 한도.

PDF_PATH는 파일 경로입니다. stdin에서 읽으려면 -를 사용합니다. ast 명령은 단일 문서 트리를 생성하며, 두 PDF를 비교하지 않습니다. 구조적 비교는 레시피: 두 PDF 개정판 비교를 참조하십시오.

단일 문서의 간결한 JSON 요약을 출력합니다. 스키마 버전, 소스 해시, 페이지 수, 추정 토큰 수, 루트 노드 유형, 루트 자식 수를 포함합니다.

nextpdf [GROUP OPTIONS] info PDF_PATH

PDF_PATH는 파일 경로입니다. stdin에서 읽으려면 -를 사용합니다.

설치된 SDK 버전(예: nextpdf 1.1.0)을 출력하고 종료합니다. 이 명령은 서버에 연결하지 않으며 자격 증명이 필요하지 않습니다.

nextpdf version

연결 옵션을 환경 변수로 한 번 설정하고 반복되는 플래그를 생략하십시오. 이 형식은 자격 증명이 명령줄에 전혀 나타나지 않으므로 옵션 순서 문제도 완전히 피합니다.

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

Windows PowerShell에서:

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

비밀 저장소나 버전 관리에서 제외된 .env 파일에서 키를 불러오는 것이 좋습니다. 프로덕션 키를 공유된 터미널 세션이나 커밋될 스크립트에 붙여넣지 마십시오.

명령마다 --format으로 출력 형식을 선택합니다. 텍스트 및 표 명령은 둘 이상의 형식을 지원하며, astinfo는 항상 JSON을 내보냅니다.

명령형식기본값
extract textjson, markdown, plainjson
extract tablesjson, csvjson
astjsonjson
infojsonjson

다운스트림 프로그램에 페이지 인덱스, 신뢰도 점수 또는 노드 식별자가 필요할 때는 JSON을 선택하십시오. 스프레드시트나 표 형식 파이프라인에서 표를 사용할 때는 CSV를 선택하십시오. 사람이 읽거나 텍스트 전용 도구가 처리할 결과라면 plain 또는 markdown 텍스트를 선택하십시오.

텍스트 명령은 인용된 블록의 JSON 배열을 내보냅니다. 각 블록에는 text, citation 객체(node_id, page_index, bbox, confidence), 그리고 선택적 node_type이 있습니다. --output으로 출력을 파일에 보낸 다음(또는 stdout을 리디렉션한 다음) 구문 분석하십시오.

이 셸 예제는 jq를 사용하여 0 페이지의 제목만 남깁니다:

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

동일한 데이터는 Python에서도 깔끔하게 구문 분석됩니다. CLI는 JSON 배열을 쓰므로, 표준 라이브러리로 로드하여 타입이 지정된 필드를 읽습니다:

"""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)

원시 딕셔너리 대신 검증된 타입 모델이 필요할 때는 CLI 출력을 구문 분석하는 대신 SDK를 직접 호출하십시오. Python 개요에서 NextPDF 클라이언트와 해당 CitedTextBlock 반환 형식을 참조하십시오.

--format csv 옵션을 사용하면 표 명령은 표마다 하나의 CSV 블록을 씁니다. 주석 행 # Table N (pM)이 각 표 앞에 오며 1 기반 표 번호와 0 기반 페이지 인덱스를 나타냅니다. 연속된 표는 빈 줄로 구분됩니다. CLI는 Python의 csv 모듈로 셀 값을 따옴표로 묶고 이스케이프하므로, 쉼표, 따옴표, 줄바꿈을 포함하는 값도 안전하게 왕복됩니다.

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

파일에는 여러 CSV 블록이 들어 있으므로, 각 블록을 독립된 표로 구문 분석하기 전에 주석 행에서 분할하십시오:

"""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")

CLI는 세 가지 종료 코드를 사용합니다. 셸 스크립트에서 $?(또는 PowerShell에서 $LASTEXITCODE)를 확인하여 성공 또는 실패에 따라 분기하고, stdout의 데이터와 분리되어 유지되는 stderr에서 진단 메시지를 읽으십시오.

종료 코드의미예시
0성공.명령 완료. version 출력.
1런타임 오류. CLI가 Error: <message>를 stderr에 출력함.입력 파일을 찾을 수 없거나 일반 파일이 아님, 빈 stdin, 누락되었거나 유효하지 않은 --base-url/--api-key, 모든 서버 측 오류(라이선스 필요, 할당량 초과, 태그 없는 PDF, 빌드 시간 초과, 또는 기타 API 실패).
2Click 이 보고하는 사용법 오류.알 수 없는 명령 또는 옵션(하위 명령 뒤에 배치된 그룹 옵션 포함), PDF_PATH와 같은 필수 인수 누락.

모든 서버 측 실패는 사람이 읽을 수 있는 메시지를 stderr에 출력하고 종료 코드 1로 나타납니다. SDK는 타입이 지정된 예외를 발생시킵니다 — NextPDFLicenseError(HTTP 402), QuotaExceededError(HTTP 429), AstNoStructTreeError(HTTP 422, 태그 없는 PDF), AstBuildTimeoutError(HTTP 504), 또는 기본 NextPDFAPIError. CLI는 공통 기본 클래스 NextPDFError 아래에서 이들을 모두 포착하고, 메시지를 출력하며, 1로 종료합니다. CLI는 실패 유형별로 별도의 종료 코드를 노출하지 않습니다. 예를 들어 스크립트에서 할당량 오류와 라이선스 오류를 구분하려면 stderr의 메시지 텍스트를 검사하거나 SDK를 직접 호출하십시오(예외 클래스는 Python 개요 참조).

데이터와 진단을 분리하는 스크립팅 패턴:

#!/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

참고로 --output은 데이터를 지정된 파일에 쓰고 확인 줄 Written to <path>만 stderr에 출력하므로 stdout은 비어 있게 됩니다. --output이 없으면 데이터는 stdout으로 전달되며 리디렉션할 수 있습니다.

아래 모든 레시피는 검증된 명령과 플래그만 사용합니다. 각 경우에 자격 증명은 환경에서 가져옵니다.

송장 폴더를 스프레드시트나 회계 파이프라인에서 사용할 수 있도록 문서당 하나의 CSV 파일로 변환합니다:

#!/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

out/<name>.csv는 감지된 표마다 하나의 CSV 블록을 담으며, 각 블록 앞에는 # Table N (pM) 헤더가 옵니다. 위에 표시된 CSV 리더로 블록을 구문 분석하십시오.

--headings-only 옵션을 markdown 형식과 함께 사용하여 읽거나 노트에 붙여넣기 쉬운 빠른 개요를 생성하십시오:

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

CLI의 ast 명령은 단일 문서의 트리를 반환하며, diff 하위 명령이 없습니다. 구조적 비교는 SDK에서 client.ast.get_ast_diff(...)로, 그리고 Model Context Protocol(MCP) 서버에서 nextpdf_diff 도구로 제공됩니다. diff는 SDK를 통해 실행하십시오:

"""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"))

동일한 diff를 스크립트가 아니라 AI 에이전트에서 실행하려면, MCP 서버를 등록하고 nextpdf_diff 도구를 호출하십시오. Python MCP 서버 페이지를 참조하십시오.

레시피: 다른 도구에서 PDF 스트리밍 입력

섹션 제목: “레시피: 다른 도구에서 PDF 스트리밍 입력”

자체 stdout으로 PDF를 내보내는 도구 뒤에 nextpdf를 연결하고, -로 stdin에서 PDF 바이트를 읽게 하십시오:

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

- 인수는 명령에 stdin에서 문서를 읽도록 지시합니다. 바이트가 도착하지 않으면 명령은 오류를 보고하고 1로 종료합니다.

CLI는 각 응답을 메모리에 구성한 뒤 한 번에 쓰므로 출력을 리디렉션하거나 파이프하는 것은 간단하지만, 출력이 점진적으로 생성되지는 않습니다. 큰 AST나 표 집합은 첫 바이트가 stdout이나 --output 파일에 도달하기 전에 완전히 버퍼링됩니다. 스트림이 아니라 전체 문서 응답을 기준으로 메모리와 지연 시간을 계획하십시오.

nextpdf 호출은 새 클라이언트와 HTTP 연결을 생성하므로, 여러 파일을 반복하면 파일마다 연결을 열고 닫습니다. 연결 비용은 일반적으로 서버 측 추출 시간에 비해 작지만, 대규모에서는 실제 오버헤드가 됩니다.

  • 엔드포인트 하나를 재사용하십시오. 서버가 워밍업된 캐시와 연결 풀을 재사용할 수 있도록 모든 호출을 동일한 NextPDF Connect 배포로 보내십시오. 의도적으로 부하를 분산하는 경우가 아니라면 배치를 여러 엔드포인트에 분산하지 마십시오.
  • 호출당 작업을 제한하십시오. --page, --page-start/--page-end, 또는 --token-budget를 사용하여 필요한 페이지만 처리하십시오. 작은 페이지 범위는 서버 시간과 응답 크기를 모두 줄이며, --token-budget는 에이전트가 읽어야 하는 AST를 제한합니다.
  • 대규모 작업은 한 프로세스에서 일괄 처리하십시오. 대용량 배치에서는 반복되는 CLI 호출보다 Python SDK를 선호하십시오. 단일 장기 실행 NextPDF(또는 AsyncNextPDF) 클라이언트는 모든 문서에 걸쳐 풀링된 HTTP 연결 하나를 재사용하므로, CLI 루프가 매번 부담하는 프로세스별 시작 및 연결 설정 비용을 제거합니다. Python 개요는 클라이언트 수명 주기를 보여 주며, AsyncNextPDF는 여러 PDF에 걸친 동시 추출을 지원합니다.
  • 로그를 데이터 경로에서 분리하십시오. 배치 실행에서는 --log-level을 기본값으로 두십시오. 진단 로그는 stderr로 전달되어 stdout 데이터를 손상시키지 않지만, 레벨을 debug로 올리면 노이즈와 약간의 오버헤드가 추가됩니다.