extract-pdf

中文文档
0.1.552发布于 2026/11/03rights.institute/PROSPERTypeScriptESM + CJS构建来源已验证

转换PDF (URL或ArrayBuffer)到干净的HTML与结构标签-标题,列表,脚注,代码块,粗体/斜体。默认为Slim (PDF.js在运行时从pdfjs-无服务器CDN构建中加载),为页面w提供可选的Granite Docling OCR

中文使用文档
文档目录12 节
  1. 安装
  2. 文档和现场演示
  3. 用法
  4. 选项
  5. 返回值
  6. 解析方法
  7. 处理器模式:前端、混合、文档OCR或远程URL
  8. 运行文档处理程序服务器
  9. 在hug Face Spaces上托管处理器
  10. 检测PDF是否需要OCR
  11. 管道
  12. 文件夹结构


Documentation GitHub Stars NPM Monthly Downloads npm version NPM Total Downloads TypeScript types Install size
GitHub Issues Open Pull Requests Merged Pull Requests GitHub Discussions GitHub last commit
Open in StackBlitz Bun TypeScript Vite

🤖座席技能 - - - - - - npx skills@latest add https://github.com/OpenSourceAGI/qwksearch-research-agent --skill extract-pdf (它涵盖了什么)

extract-pdf

当用户上传PDF时,他们希望得到即时聊天响应,而不是在OCR模型上等待5分钟。

即时无后端需要javascript转换PDF (URL或 ArrayBuffer)变成干净的HTML与结构标签-标题,列表,脚注,代码块,粗体/斜体,和目录条目。可以在Node.js、Cloudflare Workers和浏览器环境中工作 pdfjs-serverless。

默认为Slim: 该软件包不捆绑PDF引擎。PDF.js是在运行时从jsdeliver的ESM构建中惰性加载的 pdfjs-serverless (https://cdn.jsdelivr.net/npm/pdfjs-serverless@1/+esm(固定在主版本上)-零依赖,单个~1.6 MB的Mozilla PDF.js的再分发,为无服务器/边缘运行时构建。Node.js和Bun不能导入远程url,所以加载器会返回到本地安装的 pdfjs-serverless 可选依赖。所有与ocr相关的东西(花岗岩) @huggingface/transformers, @napi-rs/canvas)同样是可选的,只在实际使用时才导入。

为了在包含信息图表、图表和表格的页面上实现ocr级保真度,软件包还附带了Granite Docling路径(从前者合并而来) extract-pdf-docling 包):通过前端JS解析器运行所有页面,通过文档OCR运行所有页面 混合动力 模式,只对需要它的页面和ocr进行regex扫描,或者指向远程文档兼容处理器的URL(参见 server/).

安装

bun add extract-pdf

文档和现场演示

site/ 是否有一个Cloudflare Worker为这个包提供文档服务 extract-webpage,另外还有现场演示 /demo:上传PDF或粘贴URL,并获得HTML返回 /api/convert,配合OCR跟进,或通过提取网页 /api/extract. 运行它 bun install 然后在存储库根目录下 cd site && bun run dev. CI在每次涉及它的推送上部署它。看到 网站/ README.md 用于秘密,自定义域,CPU限制和加固。

用法

import { convertPDFToHTML } from "extract-pdf";

const { html, title, author } = await convertPDFToHTML(
  "https://example.com/paper.pdf",
);
// or pass an ArrayBuffer from fs.readFile / fetch
const { html } = await convertPDFToHTML(buffer, { addPageNumbers: true });

选项

选项默认的描述
addPageNumbersfalse插入 [n] 每一页边界处的标记
addCitationtrue读取PDF元数据和要填充的第一页标题 title/author 在返回值中
method"ts-block-algorithm"解析引擎—— "ts-block-algorithm", "liteparse",或 "liteparse-wasm" (见下文)
liteParseOptions{}传递给LiteParse的构造函数 method 是 "liteparse" 或 "liteparse-wasm"
processor"frontend"OCR发生在哪里 "frontend", "hybrid", "docling",或处理器URL(见下文)
processorUrl- - - - - -使用的远程文档兼容API "hybrid"/"docling" 而不是进程内模型
ocrScanOptions{}混合页面扫描的阈值调优(scanPagesForOCR)
doclingOptions{}prompt, maxTokens, scale 为dooping OCR模型 processorHeaders 发送到 processorUrl

返回值

{ html: string, title?: string, author?: string, format: "pdf",
  processor: string, ocrScan: OcrScanResult }

解析方法

convertPDFToHTML 支持三种可互换的解析引擎 options.method:

方法引擎环境光学字符识别
"ts-block-algorithm" (默认)下面记录的pure-TS管道(这个包)Node.js, Cloudflare Workers,浏览器否
"liteparse"LiteParse (本地, @llamaindex/liteparse)node . js只可选
"liteparse-wasm"LiteParse (WASM @llamaindex/liteparse-wasm)Node.js, Cloudflare Workers,浏览器可选(通过回调)
import { convertPDFToHTML } from "extract-pdf";

const { html } = await convertPDFToHTML(buffer, { method: "liteparse" });

