# 使用 Python 总结 PDF —— PDF 总结 API 教程

只需几行代码，即可将 PDF 总结功能添加到 Python 脚本、Notebook 或后端中。本教程涵盖身份验证、第一个请求、响应格式、流式传输、处理整个文件夹以及正确处理错误。

## Key facts

- 端点：POST https://pdf-summarize.com/api/summarize.php，采用 multipart/form-data 格式，字段为 file。
- 身份验证：请求头 Authorization: Bearer sk_... — 注册即可获得免费密钥，无需信用卡。
- 选项：length（short/medium/long/extensive）、format（paragraph/bullets/mixed）、outputLang（auto 或语言代码）、includeKeywords。
- 响应：包含 summary、keywords、page_count、processing_time、requests_remaining 的 JSON。
- 添加 ?stream=1 以 Server-Sent Events（服务器发送事件）形式接收总结。

## 前提条件

- Python 3.8+ 以及 `requests` 库（`pip install requests`）。
- API 密钥：[创建一个免费账户](/signup)并从控制台复制你的密钥。建议将其存储在环境变量中，而不是直接硬编码在代码里：

```bash
export PDF_SUMMARIZE_KEY="sk_live_..."
```

## 在 Python 中生成你的第一个 PDF 总结

1. **安装 requests** — pip install requests。
2. **设置你的 API 密钥** — 存入 PDF_SUMMARIZE_KEY 环境变量中。
3. **发送 PDF** — 作为 multipart/form-data 发送，字段名为 file。
4. **读取 JSON** — 总结内容在 summary 中；检查 success 和 HTTP 状态码。

```python
import os
import requests

API_URL = "https://pdf-summarize.com/api/summarize.php"
API_KEY = os.environ["PDF_SUMMARIZE_KEY"]

def summarize_pdf(path, length="medium", fmt="bullets", lang="auto"):
    with open(path, "rb") as f:
        resp = requests.post(
            API_URL,
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": (os.path.basename(path), f, "application/pdf")},
            data={"length": length, "format": fmt, "outputLang": lang, "includeKeywords": "1"},
            timeout=180,
        )
    data = resp.json()
    if resp.status_code != 200 or not data.get("success"):
        raise RuntimeError(f"{resp.status_code}: {data.get('error', data)}")
    return data

result = summarize_pdf("annual-report.pdf")
print(result["summary"])
print("页数：", result["page_count"], "| 核心要点：", result.get("keywords"))
```

## 响应内容

```json
{
  "success": true,
  "summary": "- 收入增长 6% 至...",
  "keywords": "revenue, margin, guidance, ...",
  "page_count": 48,
  "original_length": 182340,
  "summary_length": 1210,
  "processing_time": 6.214,
  "requests_remaining": 4987
}
```

`requests_remaining` 是你当月剩余的额度（`-1` 表示无限）。

## 流式传输总结

对于长文档或交互式应用，可以在生成总结时进行流式传输：

```python
import json

def stream_summary(path):
    with open(path, "rb") as f:
        with requests.post(
            API_URL + "?stream=1",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": (os.path.basename(path), f, "application/pdf")},
            data={"length": "long", "format": "mixed"},
            stream=True, timeout=300,
        ) as resp:
            resp.raise_for_status()
            for line in resp.iter_lines(decode_unicode=True):
                if not line or not line.startswith("data: "):
                    continue
                payload = line[6:]
                if payload == "[DONE]":
                    break
                event = json.loads(payload)
                if "error" in event:
                    raise RuntimeError(event["error"])
                if event.get("type") == "summary":
                    print(event["content"], end="", flush=True)

stream_summary("research-paper.pdf")
```

## 批量处理 PDF 文件夹

```python
import pathlib, time

out_dir = pathlib.Path("summaries")
out_dir.mkdir(exist_ok=True)

for pdf in sorted(pathlib.Path("pdfs").glob("*.pdf")):
    target = out_dir / (pdf.stem + ".md")
    if target.exists():
        continue                      # 支持断点续传
    for attempt in range(3):
        try:
            data = summarize_pdf(str(pdf), length="long", fmt="mixed")
            target.write_text(data["summary"], encoding="utf-8")
            print("成功", pdf.name, data["page_count"], "页")
            break
        except RuntimeError as e:
            if str(e).startswith("429"):
                time.sleep(30 * (attempt + 1))   # 触及速率限制：退避重试
            else:
                print("失败", pdf.name, e)
                break
```

## 错误处理

| 状态码 | 含义 | 处理方法 |
|---|---|---|
| 400 | 文件丢失、类型错误或超出页数限制 | 检查文件以及你当前套餐的页数限制 |
| 401 | API 密钥丢失或无效 | 检查 `Authorization` 请求头 |
| 403 | 账户已被暂停 | 联系客服支持 |
| 413 | 文件过大 | 压缩或拆分 PDF |
| 422 | 无可读文本（空白、加密或无法读取的扫描件） | 移除密码；提高扫描质量 |
| 429 | 达到速率限制或月度额度上限 | 退避并重试，或升级套餐 |
| 500 | 总结服务暂时不可用 | 退避重试 |

> **想先不写代码直接测试？** — 在浏览器中免费体验相同的底层引擎。

## 提示

- 为长 PDF 设置慷慨的**超时时间**（2-3 分钟）。
- 通过文件哈希**缓存结果**，避免为同一文档重复付费。
- **将密钥保存在服务器端** —— 切勿将其打包在前端或移动端应用中。
- 完整参数参考：请查阅 [API 文档](/docs)。

## FAQ

### 是否提供免费的 API 套餐？

是的。免费套餐包含每月的请求额度，无需绑定信用卡。详情请查看定价。

### 可以直接发送 PDF 的 URL 网址而不是文件吗？

API 接收的是文件本身。你需要在代码中下载 PDF（例如使用 requests）并发送其二进制数据。

### 总结支持哪些语言？

使用 outputLang=auto 可保留文档的原语言，或指定语言代码，如 en、fr、es、de。

### 如何通过 API 总结扫描版的 PDF？

像发送普通 PDF 一样发送即可；当没有可用的文本层时，提取流程会自动启用 OCR。

---
Source: https://pdf-summarize.com/zh/guides/pdf-summary-api-python — PDF Summarizer (free PDF summarizer, Q&A with page citations, OCR, REST API). Site overview: https://pdf-summarize.com/llms.txt
