Bỏ qua để đến nội dung

Python CLI

Sử dụng lệnh nextpdf để trích xuất nội dung từ các tệp Portable Document Format (PDF) ngay trong terminal. Trỏ lệnh đến một endpoint NextPDF Connect, truyền vào một tệp PDF, rồi nhận kết quả có cấu trúc — văn bản có trích dẫn, bảng, toàn bộ cây cú pháp trừu tượng (Abstract Syntax Tree, AST) ngữ nghĩa, hoặc bản tóm tắt metadata — trên đầu ra chuẩn (stdout) hoặc trong một tệp.

Lệnh nextpdf là một nhóm lệnh Click. Các tùy chọn kết nối và phiên — --base-url, --api-key, --log-level, --output/-o, và --strict — thuộc về nhóm, nên hãy đặt chúng trước lệnh con. Đặt lệnh con và các tùy chọn của lệnh con, chẳng hạn --format hoặc --page, ở phía sau:

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

Nếu bạn đặt một tùy chọn nhóm sau lệnh con, lệnh sẽ thất bại. Ví dụ, nextpdf info document.pdf --base-url ... sẽ báo Error: No such option: --base-url và thoát với trạng thái 2, vì Click đã phân tích lệnh con info khi gặp --base-url, còn info không định nghĩa tùy chọn đó.

Để tránh lỗi về thứ tự, hãy cung cấp thông tin xác thực qua các biến môi trường (xem Cấu hình một lần cho mỗi shell). Các ví dụ bên dưới dùng cờ tường minh trước để thứ tự đúng thật rõ ràng.

Trích xuất văn bản dưới dạng JavaScript Object Notation (JSON):

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

Trích xuất bảng dưới dạng giá trị phân tách bằng dấu phẩy (CSV):

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

Kiểm tra metadata và cấu trúc của tài liệu:

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

Lấy toàn bộ AST ngữ nghĩa:

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

In phiên bản bộ công cụ phát triển phần mềm (SDK) đã cài đặt mà không cần liên hệ với máy chủ:

Terminal window
nextpdf version

Lệnh version là lệnh duy nhất không cần --base-url hoặc --api-key. Mọi lệnh khác đều liên hệ với máy chủ và yêu cầu cả hai.

Mỗi ví dụ đọc khóa giao diện lập trình ứng dụng (API) từ biến môi trường NEXTPDF_API_KEY thay vì nhúng trực tiếp vào dòng lệnh. Hãy coi khóa này là bí mật. Khóa ở dạng nguyên văn trên dòng lệnh sẽ xuất hiện trong lịch sử shell và trong danh sách tiến trình (ps) với những người dùng khác trên máy chủ.

Đặt các tùy chọn này trước lệnh con. Mỗi tùy chọn kết nối cũng đọc từ một biến môi trường, nên có thể bỏ qua cờ khi biến đã được thiết lập.

Tùy chọnBiến môi trườngMặc địnhMục đích
--base-urlNEXTPDF_BASE_URL(bắt buộc)Định vị tài nguyên thống nhất (URL) của máy chủ NextPDF Connect.
--api-keyNEXTPDF_API_KEY(bắt buộc)Khóa API để xác thực bearer.
--log-levelwarningMức độ chi tiết của nhật ký: debug, info, warning, hoặc error. Nhật ký được ghi ra lỗi chuẩn (stderr).
--output, -ostdoutGhi đầu ra của lệnh vào một tệp thay vì stdout.
--stricttắtDành cho việc dùng trong tương lai. Hiện tại cờ này được phân tích nhưng không thay đổi hành vi.
--help, -hHiển thị trợ giúp và thoát.

Các giá trị --base-url--api-key là bắt buộc với mọi lệnh trừ version. Nếu thiếu một trong hai giá trị — không có cờ và không có biến môi trường — lệnh sẽ in lỗi và thoát với trạng thái 1.

Trích xuất các khối văn bản có trích dẫn. Mỗi khối bao gồm một mỏ neo trích dẫn cùng mã định danh nút, chỉ số trang, hộp bao và điểm tin cậy.