// Or the WASM build, which also runs in browsers and Cloudflare Workers:
const { html } = await convertPDFToHTML(buffer, { method: "liteparse-wasm" });

LiteParse附带了一个本地(napi)插件,所以 method: "liteparse" 只跑进去 Node.js——它没有被绑定到浏览器或Cloudflare Workers构建中。安装 它明确地(bun add @llamaindex/liteparse),因为它是可选的 依赖;如果没有安装, convertPDFToHTML 返回 { error } 而不是扔。

method: "liteparse-wasm" 将委托给LiteParse的WebAssembly构建, 它可以运行在WASM支持的任何地方——浏览器、Cloudflare Workers和Node.js。 显式安装它(bun add @llamaindex/liteparse-wasm),因为它也是 可选的依赖项;如果没有安装, convertPDFToHTML 返回 { error } 而不是扔。WASM构建没有内置OCR引擎 通过一项 liteParseOptions.ocrEngine 回调(例如由 tesseract-js) 启用OCR。

默认情况下,两个LiteParse路径在禁用OCR的情况下运行(ocrEnabled: false) - - - 符合这个包的“即时,无后端”的哲学。使用 detectPdfNeedsOcr (见下文)来决定何时值得重新解析文档 liteParseOptions: { ocrEnabled: true }。

处理器模式:前端、混合、文档OCR或远程URL

分开 method, processor 选项决定页面是否删除 通过 花岗岩Docling OCR模型——保留布局、表格、图表、代码和公式 每页模型推理成本:

processor会发生什么
"frontend" (默认)所有页面都由纯js文本层管道解析。没有OCR,没有模型,即时。
"hybrid"JS管道无处不在+正则表达式扫描(scanPagesForOCR)标记带有信息图表/数字/表格或没有可用文本层的页面;只有那些页面是栅格化的,并使用文档进行OCR识别。
"docling"每一页都栅格化了,用OCR打印。
"https://..." (URL)就像 "docling",但是每个页面都被post到与文档兼容的处理器API,而不是在进程中运行模型。
// Hybrid: fast JS parse, OCR only the pages that need it
const { html, ocrScan } = await convertPDFToHTML(buffer, { processor: "hybrid" });
console.log(ocrScan.pagesNeedingOcr); // e.g. [3, 7] — pages with tables/figures
// each ocrScan.pages[i] lists reasons: "table-caption", "figure-caption",
// "table-rows", "numeric-grid", "no-text", "sparse-text", "garbled-text"

// All pages through a remote Docling processor (this package's server/):
const { html } = await convertPDFToHTML(buffer, {
  processor: "http://localhost:3000",
});

// Hybrid with the OCR offloaded to a remote processor:
const { html } = await convertPDFToHTML(buffer, {
  processor: "hybrid",
  processorUrl: "http://localhost:3000",
});

使用OCR的页面以 <section class="ocr-page" id="page-N">…</section> (表格变得真实 <table> 标记、标题 <figcaption>,公式 <code class="formula">,……);OCR失败的页面保留其js解析的HTML。

运行Docling 进程内的 需要可选的 @huggingface/transformers 依赖(ONNX模型) onnx-community/granite-docling-258M-ONNX, ~ 1gb; 第一次使用时下载)和-在Node.js中- @napi-rs/canvas 对页面 光栅化(浏览器/工作器使用) OffscreenCanvas).

正则表达式扫描器也是独立导出的,OCR帮助器也是如此:

import { scanPagesForOCR, doctagsToHtml, ocrImageWithDocling } from "extract-pdf";

const scan = scanPagesForOCR(pageTexts); // string[] of per-page text
// { needsOcr, pagesNeedingOcr: number[], pages: [{ page, reasons, captions }] }

运行文档处理程序服务器

这个 server/ 文件夹包含Hono HTTP API(以前是 extract-pdf-docling 暴露花岗岩Docling模型:

bun run serve:docling   # or dev:docling for --watch; port 3000
  • 昂首阔步界面: http://localhost:3000/docs,说明 /openapi.json
  • POST /api/v1/convert - - - - - - { imageUrl, prompt?, maxTokens? }
  • POST /api/v1/convert-base64 - - - - - - { imageBase64, mimeType?, prompt?, maxTokens? }
  • POST /api/v1/convert-stream - SSE令牌流
  • GET /health

一个 server/wrangler.jsonc 将其部署为Cloudflare Worker。 它的任何部署(或具有相同契约的任何API)都可以作为 processor/processorUrl 上面的选项。

在hug Face Spaces上托管处理器

docling-space/ 包装与“拥抱脸”相同的型号 Docker空间:令牌验证,每次生成一个有界队列 模型惰性加载,以及可选的经过处理的HTML输出。它的README有 部署步骤。发送空间的令牌(如果是私人空间,则发送拥抱脸) 读取令牌) doclingOptions.processorHeaders:

const { html } = await convertPDFToHTML(buffer, {
  processor: "hybrid",
  processorUrl: "https://YOUR_HF_USERNAME-extract-pdf-docling.hf.space",
  doclingOptions: {
    processorHeaders: {
      "X-Docling-Token": process.env.DOCLING_API_TOKEN,
      Authorization: `Bearer ${process.env.HF_SPACE_TOKEN}`, // private Space only
    },
    maxTokens: 1500,
  },
});

