开篇:一份测试文档
2026年1月1日,新年第一天。
前几天,一位挚友发来一份文档——《Indonesia Investment Guidebook》,印尼投资部的官方投资指南,97页,全是投资政策、税收优惠、经济特区这些硬核内容。
她是 Master-Translator 这个项目的灵感来源。最近我们在聊能不能把 AI 翻译这件事进一步技术落地,她从一位律所合伙人那里拿到这份文档,想让我测试一下实际效果。
正好。前阵子刚用 Master-Translator 翻译了一本320页的技术书籍,这97页官方文档是个不错的试金石。
结果,MinerU 桌面版给我来了个下马威——进度条走到一半就卡死了。没有报错,没有日志,就是不动了。
这新年第一天,总不能就这么认输吧?
MinerU 不是有远程 API 吗?既然桌面版不行,那就直接调 API。更进一步,能不能逐页诊断,找出到底是哪一页有问题?
窗外朋友圈还在刷跨年祝福,我已经打开了 Claude,准备开干。
Part 1: MinerU API 的"考古"之旅
从官方文档到 GitHub 源码
MinerU 官方提供了 API 服务(mineru.net),但官方文档的 API 版本信息有些混乱。我最初尝试的端点都返回 404:
# 官方文档说的 v1 接口 - 404
POST https://mineru.net/api/v1/pdf/convert
# 我猜测的 v3 接口 - 还是 404
POST https://mineru.net/api/v3/extract
这让我意识到:官方文档可能已经过时。
转机来自 GitHub。在 MinerU 官方仓库中,我找到了一个 MCP Client 示例代码,里面暴露了真正的 API 端点:
# 正确的 v4 API 端点
BASE_URL = "https://mineru.net"
BATCH_URL = f"{BASE_URL}/api/v4/file-urls/batch"
RESULT_URL = f"{BASE_URL}/api/v4/extract-results/batch/{{batch_id}}"
教训一:当官方文档过时时,去看官方的 SDK 或 Client 代码。
OSS 上传的代理陷阱
找到正确端点后,新的问题出现了。API 的工作流程是:
- 调用
/api/v4/file-urls/batch获取 OSS 上传 URL - PUT 文件到 OSS URL
- 轮询
/api/v4/extract-results/batch/{batch_id}获取结果
第一步成功了,但第二步——PUT 上传到阿里云 OSS——失败了:
SSL: CERTIFICATE_VERIFY_FAILED
排查后发现:我的系统配置了代理,而阿里云 OSS 的 SSL 证书验证在代理环境下出了问题。
解决方案出奇的简单:
# 创建一个不使用系统代理的 session
session = requests.Session()
session.trust_env = False # 关键!绕过系统代理
# 使用这个 session 进行 OSS 上传
session.put(oss_url, data=file_data)
教训二:当 HTTPS 请求莫名其妙失败时,检查代理配置。
Content-Type 的微妙差异
还有一个坑:上传到 OSS 时,不要设置 Content-Type header。
# 错误 ❌
headers = {"Content-Type": "application/pdf"}
requests.put(oss_url, data=data, headers=headers)
# 正确 ✅ - OSS 签名 URL 已包含 Content-Type 信息
requests.put(oss_url, data=data)
如果自己设置 Content-Type,会与预签名 URL 中的签名不匹配,导致 403 Forbidden。
Part 2: 逐页诊断 PDF 问题
为什么桌面版失败?
MinerU 桌面版处理这份97页 PDF 时失败,但没有给出具体原因。我的假设是:可能某些页面有特殊格式导致解析失败。
为了验证这个假设,我写了一个逐页诊断脚本:
# diagnose_pdf_official.py 核心逻辑
from pypdf import PdfReader, PdfWriter
import tempfile
def diagnose_pdf(pdf_path, start_page=1, end_page=None):
"""逐页提取并测试每一页"""
reader = PdfReader(pdf_path)
total_pages = len(reader.pages)
results = []
for page_num in range(start_page, min(end_page or total_pages, total_pages) + 1):
# 创建单页 PDF
writer = PdfWriter()
writer.add_page(reader.pages[page_num - 1])
with tempfile.NamedTemporaryFile(suffix='.pdf') as tmp:
writer.write(tmp.name)
# 调用 API 测试这一页
result = client.extract_file(tmp.name)
results.append({
'page': page_num,
'success': result.success,
'error': result.error if not result.success else None
})
return results
测试结果:全部通过!
运行诊断脚本测试前5页:
python diagnose_pdf_official.py "Indonesia_Investment_Guidebook.pdf" \
--start 1 --end 5 --model vlm
结果出人意料:
📊 诊断结果汇总:
================
成功: 5/5 页 (100.00%)
失败: 0 页
✅ 所有测试页面均处理成功!
所有页面都能正常解析! 这意味着桌面版的失败可能是其他原因(内存、超时、或版本差异)。
既然 API 可以正常工作,那就直接用 API 处理整个文档吧。
Part 3: 完整解析与翻译
使用 VLM 模型解析
VLM(Vision Language Model)是 MinerU 提供的高级模型,相比传统 OCR 管道,对表格和复杂布局的处理更好。
python mineru_client.py "Indonesia_Investment_Guidebook.pdf" \
--model vlm \
--output ./output
约3分钟后,解析完成:
✅ 提取成功!
批次ID: a5d6e18f-69d6-4428-bd3c-065adeaa2e8d
ZIP URL: https://cdn.mineru.net/...
耗时: 188.2 秒
📥 结果已下载到: ./output
- full.md (168KB)
- images/ (119张图片)
解析结果统计
| 指标 | 数值 |
|---|---|
| 原 PDF 页数 | 97 页 |
| Markdown 行数 | 2,242 行 |
| 总字符数 | 172,160 |
| 图片数量 | 119 张 |
| HTML 表格数 | 26 个 |
表格被完美提取为 HTML 格式,包括复杂的合并单元格:
<table>
<tr>
<td rowspan="2">Tax Holiday</td>
<td colspan="4">Applying general provisions...</td>
<td>TH is applicable</td>
</tr>
...
</table>
构建术语表
投资类文档最怕的就是术语翻译不一致——同一个机构名,前面叫"投资协调委员会",后面又变成"投资管理局",读者会懵。
所以在翻译之前,我先让 Claude 基于文档内容构建了一个72条术语的专业术语表:
[
{"term": "FDI", "translation": "外国直接投资", "note": "Foreign Direct Investment"},
{"term": "BKPM", "translation": "印尼投资协调委员会", "note": "Badan Koordinasi Penanaman Modal"},
{"term": "OSS RBA", "translation": "在线单一提交系统(风险评估版)", "note": "Online Single Submission Risk Based Approach"},
{"term": "Job Creation Law", "translation": "创造就业法", "note": "2020年第11号法律"},
{"term": "SEZ", "translation": "经济特区", "note": "Special Economic Zone"},
{"term": "Tax Holiday", "translation": "税收假期", "note": "对先驱产业的企业所得税减免"},
// ... 还有66条
]
这个术语表里有机构名称、法律法规、税收政策术语,还有印尼特有的一些制度名词。有了它,Master-Translator 在翻译时就能保证全文术语一致。
这也是为朋友做事的态度吧——要么不做,要做就认真做。
使用 Master-Translator 翻译
mcp_master-transl_translate_document(
document_path="/path/to/output/full.md",
target_language="chinese",
model="deepseek-official"
)
翻译统计:
| 指标 | 数值 |
|---|---|
| 翻译模式 | 并行 (5 并发) |
| 分块数 | 16 块 |
| 失败数 | 0 |
| 输入字符 | 172,033 |
| 输出字符 | 66,432 |
| 耗时 | 248 秒 (~4分钟) |
| 估算成本 | $0.25 |
使用 DeepSeek V3 官方 API,4分钟完成17万字符的翻译,成本不到2元人民币。
Part 4: 翻译质量验证
翻译完成后,我对中英文版本进行了详细对比:
结构完整性检查
# 图片引用数量
grep -c '!\[' full.md full_chinese.md
# full.md: 90
# full_chinese.md: 90 ✅
# 表格数量
grep -c '<table>' full.md full_chinese.md
# full.md: 26
# full_chinese.md: 26 ✅
发现并修复的问题
在 Pandoc 转换 Word 时,发现一个警告:
[WARNING] Could not fetch resource images/a935da19...0836c026f68.jpg
排查后发现:翻译过程中,图片路径中的一个字符被错误修改。
原文: ...281d083f6c026f68.jpg (f)
译文: ...281d0836c026f68.jpg (6) ← 错误!
这是一个罕见的 edge case——长 hash 字符串在 LLM 处理时偶尔会出现字符替换。用 sed 快速修复:
sed -i '' 's/281d0836c026f68/281d083f6c026f68/g' full_chinese.md
翻译质量评估
| 维度 | 评分 | 说明 |
|---|---|---|
| 完整性 | ⭐⭐⭐⭐⭐ | 所有内容均已翻译,无遗漏章节 |
| 准确性 | ⭐⭐⭐⭐⭐ | 专业术语翻译准确一致 |
| 格式保留 | ⭐⭐⭐⭐⭐ | 表格、图片、公式完整保留 |
| 流畅度 | ⭐⭐⭐⭐☆ | 语句通顺,偶有直译痕迹 |
示例对比:
原文:
The Job Creation Law, a comprehensive law that governs and amends many provisions in various sectors, was signed by President Joko Widodo on 2 November 2020.
译文:
《创造就业法》是一部综合性法律,旨在进行结构性改革并加速经济转型,于2020年11月2日由佐科·维多多总统签署,该法管辖并修订了多个领域的许多规定。
术语一致性示例:
Ministry of Investment/BKPM→投资部/印度尼西亚投资协调委员会(BKPM)✅OSS RBA→在线单一提交系统(OSS RBA)✅Tax Holiday→税收假期✅
Part 5: Word 导出的两跳转换
翻译完成后,需要导出为 Word 文档。这里有个技巧:
直接转换的问题
# 直接 MD → DOCX:表格格式丢失
pandoc full_chinese.md -o full_chinese.docx
Pandoc 直接转换时,HTML 表格(尤其是带 colspan/rowspan 的)会变成纯文本。
两跳转换方案
# 步骤1: Markdown → HTML(嵌入所有资源)
pandoc full_chinese.md -o full_chinese.html \
--embed-resources --standalone --mathjax
# 步骤2: HTML → Word
pandoc full_chinese.html -o full_chinese.docx
这个方案的原理:
- Pandoc 的 HTML 输出器完美保留 HTML 表格
- Pandoc 的 HTML→DOCX 转换器能正确解析已渲染的 HTML
最终生成了 9.3MB 的完整 Word 文档:
- ✅ 119 张图片完整嵌入
- ✅ 26 个表格正确渲染(包括合并单元格)
- ✅ 数学公式通过 MathJax 完美呈现
技术复盘
既然博文都写到这里了,不如把整个工具链和踩过的坑也记录一下,方便日后参考。
工具链总结
PDF 文档
↓ (MinerU VLM API)
Markdown + Images
↓ (术语表构建)
terminology.json
↓ (Master-Translator + DeepSeek)
中文 Markdown
↓ (Pandoc 两跳转换)
Word 文档
踩坑清单
| 问题 | 解决方案 |
|---|---|
| API 端点 404 | 查看官方 SDK 源码找到 v4 端点 |
| OSS 上传 SSL 错误 | 设置 trust_env=False 绕过代理 |
| OSS 上传 403 错误 | 不要手动设置 Content-Type |
| 图片路径字符被改 | 用 sed 修复,并对比检查 |
| 表格格式丢失 | 使用 MD→HTML→DOCX 两跳转换 |
| LaTeX 公式显示异常 | 清理 OCR 产生的无效公式标记 |
时间线
| 时间 | 工作内容 |
|---|---|
| 下午 2:00 | 开始研究 MinerU API |
| 下午 3:00 | 调通 API 端点,解决代理问题 |
| 下午 4:00 | 完成逐页诊断脚本 |
| 下午 5:00 | 全文解析完成,开始构建术语表 |
| 下午 6:00 | 翻译完成,开始质量检查 |
| 晚上 7:00 | 修复图片路径问题,完成 Word 导出 |
| 晚上 8:00 | 项目完成 🎉 |
彩蛋:OCR 的"幻觉"
最后说个好玩的事。
在质量检查时,我发现 Word 文档中有些地方显示着奇怪的 \( xxx \) 符号。追查发现,MinerU 的 VLM 模型在解析 PDF 封面时产生了"OCR 幻觉":
# 原文档第二部分封面被识别成了这些乱码:
NO SMOKING
PVEHICLEX1
NO6CARDK
(2) $\mathrm{{NaOH}}$ 扩散的体积为 ← 这是什么鬼?
H21HxTg
是的,一份印尼投资指南的封面,被 OCR 成了化学方程式 NaOH。
我把这个截图发给挚友,她说可以当成"AI 也会胡说八道"的案例存档。
不过这也提醒我们:即使是最先进的 VLM 模型,在处理设计感强的封面页时,也可能产生完全离谱的输出。好在这些乱码只出现在封面区域,正文内容是没问题的。
结语:新年的正确打开方式
晚上8点,我把最终的 Word 文档和术语表打包发给了挚友,让她转交给律所那边。
发完消息,对方还没回复——大概还在享受新年假期吧。
不过这不重要。重要的是,这次测试让我对 Master-Translator 的实战能力更有信心了:97页官方文档,从 PDF 解析到中文 Word 导出,6小时搞定,成本不到2块钱。当然,这6小时里有一半时间是在调 API、抓 Bug。但正是这些折腾,让整个过程变得有趣。
2026年的第一天,就这样在 API Debug 和翻译校对中度过。没有跨年晚会,没有朋友聚餐,只有屏幕上跳动的代码和一份渐渐成型的中文译稿。
窗外天色已暗,桌上的咖啡早就凉透了。
但心里是热的——因为这个项目,正在从"个人工具"慢慢走向"可能真的有用"。
新年第一天,用来折腾有意义的事情——这大概就是我的仪式感吧。 🚀
本文使用的工具:
- MinerU - 高质量 PDF 解析 API
- Master-Translator-MCP-Server - 长文档翻译 MCP 工具
- DeepSeek - 大语言模型 API
- Pandoc - 文档格式转换
如果你对 AI 翻译或 MCP 开发感兴趣,欢迎在评论区交流!
