Python CLI(コマンドラインインターフェイス)
Python CLI(コマンドラインインターフェイス)
「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 として抽出する:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract text document.pdfテーブルをカンマ区切り値(CSV)として抽出する:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" extract tables invoice.pdf --format csvドキュメントのメタデータと構造を確認する:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" info document.pdf完全なセマンティック AST を取得する:
nextpdf --base-url http://localhost:8080 --api-key "$NEXTPDF_API_KEY" ast document.pdfサーバーに接続せずに、インストール済みの SDK バージョンを表示する:
nextpdf versionversion コマンドは、--base-url と --api-key のどちらも必要としない唯一のコマンドです。それ以外のコマンドはすべてサーバーに接続するため、両方が必要です。
各例では、API キーをコマンドラインに埋め込むのではなく、NEXTPDF_API_KEY 環境変数から読み取ります。キーは秘密情報として扱ってください。コマンドラインにキーを直接記述すると、シェルの履歴や、ホスト上の他のユーザーが閲覧できるプロセス一覧(ps)に表示されます。
コマンドとオプション
「コマンドとオプション」という見出しのセクショングループオプション
「グループオプション」という見出しのセクションこれらはサブコマンドの前に置きます。各接続オプションは環境変数からも読み取られるため、変数が設定されている場合はフラグを省略できます。
| オプション | 環境変数 | デフォルト | 目的 |
|---|---|---|---|
--base-url | NEXTPDF_BASE_URL | (必須) | NextPDF Connect サーバーの URL。 |
--api-key | NEXTPDF_API_KEY | (必須) | ベアラー認証用の API キー。 |
--log-level | — | warning | ログの詳細度: debug、info、warning、または error。ログは標準エラー出力(stderr)に出力されます。 |
--output、-o | — | stdout | コマンド出力を stdout ではなくファイルに書き込みます。 |
--strict | — | オフ | 将来の使用に備えて予約されています。このフラグは現在解析されますが、動作は変わりません。 |
--help、-h | — | — | ヘルプを表示して終了します。 |
--base-url と --api-key の値は、version を除くすべてのコマンドで必須です。いずれかが欠落している場合(フラグも環境変数もない場合)、コマンドはエラーを表示し、ステータス 1 で終了します。
nextpdf extract text
「nextpdf extract text」という見出しのセクション引用付きテキストブロックを抽出します。各ブロックには引用アンカー(ノード識別子、ページインデックス、バウンディングボックス、信頼度スコア)が付与されます。
nextpdf [GROUP OPTIONS] extract text PDF_PATH [--format FORMAT] [--page N] [--headings-only]| オプション | 値 | デフォルト | 目的 |
|---|---|---|---|
--format | json、markdown、plain | json | 出力形式。 |
--page | 整数 | 全ページ | この 0 始まりのページインデックスのみを抽出します。 |
--headings-only | フラグ | オフ | 見出しノードのみを抽出します。 |
PDF_PATH はファイルパスです。stdin から PDF バイトを読み取る場合は - を指定します。
nextpdf extract tables
「nextpdf extract tables」という見出しのセクションすべてのテーブルを、引用アンカーとセルレベルの構造とともに抽出します。
nextpdf [GROUP OPTIONS] extract tables PDF_PATH [--format FORMAT] [--page-start N] [--page-end N]| オプション | 値 | デフォルト | 目的 |
|---|---|---|---|
--format | json、csv | json | 出力形式。 |
--page-start | 整数 | 最初のページ | 開始ページインデックス(0 始まり)。 |
--page-end | 整数 | 最後のページ | 終了ページインデックス(0 始まり)。 |
PDF_PATH はファイルパスです。stdin から読み取る場合は - を指定します。
nextpdf ast
「nextpdf ast」という見出しのセクション完全なセマンティック 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 コマンドは単一のドキュメントツリーを生成します。2 つの PDF を比較することはありません。構造的な差分については、レシピ: 2 つの PDF リビジョンを差分するを参照してください。
nextpdf info
「nextpdf info」という見出しのセクション1 つのドキュメントについて、簡潔な JSON 概要を表示します。スキーマバージョン、ソースハッシュ、ページ数、推定トークン数、ルートノードの種類、ルートの子の数を含みます。
nextpdf [GROUP OPTIONS] info PDF_PATHPDF_PATH はファイルパスです。stdin から読み取る場合は - を指定します。
nextpdf version
「nextpdf version」という見出しのセクションインストール済みの SDK バージョン(たとえば nextpdf 1.1.0)を表示して終了します。このコマンドはサーバーに接続せず、資格情報も必要としません。
nextpdf versionシェルごとに一度設定する
「シェルごとに一度設定する」という見出しのセクション接続オプションを環境変数として一度設定しておくと、繰り返し指定するフラグを省略できます。この形式では資格情報がコマンドラインに一切現れないため、オプション順序の問題も完全に回避できます。
export NEXTPDF_BASE_URL=http://localhost:8080export NEXTPDF_API_KEY=your-keynextpdf extract text document.pdfWindows PowerShell の場合:
$env:NEXTPDF_BASE_URL = "http://localhost:8080"$env:NEXTPDF_API_KEY = "your-key"nextpdf extract text document.pdfキーは、シークレットストア、またはバージョン管理対象外にしておく .env ファイルから読み込むことをお勧めします。本番用キーを、共有のターミナルセッションや、コミット対象のスクリプトに貼り付けないでください。
出力形式は、コマンドごとに --format で選択します。テキストコマンドとテーブルコマンドは複数の形式をサポートします。ast と info は常に JSON を出力します。
| コマンド | 形式 | デフォルト |
|---|---|---|
extract text | json、markdown、plain | json |
extract tables | json、csv | json |
ast | json | json |
info | json | json |
ダウンストリームのプログラムがページインデックス、信頼度スコア、ノード識別子を必要とする場合は JSON を選択してください。スプレッドシートや表形式のパイプラインでテーブルを使用する場合は CSV を選択してください。人が読む場合や、テキストのみを扱うツールで結果を処理する場合は、plain または markdown テキストを選択してください。
JSON 出力の解析
「JSON 出力の解析」という見出しのセクションテキストコマンドは、引用付きブロックの JSON 配列を出力します。各ブロックには text、citation オブジェクト(node_id、page_index、bbox、confidence)、およびオプションの node_type があります。出力を --output でファイルに書き出し(または stdout をリダイレクトし)、その後で解析します。
次のシェル例では、jq を使用して、ページ 0 の見出しのみを残します:
nextpdf --output blocks.json extract text report.pdf --format jsonjq '[.[] | 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 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)生のディクショナリではなく、検証済みの型付きモデルが必要な場合は、CLI 出力を解析するのではなく、SDK を直接呼び出してください。Python の概要では、NextPDF クライアントとその CitedTextBlock の戻り値の型を参照できます。
CSV 出力の解析
「CSV 出力の解析」という見出しのセクション--format csv を指定すると、テーブルコマンドはテーブルごとに 1 つの CSV ブロックを書き込みます。コメント行 # Table N (pM) が各テーブルの前に置かれ、その 1 始まりのテーブル番号と 0 始まりのページインデックスを示します。連続するテーブルは空行で区切られます。CLI は Python の csv モジュールでセル値を引用符で囲み、エスケープします。そのため、カンマ、引用符、改行を含む値も安全にラウンドトリップできます。
nextpdf --output tables.csv extract tables statement.pdf --format csvファイルには複数の CSV ブロックが含まれるため、各ブロックを独立したテーブルとして解析する前に、コメント行で分割してください:
"""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")終了コードとエラー検出
「終了コードとエラー検出」という見出しのセクションCLI は 3 つの終了コードを使用します。シェルスクリプトでは $? を(PowerShell では $LASTEXITCODE を)確認して成功または失敗で分岐し、stdout のデータから分離された stderr から診断メッセージを読み取ります。
| 終了コード | 意味 | 例 |
|---|---|---|
0 | 成功。 | コマンドが完了しました。version が表示されました。 |
1 | ランタイムエラー。CLI は Error: <message> を stderr に出力します。 | 入力ファイルが見つからない、または通常のファイルではない、stdin が空、--base-url/--api-key が欠落または無効、すべてのサーバー側エラー(ライセンスが必要、クォータ超過、タグ付けされていない PDF、ビルドタイムアウト、その他の API 障害)。 |
2 | Click が報告する使用方法エラー。 | 不明なコマンドまたはオプション(サブコマンドの後に置かれたグループオプションを含む)、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 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}"fi--output は指定したファイルにデータを書き込み、確認行 Written to <path> のみを stderr に出力するため、stdout は空のままになります。--output がない場合、データは stdout に出力され、リダイレクトできます。
以下の各レシピでは、検証済みのコマンドとフラグのみを使用します。いずれの場合も、資格情報は環境から取得します。
レシピ: 請求書のテーブルを CSV に抽出する
「レシピ: 請求書のテーブルを CSV に抽出する」という見出しのセクションスプレッドシートや会計のパイプライン向けに、請求書フォルダーを、ドキュメントごとに 1 つの CSV ファイルへ変換します:
#!/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 csvdone各 out/<name>.csv には、検出されたテーブルごとに 1 つの CSV ブロックが含まれ、各ブロックの前に # Table N (pM) ヘッダーが付きます。ブロックは 上記の CSV リーダーで解析してください。
レシピ: ドキュメントのアウトラインを作成する
「レシピ: ドキュメントのアウトラインを作成する」という見出しのセクション--headings-only を markdown 形式と組み合わせると、読みやすく、ノートにも貼り付けやすい簡単なアウトラインを生成できます:
nextpdf --output outline.md extract text whitepaper.pdf --headings-only --format markdownレシピ: 2 つの PDF リビジョンを差分する
「レシピ: 2 つの PDF リビジョンを差分する」という見出しのセクションCLI の ast コマンドは、単一のドキュメントツリーを返します。差分用のサブコマンドはありません。構造的な差分は、SDK では client.ast.get_ast_diff(...) として、Model Context Protocol(MCP)サーバーでは nextpdf_diff ツールとして提供されます。差分は 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"))スクリプトではなく AI エージェントから同じ差分を実行するには、MCP サーバーを登録し、nextpdf_diff ツールを呼び出します。Python MCP サーバーのページを参照してください。
レシピ: 別のツールから PDF をストリーミング入力する
「レシピ: 別のツールから PDF をストリーミング入力する」という見出しのセクション- を指定して stdin から PDF バイトを読み取るようにすると、自身の stdout に PDF を出力するツールの後ろへ nextpdf を連結できます:
curl --silent https://example.com/report.pdf | nextpdf info -- 引数は、ドキュメントを stdin から読み取るようコマンドに指示します。バイトが届かない場合、コマンドはエラーを報告し、1 で終了します。
パフォーマンスに関する注意
「パフォーマンスに関する注意」という見出しのセクションCLI は各レスポンスをメモリ内で構築してから一度に書き込むため、出力のリダイレクトやパイプは扱いやすくなりますが、出力が段階的に生成されるわけではありません。大きな AST やテーブルセットは、最初のバイトが stdout または --output ファイルに到達する前に、完全にバッファリングされます。ストリーミングではなく、ドキュメント全体のレスポンスを想定して、メモリとレイテンシを計画してください。
nextpdf を呼び出すたびに新しいクライアントと HTTP 接続が作成されるため、多数のファイルをループ処理すると、ファイルごとに接続を開いて閉じます。接続コストは通常、サーバー側の抽出時間に比べて小さいものの、規模が大きくなると無視できないオーバーヘッドになります。
- 1 つのエンドポイントを再利用する。 すべての呼び出しを同じ NextPDF Connect デプロイメントに向けて、サーバーがウォームアップ済みのキャッシュと接続プールを再利用できるようにします。意図的に負荷分散している場合を除き、バッチを複数のエンドポイントに分散させないでください。
- 呼び出しごとの作業量を制限する。
--page、--page-start/--page-end、または--token-budgetを使用して、必要なページのみを処理します。ページ範囲を小さくすると、サーバー時間とレスポンスサイズの両方を削減できます。--token-budgetは、エージェントが読み取る必要のある AST を制限します。 - 大規模なジョブは 1 つのプロセスでバッチ処理する。 大規模なバッチでは、CLI を繰り返し呼び出すより Python SDK を優先してください。長く保持する単一の
NextPDF(またはAsyncNextPDF)クライアントは、すべてのドキュメントにわたって 1 つのプールされた HTTP 接続を再利用するため、CLI ループが毎回支払うプロセスごとの起動コストと接続セットアップを取り除けます。Python の概要はクライアントのライフサイクルを示しており、AsyncNextPDFは多数の PDF にわたる並行抽出をサポートします。 - ログをデータパスから外す。 バッチ実行では
--log-levelをデフォルトのままにしてください。診断ログは stderr に出力され、stdout のデータを壊すことはありませんが、レベルをdebugに上げるとノイズとわずかなオーバーヘッドが増えます。