混合模式在返回之前仍然等待每个标记的页面。回答… 一旦增强,之后就跑 processor: "frontend",返回它的HTML,和 光学字符识别 ocrScan.pagesNeedingOcr 作为后续;这个 现场演示 做 正是如此。

检测PDF是否需要OCR

在提交完整的(可能很慢的)OCR解析之前, detectPdfNeedsOcr 运行一个廉价的、仅限文本层的通道,并报告每个页面是否需要OCR或 其他繁重的解析——用于将文档路由到不同的管道 (快速路径vs. OCR vs.截图vs. LlamaParse或 Docling):

import { detectPdfNeedsOcr, convertPDFToHTML } from "extract-pdf";

const assessment = await detectPdfNeedsOcr(buffer);
// { needsOcr: boolean, pages: PageComplexityStats[], reasons: string[] }

if (!assessment.needsOcr) {
  const { html } = await convertPDFToHTML(buffer, { method: "liteparse" });
} else {
  console.log("Needs OCR:", assessment.reasons); // e.g. ["scanned", "sparse-text"]
  // Route to an OCR-enabled pipeline, e.g.:
  const { html } = await convertPDFToHTML(buffer, {
    method: "liteparse",
    liteParseOptions: { ocrEnabled: true },
  });
}

reasons 收集在页面上发现的每个不同的信号; "scanned", "no-text", "sparse-text", "embedded-images", "garbled",或 "vector-text"。就像 method: "liteparse",这是Node.js只需要 @llamaindex/liteparse。

管道

对象上运行一个顺序的转换链 ParseResult (页→项):

Raw pdfjs text spans
  → CalculateGlobalStats   — font heights, distances, format map
  → CompactLines           — merge spans on the same y-line into LineItems
  → RemoveRepetitiveElements — strip recurring page headers/footers
  → VerticalToHorizontal   — rotate vertical character runs
  → DetectTOC              — identify Table of Contents pages, link headings
  → DetectHeaders          — classify items as H1–H6 by font height
  → DetectListItems        — detect bullet/numbered list items
  → GatherBlocks           — group adjacent same-type lines into blocks
  → DetectCodeQuoteBlocks  — mark indented blocks as CODE
  → DetectListLevels       — add indentation for nested list levels
  → ToTextBlocks           — flatten blocks to { category, text } pairs
  → ToHTML                 — render pairs as <p>, <h1>–<h6>, <ul>, <code>

文件夹结构

src/
  pdf-to-html.ts          — main entry point (convertPDFToHTML)
  liteparse-to-html.ts    — "liteparse" method (native napi addon)
  liteparse-wasm-to-html.ts — "liteparse-wasm" method (WASM, browser/edge)
  ocr-page-scan.ts        — regex scan flagging infographic/table pages for OCR
  docling-ocr.ts          — Granite Docling OCR (local ONNX or remote URL),
  │                         page rasterization, doctags → HTML
  detect-needs-ocr.ts     — LiteParse-based OCR routing (Node.js only)
  models/                 — data classes: Page, ParseResult, TextItem,
  │                         LineItem, LineItemBlock, Word, BlockType, …
  transforms/
  │  base/                — abstract Transformation, ToLineItem*, ToLineItemBlock*
  │  line-item/           — per-line-item transformations
  │  block/               — per-block transformations
  │  calculate-global-stats.ts
  │  to-text-blocks.ts
  │  to-html.ts
  utils/
     load-pdfjs.ts        — lazy CDN loader for pdfjs-serverless
     string-functions.ts
     page-item-functions.ts
     page-number-functions.ts
server/                   — Granite Docling HTTP processor (Hono):
   server.js, routes.js, schemas.js, model.js, wrangler.jsonc

版本与发布记录

extract-pdf 共发布 553 个版本,首次发布于 2026/06/04;过去 12 个月发布了 553 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.552latest2026/11/03今天
0.1.5512026/11/03今天
0.1.5502026/11/03今天
0.1.5492026/11/03今天
0.1.5482026/11/03今天
0.1.5472026/11/03今天

关于 extract-pdf 的常见问题

extract-pdf 是什么?

转换PDF (URL或ArrayBuffer)到干净的HTML与结构标签-标题,列表,脚注,代码块,粗体/斜体。默认为Slim (PDF.js在运行时从pdfjs-无服务器CDN构建中加载),为页面w提供可选的Granite Docling OCR

如何安装 extract-pdf?

在项目目录运行 npm install extract-pdf,或使用 pnpm add / yarn add / bun add。

extract-pdf 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

extract-pdf 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

extract-pdf 可以商用吗?

extract-pdf 使用 rights.institute/PROSPER 许可。声明的许可为 rights.institute/PROSPER,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

extract-pdf 还在维护吗?

最新版本 0.1.552 发布于 2026/11/03(今天);至今共发布 553 个版本,其中过去 12 个月发布了 553 个;首次发布于 2026/06/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。