nextpdf [GROUP OPTIONS] extract text PDF_PATH [--format FORMAT] [--page N] [--headings-only]
Tùy chọnGiá trịMặc địnhMục đích
--formatjson, markdown, plainjsonĐịnh dạng đầu ra.
--pagesố nguyêntất cả trangChỉ trích xuất chỉ số trang dựa trên 0 này.
--headings-onlycờtắtChỉ trích xuất các nút tiêu đề.

PDF_PATH là một đường dẫn tệp, hoặc - để đọc byte PDF từ đầu vào chuẩn (stdin).

Trích xuất mọi bảng cùng các mỏ neo trích dẫn và cấu trúc ở cấp ô.

nextpdf [GROUP OPTIONS] extract tables PDF_PATH [--format FORMAT] [--page-start N] [--page-end N]
Tùy chọnGiá trịMặc địnhMục đích
--formatjson, csvjsonĐịnh dạng đầu ra.
--page-startsố nguyêntrang đầuChỉ số trang bắt đầu (dựa trên 0).
--page-endsố nguyêntrang cuốiChỉ số trang kết thúc (dựa trên 0).

PDF_PATH là một đường dẫn tệp, hoặc - để đọc từ stdin.

Trả về toàn bộ AST ngữ nghĩa dưới dạng JSON: một cây nút phân cấp, bao gồm tiêu đề, đoạn văn, bảng, danh sách và hình minh họa, kèm theo hộp bao và nội dung văn bản.

nextpdf [GROUP OPTIONS] ast PDF_PATH [--page-start N] [--page-end N] [--token-budget N]
Tùy chọnGiá trịMặc địnhMục đích
--page-startsố nguyêntrang đầuChỉ số trang bắt đầu (dựa trên 0).
--page-endsố nguyêntrang cuốiChỉ số trang kết thúc (dựa trên 0).
--token-budgetsố nguyênkhông giới hạnGiới hạn token gần đúng cho AST trả về.

PDF_PATH là một đường dẫn tệp, hoặc - để đọc từ stdin. Lệnh ast tạo ra một cây tài liệu; lệnh này không so sánh hai tệp PDF. Để so sánh khác biệt về cấu trúc, xem Công thức: so sánh hai bản sửa đổi PDF.

In một bản tóm tắt JSON gọn về tài liệu: phiên bản schema, source hash, số trang, số token ước tính, kiểu nút gốc và số nút con của gốc.

nextpdf [GROUP OPTIONS] info PDF_PATH

PDF_PATH là một đường dẫn tệp, hoặc - để đọc từ stdin.

In phiên bản SDK đã cài đặt, chẳng hạn nextpdf 1.1.0, rồi thoát. Lệnh này không liên hệ với máy chủ và không cần thông tin xác thực.

nextpdf version

Thiết lập các tùy chọn kết nối một lần dưới dạng biến môi trường, rồi bỏ qua các cờ lặp lại. Cách này cũng tránh hoàn toàn lỗi thứ tự tùy chọn, vì thông tin xác thực không bao giờ xuất hiện trên dòng lệnh.

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

Trên Windows PowerShell:

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

Bạn nên nạp khóa từ một kho bí mật hoặc một tệp .env được giữ ngoài hệ thống quản lý phiên bản. Không dán khóa môi trường sản xuất vào phiên terminal dùng chung hoặc vào script mà bạn commit.

Chọn định dạng đầu ra cho từng lệnh bằng --format. Các lệnh text và table hỗ trợ nhiều định dạng; astinfo luôn xuất JSON.

LệnhĐịnh dạngMặc định
extract textjson, markdown, plainjson
extract tablesjson, csvjson
astjsonjson
infojsonjson

Chọn JSON khi chương trình phía sau cần chỉ số trang, điểm tin cậy hoặc mã định danh nút. Chọn CSV khi bảng tính hoặc quy trình dạng bảng cần dùng các bảng. Chọn văn bản plain hoặc markdown khi người dùng hoặc công cụ chỉ xử lý văn bản đọc kết quả.

Lệnh text xuất ra một mảng JSON gồm các khối có trích dẫn. Mỗi khối có text, một đối tượng citation (node_id, page_index, bbox, confidence) và một node_type tùy chọn. Gửi đầu ra vào một tệp bằng --output, hoặc chuyển hướng stdout, rồi phân tích dữ liệu đó.

Ví dụ shell này dùng jq để chỉ giữ lại các tiêu đề trên trang 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

Dữ liệu tương tự cũng có thể được phân tích gọn gàng trong Python. Giao diện dòng lệnh (CLI) ghi ra một mảng JSON, nên hãy nạp dữ liệu bằng thư viện chuẩn và đọc các trường có kiểu:

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

Khi cần các mô hình đã được kiểm tra và có kiểu thay vì từ điển thô, hãy gọi trực tiếp SDK thay vì phân tích đầu ra CLI. Xem Tổng quan Python để biết về client NextPDF và kiểu trả về CitedTextBlock của nó.

Với --format csv, lệnh table ghi một khối CSV cho mỗi bảng. Một hàng chú thích, # Table N (pM), đứng trước mỗi bảng và nêu số thứ tự bảng dựa trên 1 cùng chỉ số trang dựa trên 0 của bảng đó. Một dòng trống ngăn cách các bảng liên tiếp. CLI trích dẫn và thoát ký tự cho các giá trị ô bằng module csv của Python, nên các giá trị chứa dấu phẩy, dấu ngoặc kép hoặc ký tự xuống dòng vẫn được bảo toàn an toàn qua mỗi lượt.

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

Vì tệp chứa nhiều khối CSV, hãy tách theo các hàng chú thích trước khi phân tích từng khối như một bảng độc lập:

"""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 dùng ba mã thoát. Kiểm tra $? trong các script shell, hoặc $LASTEXITCODE trong PowerShell, để rẽ nhánh theo thành công hoặc thất bại. Đọc thông báo chẩn đoán từ stderr, vốn tách biệt với dữ liệu trên stdout.

Mã thoátÝ nghĩaVí dụ
0Thành công.Một lệnh đã hoàn tất; version đã in ra.
1Lỗi thời gian chạy. CLI in Error: <message> ra stderr.Không tìm thấy tệp đầu vào hoặc tệp đầu vào không phải tệp thông thường, stdin rỗng, thiếu hoặc không hợp lệ --base-url/--api-key, bất kỳ lỗi phía máy chủ nào (yêu cầu giấy phép, vượt hạn mức, PDF chưa được gắn thẻ, hết thời gian dựng hoặc lỗi API khác).
2Lỗi sử dụng, do Click báo cáo.Lệnh hoặc tùy chọn không xác định (bao gồm một tùy chọn nhóm đặt sau lệnh con), thiếu một đối số bắt buộc chẳng hạn PDF_PATH.

Mọi lỗi phía máy chủ đều trả về mã thoát 1 cùng một thông báo dễ đọc trên stderr. SDK ném ra một ngoại lệ có kiểu — NextPDFLicenseError (Hypertext Transfer Protocol (HTTP) 402), QuotaExceededError (HTTP 429), AstNoStructTreeError (HTTP 422, PDF chưa được gắn thẻ), AstBuildTimeoutError (HTTP 504), hoặc NextPDFAPIError cơ sở. CLI bắt tất cả dưới lớp cơ sở chung NextPDFError, in thông báo và thoát 1. CLI không bộc lộ mã thoát riêng cho từng loại lỗi. Để phân biệt, chẳng hạn, lỗi hạn mức với lỗi giấy phép trong script, hãy kiểm tra nội dung thông báo trên stderr hoặc gọi trực tiếp SDK (xem Tổng quan Python để biết các lớp ngoại lệ).

Dùng mẫu script này để tách dữ liệu khỏi thông tin chẩn đoán:

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

Với --output, CLI ghi dữ liệu vào tệp được đặt tên và chỉ in dòng xác nhận Written to <path> ra stderr, nên stdout vẫn rỗng. Khi không có --output, dữ liệu đi ra stdout và bạn có thể chuyển hướng dữ liệu đó.

Mọi công thức bên dưới chỉ dùng các lệnh và cờ đã được kiểm chứng. Trong từng trường hợp, thông tin xác thực đều đến từ môi trường.

Công thức: trích xuất bảng hóa đơn ra CSV

Phần tiêu đề “Công thức: trích xuất bảng hóa đơn ra CSV”

Biến một thư mục hóa đơn thành một tệp CSV cho mỗi tài liệu để phục vụ bảng tính hoặc quy trình kế toán:

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

Mỗi out/<name>.csv chứa một khối CSV cho mỗi bảng được phát hiện, với tiêu đề # Table N (pM) đứng trước mỗi khối. Phân tích các khối bằng bộ đọc CSV được trình bày ở trên.

Công thức: dựng một mục lục tài liệu

Phần tiêu đề “Công thức: dựng một mục lục tài liệu”

Kết hợp --headings-only với định dạng markdown để tạo nhanh mục lục mà bạn có thể đọc hoặc dán vào ghi chú:

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

Lệnh ast của CLI trả về cây cho một tài liệu; lệnh này không có lệnh con so sánh. Tính năng so sánh khác biệt về cấu trúc nằm trong SDK ở dạng client.ast.get_ast_diff(...) và trong máy chủ Model Context Protocol (MCP) ở dạng công cụ nextpdf_diff. Chạy phép so sánh thông qua 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"))

Để chạy cùng phép so sánh đó từ một tác nhân trí tuệ nhân tạo (AI) thay vì từ script, hãy đăng ký máy chủ MCP và gọi công cụ nextpdf_diff. Xem trang Máy chủ Python MCP.

Công thức: truyền vào một tệp PDF từ một công cụ khác

Phần tiêu đề “Công thức: truyền vào một tệp PDF từ một công cụ khác”

Đọc byte PDF từ stdin với - để nối nextpdf sau một công cụ phát ra tệp PDF trên stdout của chính công cụ đó:

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

Đối số - báo cho lệnh đọc tài liệu từ stdin. Nếu không nhận được byte nào, lệnh sẽ báo lỗi và thoát 1.

CLI dựng mỗi phản hồi trong bộ nhớ và ghi một lần. Việc chuyển hướng hoặc đưa đầu ra qua pipe rất đơn giản, nhưng đầu ra không được tạo theo từng phần. Một AST hoặc tập bảng lớn được đệm đầy đủ trước khi byte đầu tiên đến stdout hoặc tệp --output. Hãy dự trù bộ nhớ và độ trễ cho các phản hồi trên toàn bộ tài liệu, không phải cho một luồng.

Mỗi lần gọi nextpdf tạo một client và kết nối HTTP mới, nên vòng lặp qua nhiều tệp sẽ mở và đóng một kết nối cho mỗi tệp. Chi phí kết nối thường nhỏ so với thời gian trích xuất phía máy chủ, nhưng sẽ trở thành phụ phí đáng kể ở quy mô lớn.

  • Tái sử dụng một endpoint. Trỏ mọi lần gọi đến cùng một triển khai NextPDF Connect để máy chủ có thể tái sử dụng các bộ nhớ đệm đã được làm nóng và các nhóm kết nối. Tránh phân tán một lô qua nhiều endpoint trừ khi bạn chủ động cân bằng tải.
  • Giới hạn khối lượng công việc cho mỗi lần gọi. Dùng --page, --page-start/--page-end, hoặc --token-budget để chỉ xử lý các trang cần thiết. Phạm vi trang nhỏ hơn giúp giảm cả thời gian máy chủ lẫn kích thước phản hồi; --token-budget giới hạn AST mà tác nhân của bạn phải đọc.
  • Gộp lô trong một tiến trình cho các tác vụ lớn. Với các lô khối lượng lớn, hãy ưu tiên Python SDK thay vì gọi CLI lặp đi lặp lại. Một client NextPDF hoặc AsyncNextPDF tồn tại lâu dài duy nhất sẽ tái sử dụng kết nối HTTP đã gộp sẵn cho mọi tài liệu, nhờ đó loại bỏ phần khởi động cho mỗi tiến trình và chi phí thiết lập kết nối mà vòng lặp CLI phải trả mỗi lần. Tổng quan Python trình bày vòng đời của client, và AsyncNextPDF hỗ trợ trích xuất đồng thời trên nhiều tệp PDF.
  • Giữ nhật ký ngoài đường dữ liệu. Để --log-level ở mức mặc định cho các lần chạy theo lô. Nhật ký chẩn đoán đi ra stderr và không làm hỏng dữ liệu stdout, nhưng nâng mức lên debug sẽ thêm nhiễu và một ít phụ phí.