从arXiv到中文交互网页:DeMinds论文阅读工具链实战

从arXiv到中文交互网页:DeMinds论文阅读工具链实战 每天都有大量论文发布在 arXiv 上但真正把一篇论文从“看到标题”推进到“读懂方法、留下笔记、分享给团队”往往要花掉一整个下午。PDF 排版参差不齐复制出来段落错乱术语翻译不统一前后文对不上就算翻译好了想在手机上快速翻阅也很痛苦。这篇文章围绕 DeMinds 项目实践整理一套从 arXiv 获取论文到中文交互网页的完整流程覆盖结构优化、翻译处理、网页生成与发布部署。文中的方案都可以直接复制到本地项目里既适合想提升论文阅读效率的研究生也适合需要做文档处理工具链的开发者。1. 背景与核心概念1.1 论文阅读的常见痛点arXiv 是计算机、物理、数学等领域最重要的预印本平台绝大多数最新研究成果都会在第一时间上传到 arXiv。但 arXiv 本身只提供 PDF 文件阅读体验和“能用工具二次处理”完全是两回事。实际开发中我遇到最典型的三个问题第一PDF 文本提取质量不稳定。arXiv 上的论文大多由 LaTeX 生成页面结构相对规整但仍然存在双栏排版、公式断裂、图表穿插、引用编号混乱的问题。用普通 PDF 阅读器复制文本经常出现段落顺序颠倒、中英文混排后样式丢失等现象。第二翻译成本与术语一致性。计算机领域的论文专业词很多“attention mechanism”“knowledge distillation”“end-to-end”这类表达在上下文里应该保持统一翻译。如果只靠在线翻译工具逐段粘贴先不说效率术语一致性就很难保证。第三阅读载体单一。PDF 在手机上的阅读体验并不好尤其是面对双栏排版的小字号论文。很多研究者希望把论文转成结构清晰的中文网页方便随时翻阅也方便把链接分享给同事。1.2 DeMinds 的设计思路DeMinds 是一套围绕“论文结构化与多语言阅读”设计的开源工具链思路。它的核心不是做翻译而是把论文当成“数据”来处理通过一条清晰的处理流水线把零散的 PDF 转化为结构化、可检索、可展示的内容。这条流水线可以拆成四个阶段获取通过 arXiv 官方 API 或手工下载拿到论文 PDF 与元数据。结构优化将 PDF 的版面信息解析成标题、摘要、章节、段落、参考文献等结构化字段清理多余换行与页眉页脚。翻译对结构化文本做术语对齐与批量翻译生成中英双语语料。发布将翻译结果渲染成 HTML 静态网页部署到服务器或静态托管平台。与“一键翻译 PDF”类工具相比DeMinds 更强调结构优化。因为只有结构被正确识别翻译之后生成的网页才能保留原文的条理性而不是变成一大段连续文本。1.3 这套流程的价值从工程角度看这套流程的价值体现在三个方面可复用一旦完成工具链搭建后续新增论文只需要执行一条命令或一个脚本就能生成对应的中文网页。可定制术语表、样式模板、翻译引擎都可以按需替换不绑定任何单一厂商。可扩展生成的结构化 JSON 不仅能用于网页展示还能继续接入知识库、问答系统、笔记软件等其他场景。如果你正在做论文阅读工具、知识管理平台或者只是希望提升个人文献阅读效率这篇文章的思路都可以直接借鉴。2. 环境准备与工具选型2.1 运行环境本文的示例以 Linux 或 macOS 环境为主Windows 下命令略有差异但原理相同。建议提前安装好以下基础环境工具用途说明Python 3.10主流程脚本本文示例基于 Python 3版本差异不大较高版本即可Git版本管理可选用于管理项目代码Node.js前端构建如果只是生成静态 HTML不是必须如果使用 Vite 等构建工具则需要Nginx服务器部署可选也可以使用 GitHub Pages 或对象存储托管版本号不必完全一致。实际项目里Python 3.8 以上运行本文代码基本没有障碍个别库如果接口有变化以官方文档为准。2.2 安装 Python 依赖建议先创建虚拟环境再安装依赖。下面的命令在项目根目录执行mkdir deminds cd deminds python3 -m venv .venv source .venv/bin/activate然后安装核心依赖pip install arxiv pymupdf pdfplumber requests jinja2这里简单说明每个库的作用arxivarXiv 官方 API 的 Python 封装用于搜索论文、获取元数据、下载 PDF。pymupdf基于 MuPDF 的 PDF 解析库速度很快适合提取文本和版面信息。pdfplumber另一个 PDF 解析库对表格和文本坐标控制更灵活可以作为 pymupdf 的补充。requests发送 HTTP 请求主要用于调用翻译 API。jinja2Python 模板引擎用于生成最终的中文交互网页。如果你不想使用虚拟环境也可以全局安装但在项目开发中依然建议保持依赖隔离。2.3 工具链功能对照处理阶段推荐工具备选方案注意事项论文获取arxiv 库arXiv API 直接请求注意 API 调用频率不要高频请求PDF 解析PyMuPDFpdfplumber、Grobid双栏论文需要后处理结构优化规则解析 正则LLM 辅助识别规则解析快且稳定适合大多数论文翻译DeepL API / 百度翻译本地开源模型需要申请 API Key注意调用限额网页生成Jinja2MkDocs、Hugo静态页面部署成本最低3. 核心机制拆解结构优化、翻译与网页生成3.1 从 PDF 到结构化 JSONPDF 本身是一堆图形对象的集合没有“段落”“标题”“章节”这些语义概念。结构优化要解决的就是把这些排版层面信息还原成语义层面结构。先来看一个最基础的文本提取示例# 文件路径scripts/parse_pdf.py import fitz # PyMuPDF def extract_text_from_pdf(pdf_path: str) - str: doc fitz.open(pdf_path) full_text [] for page_num, page in enumerate(doc): page_text page.get_text(text) full_text.append(f!-- PAGE {page_num 1} --) full_text.append(page_text) doc.close() return \n.join(full_text) if __name__ __main__: text extract_text_from_pdf(paper.pdf) print(text[:2000])运行这个脚本会输出论文前几页的文本。但你很快会发现两个问题第一双栏论文的文本会按照 PDF 内部对象顺序输出可能会先输出左栏下半部分再输出右栏上半部分段落顺序混乱。第二页眉页脚和参考文献编号混在正文里需要额外规则过滤。解决双栏问题可以先判断页面是否分栏。简单的方式是根据文本块的 x 坐标中位数来做聚类如果页面文本块的 x 坐标集中在左右两个区域就按两栏提取否则按单栏处理。下面是一个示例函数# 文件路径scripts/parse_pdf.py def get_columns(page) - list: 将一页文本按左右栏拆分返回重新排序后的文本块列表。 words page.get_text(words) if not words: return [] x_coords [(w[0] w[2]) / 2 for w in words] median_x sorted(x_coords)[len(x_coords) // 2] left_blocks [] right_blocks [] for w in words: block_text w[4] if (w[0] w[2]) / 2 median_x: left_blocks.append(block_text) else: right_blocks.append(block_text) return left_blocks right_blocks这个方案对大多数 arXiv 论文有效。但需要注意包含跨栏图片、表格或公式较长的页面仅靠坐标切割无法完美解决。实际项目中可以结合 PDF 原始布局块page.get_text(dict)做更精细的区块识别这里不过度展开。3.2 识别章节与摘要拿到纯文本后下一步是识别标题、摘要、章节。arXiv 论文的排版相对统一常见的章节标题无非是Introduction、Related Work、Method、Experiments、Conclusion、References这些用正则配合关键字就能稳定识别。一个简化版的结构化解析实现如下# 文件路径scripts/parse_pdf.py import re import json SECTION_PATTERNS [ r^\d\s(Introduction|Related Work|Method|Methods|Experiment|Experiments|Conclusion|Discussion)$, r^(Introduction|Related Work|Method|Methods|Experiment|Experiments|Conclusion|Discussion)$, r^\d\.\d\s[A-Z].*, ] def parse_sections(text: str) - dict: lines text.split(\n) metadata {title: , abstract: , sections: []} current_section None current_content [] in_abstract False in_references False for line in lines: stripped line.strip() if not stripped: continue if stripped.lower().startswith(abstract): in_abstract True metadata[abstract] continue if in_abstract: if stripped.lower().startswith(introduction) or stripped.lower().startswith(1 introduction): in_abstract False else: metadata[abstract] stripped continue if in_references: continue if re.match(r^references$, stripped, re.IGNORECASE): in_references True continue is_section False for pattern in SECTION_PATTERNS: if re.match(pattern, stripped, re.IGNORECASE): is_section True break if is_section: if current_section is not None: metadata[sections].append({ title: current_section, content: \n.join(current_content).strip() }) current_section stripped current_content [] else: if current_section is not None: current_content.append(stripped) if current_section is not None: metadata[sections].append({ title: current_section, content: \n.join(current_content).strip() }) return metadata这个实现比较朴素但用于 arXiv 上排版规范的论文已经够用。识别结束后把结果保存为 JSON# 文件路径scripts/parse_pdf.py def save_metadata(metadata: dict, output_path: str) - None: with open(output_path, w, encodingutf-8) as f: json.dump(metadata, f, ensure_asciiFalse, indent2)到这一步论文已经从“PDF 文件”变成了“结构化 JSON”后续的翻译和网页生成都基于这份 JSON 进行。3.3 翻译策略与术语一致性翻译不是本文的重点但有一个工程问题必须提前考虑术语一致性。直接调用翻译 API 逐段翻译看似简单实际操作中会遇到同一个术语在不同段落被翻译成不同中文的情况。比如attention上一段翻译成“注意力”下一段可能是“注意力机制”再下一段又变成“关注机制”。解决思路是建立术语表在翻译前对原文做术语替换或用翻译 API 的 glossary术语表能力。以 DeepL API 为例# 文件路径scripts/translate.py import requests DEEPL_API_URL https://api-free.deepl.com/v2/translate GLOSSARY { attention mechanism: 注意力机制, knowledge distillation: 知识蒸馏, end-to-end: 端到端, pre-training: 预训练, fine-tuning: 微调, } def translate_with_glossary(text: str, api_key: str) - str: for en, zh in GLOSSARY.items(): text text.replace(en, f[{zh}]) payload { auth_key: api_key, text: text, target_lang: ZH, } resp requests.post(DEEPL_API_URL, datapayload) resp.raise_for_status() result resp.json()[translations][0][text] # 将占位符替换还原避免术语被二次翻译 for en, zh in GLOSSARY.items(): result result.replace(f[{zh}], zh) return result这个示例有个小技巧先把术语替换成中文并加方括号再交给翻译 API最后把方括号去掉。因为翻译引擎遇到方括号里的中文通常会保留原样不会二次改写。如果你的翻译引擎支持官方 glossary 功能直接配置术语表会更好。如果你希望完全离线翻译可以考虑使用本地部署的开源翻译模型如 CTranslate2 加载 OPUS-MT 系列模型。但离线翻译的启动成本和显存要求更高个人场景下还是推荐优先使用在线 API。3.4 中文交互网页的生成思路结构化 JSON 已经准备好了翻译也完成了接下来就是网页渲染。建议使用 Jinja2 模板生成 HTML。这样既能保持论文结构清晰又能把样式和内容分离。下面是最小可用的模板!-- 文件路径templates/paper_template.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title{{ paper.title_zh }}/title style body { max-width: 860px; margin: 0 auto; padding: 24px; line-height: 1.8; color: #333; } h1 { font-size: 1.8rem; } .abstract { background: #f6f8fa; padding: 16px; border-radius: 8px; margin: 24px 0; } .section { margin-bottom: 24px; } .section h2 { font-size: 1.3rem; border-left: 4px solid #0366d6; padding-left: 12px; } .original { color: #888; font-size: 0.9rem; } media (max-width: 600px) { body { padding: 12px; } } /style /head body h1{{ paper.title_zh }}/h1 p classoriginal{{ paper.title_en }}/p div classabstract h2摘要/h2 p{{ paper.abstract_zh }}/p p classoriginal原文{{ paper.abstract_en }}/p /div {% for section in paper.sections %} div classsection h2{{ section.title_zh }}/h2 p{{ section.content_zh }}/p p classoriginal原文{{ section.title_en }} · {{ section.content_en | truncate(200) }}/p /div {% endfor %} /body /html配合 Jinja2 的渲染代码# 文件路径scripts/build_html.py from jinja2 import Environment, FileSystemLoader import json def build_html(paper_data: dict, output_path: str) - None: env Environment(loaderFileSystemLoader(templates)) template env.get_template(paper_template.html) html_content template.render(paperpaper_data) with open(output_path, w, encodingutf-8) as f: f.write(html_content)这个模板简单但足够实用。通过媒体查询适配手机端原文字号比中文略小中文内容优先展示想看原文时再向下滚动。如果你需要更复杂的交互比如目录跳转、公式渲染、夜间模式可以在后续继续扩展。4. 完整实战从 arXiv 拉取论文到发布网页这一节把前面拆解的模块串联起来形成一个可运行的流程。为了便于演示我们以“检索一篇关于知识蒸馏的论文并生成中文网页”为例。4.1 创建项目目录先建立完整的项目结构deminds/ ├── scripts/ │ ├── fetch_arxiv.py │ ├── parse_pdf.py │ ├── translate.py │ └── build_html.py ├── templates/ │ └── paper_template.html ├── data/ │ ├── pdf/ │ └── json/ ├── dist/ └── requirements.txt执行命令mkdir -p deminds/{scripts,templates,data/pdf,data/json,dist}4.2 编写拉取脚本fetch_arxiv.py负责搜索并下载论文# 文件路径scripts/fetch_arxiv.py import arxiv def fetch_papers(query: str, max_results: int 3, download_dir: str data/pdf): client arxiv.Client() search arxiv.Search( queryquery, max_resultsmax_results, sort_byarxiv.SortCriterion.SubmittedDate, ) papers [] for result in client.results(search): print(f标题: {result.title}) print(f链接: {result.entry_id}) papers.append({ title_en: result.title, abstract_en: result.summary, pdf_url: result.pdf_url, entry_id: result.entry_id, }) result.download_pdf(dirpathdownload_dir) return papers if __name__ __main__: fetch_papers(knowledge distillation, max_results1)arxiv库会自动从官方 API 获取数据并下载 PDF。如果网络环境不稳定也可以在本地浏览器先下载 PDF再手动放入data/pdf目录流程保持一致。4.3 解析 PDF 并生成结构化 JSON解析脚本我们在第 3 节已经写了大部分串联起来cd deminds python scripts/parse_pdf.py data/pdf/xxx.pdf为了更方便在parse_pdf.py底部增加命令行入口# 文件路径scripts/parse_pdf.py if __name__ __main__: import sys pdf_path sys.argv[1] output_dir sys.argv[2] if len(sys.argv) 2 else data/json full_text extract_text_from_pdf(pdf_path) metadata parse_sections(full_text) # 补充论文元信息这里可以手动维护或从 arxiv API 获取 output_path f{output_dir}/{pdf_path.split(/)[-1].replace(.pdf, .json)} save_metadata(metadata, output_path) print(f已生成: {output_path})运行python scripts/parse_pdf.py data/pdf/xxx.pdf预期输出类似{ title: , abstract: 知识蒸馏是一种模型压缩方法..., sections: [ {title: 1 Introduction, content: 深度学习模型在计算机视觉...}, {title: 2 Method, content: 我们提出...} ] }注意标题识别需要对第一页做专门处理。第一页通常包含论文标题、作者列表、摘要、关键词等而正则解析是逐行匹配的。建议对第一页单独提取前几行作为标题候选再结合 arXiv API 返回的 title 字段。实际项目中可以优先使用entry_id关联的元数据。4.4 翻译并生成双语数据这里用一个简化版翻译脚本演示流程# 文件路径scripts/translate.py import json import time def translate_paper(json_path: str, api_key: str, output_path: str None): with open(json_path, r, encodingutf-8) as f: paper json.load(f) paper[title_zh] translate_with_glossary(paper.get(title, ), api_key) paper[abstract_zh] translate_with_glossary(paper.get(abstract, ), api_key) for section in paper.get(sections, []): section[title_zh] translate_with_glossary(section[title], api_key) section[content_zh] translate_with_glossary(section[content][:1500], api_key) time.sleep(0.2) output_path output_path or json_path.replace(.json, _zh.json) with open(output_path, w, encodingutf-8) as f: json.dump(paper, f, ensure_asciiFalse, indent2) print(f翻译完成: {output_path})这里有一个工程细节翻译 API 通常对单次请求长度有限制建议按段落或按最多 1500 字符切分逐段翻译后拼接。time.sleep(0.2)是考虑到免费 API 的限流策略实际项目应根据你的 API 套餐合理调整。4.5 生成中文交互网页使用第 3 节的模板与渲染脚本python scripts/build_html.py data/json/xxx_zh.json dist/xxx.htmlbuild_html.py的入口需要增加命令行支持# 文件路径scripts/build_html.py if __name__ __main__: import sys json_path sys.argv[1] html_path sys.argv[2] if len(sys.argv) 2 else dist/index.html with open(json_path, r, encodingutf-8) as f: paper_data json.load(f) build_html(paper_data, html_path) print(f网页已生成: {html_path})打开dist/xxx.html应该能看到一个带摘要、章节、中英对照的阅读页面。4.6 本地预览在项目根目录启动一个本地静态服务器cd dist python3 -m http.server 8080浏览器访问http://localhost:8080/xxx.html即可预览效果。此时网页是一个纯静态文件不依赖任何后端服务后续部署也非常灵活。5. 发布流程详解5.1 静态文件的发布方式由于 DeMinds 生成的网页是纯静态 HTML发布方式非常灵活如果你只是想快速分享可以直接把dist目录压缩上传到任意对象存储开启静态网站托管。如果你有服务器用 Nginx 服务静态文件是最常见的方案。如果你想长期维护建议接入 Git 仓库配合 GitHub Pages 或 Gitee Pages 自动构建。以 Nginx 为例一个最小配置如下# 文件路径/etc/nginx/conf.d/deminds.conf server { listen 80; server_name your-domain.com; root /var/www/deminds; index index.html; location / { try_files $uri $uri/ 404; } # 静态资源缓存 location ~* \.(html|css|js|png|jpg|gif)$ { expires 1d; add_header Cache-Control public; } }将构建好的文件上传到服务器scp -r dist/* useryour-server:/var/www/deminds/然后重新加载 Nginxsudo nginx -t sudo nginx -s reload注意线上环境建议配置 HTTPS。如果域名没有 HTTPS现代浏览器的部分能力如navigator.clipboard会受限制微信内置浏览器打开时也容易有安全提示。5.2 使用 GitHub Pages 自动发布如果你的项目放在 GitHub 上可以开启 GitHub Pages并配合 GitHub Actions 自动构建。这里不展开完整 CI 配置只给一个思路将scripts和templates提交到仓库。在 GitHub Actions 中安装 Python 依赖运行parse_pdf.py和build_html.py。将dist目录发布到gh-pages分支。在仓库 Settings → Pages 中选择gh-pages分支作为来源。这样每次更新论文或模板后只要触发流水线网页会自动更新。5.3 扩展通过 HBuilderX 打包成微信小程序如果你希望论文网页能在微信小程序里访问HBuilderX 是一个可行的发布路径。整体流程如下在 HBuilderX 中新建一个uni-app项目。将生成的 HTML 文件放入项目的hybrid/html目录或通过web-view组件加载线上网页地址。在manifest.json中配置小程序 AppID并在微信公众平台完成域名验证。点击 HBuilderX 的“发行 → 小程序-微信”生成微信小程序代码。在微信开发者工具中打开生成目录上传代码并提交审核。这里有一个重要限制web-view组件要求业务域名必须在小程序后台配置 HTTPS 并且完成校验。个人开发者如果没有备案域名或没有经过微信验证的域名无法正常使用web-view。如果你的核心需求是让团队内部阅读论文相比打包成小程序直接分享网页链接往往是成本最低的方案。6. 常见问题与排查思路6.1 arXiv 访问与下载问题“arXiv 打不开”是高频问题尤其是手机网络环境下更容易出现。先不要急着换工具按下面的顺序排查问题现象常见原因解决思路浏览器打开很慢或超时本地网络波动或 DNS 解析异常切换 Wi-Fi/移动网络或更换公共 DNS 后重试手机端打不开电脑端正常浏览器缓存或网络环境问题清除浏览器缓存换用其他浏览器 App 访问下载 PDF 一直转圈访问高峰期或连接不稳定错峰下载或改用命令行工具请求官方 API 下载程序调用 API 超时请求频率过高或网络受限控制并发数添加重试机制使用官方export.arxiv.org接口需要说明的是arxivPython 库默认访问的是export.arxiv.org这是一个官方 API 端点。如果你在代码中遇到连接超时可以适当增加超时时间并做重试import time import arxiv def fetch_with_retry(query: str, retries: int 3): for attempt in range(retries): try: client arxiv.Client(delay_seconds3) search arxiv.Search(queryquery, max_results1) return list(client.results(search)) except Exception as e: print(f第 {attempt 1} 次请求失败: {e}) time.sleep(5) return []如果你在手机上下载论文优先通过论文详情页的官方 PDF 按钮下载不要使用第三方转码站后者往往有内容不全或乱码问题。6.2 arXiv 提交论文时的背书问题如果你不只是阅读论文还想向 arXiv 提交论文可能会遇到“endorsement”背书机制。这是 arXiv 为了保证内容质量而设计的环节新用户在首次提交论文到某些学科分类时需要获得该领域已有作者的外部认可。问题现象常见原因解决思路提交时提示需要 endorsement首次投稿且学科分类要求背书查看 arXiv 系统发的邮件确认需要背书的分类不知道找谁背书刚进入领域不认识已有作者联系导师、合作者或实验室同门请他们以 arXiv 用户身份为你确认背书邮件一直没有回应对方未登录 arXiv 或忽略邮件邮件里通常有操作链接跟进说明需要对方在登录状态打开没有作者愿意背书个人独立研究社交关系有限部分分类不要求背书可先调整论文分类再次尝试解决背书问题最核心的一点是不要重复提交或反复申请这反而会让系统认为你的行为异常。认真检查自己论文的学科归属选择合适的分类再按系统提示完成背书。6.3 翻译与结构优化常见问题问题现象常见原因解决思路解析出的正文顺序混乱双栏论文未做分栏处理使用坐标分栏或引入版面分析工具章节标题识别不出论文章节命名不规范扩充正则规则增加关键词列表翻译结果术语不一致没有使用术语表建立论文专属术语表在翻译前替换翻译 API 返回超时文本过长按段落切分控制单次请求字符数生成的 HTML 在手机上字体过小未设置 viewport在 head 中加入 viewport meta 标签7. 最佳实践与工程建议7.1 把解析结果存成规范 JSON无论你最终是否生成网页建议都把结构优化后的结果保存为 JSON。原因在于JSON 是所有工具链的公共接口。翻译脚本读取 JSON网页模板读取 JSON未来如果接入知识库或做语义检索JSON 也是最方便处理的数据格式。JSON 字段建议保持稳定{ id: 2405.12345, title_en: Knowledge Distillation: A Survey, title_zh: 知识蒸馏综述, abstract_en: ..., abstract_zh: ..., sections: [ { title: 1 Introduction, title_zh: 1 引言, content: ..., content_zh: ... } ] }字段稳定之后后续升级模板或更换翻译引擎都不需要改动整条链路。7.2 建立论文级术语表不同的论文子领域术语翻译差异很大。建议在项目目录下维护一个glossary.json而不是把所有术语硬编码在脚本里{ attention mechanism: 注意力机制, knowledge distillation: 知识蒸馏, teacher model: 教师模型, student model: 学生模型 }翻译脚本读取这个文件方便在不同论文之间复用。长期积累下来这套术语表本身就是一笔资产。7.3 控制 API 调用成本与频率翻译 API 按字符计费论文动辄上万词整篇翻译的成本不低。工程上常见的优化手段有缓存如果之前已经翻译过同一篇论文论文不要重新翻译。用论文 ID 作为缓存 key结果直接保存到 JSON。分段翻译不要一次性翻译整段超长文本按章节或按 1500 字符切分。这样即使某一段失败也不影响其他部分。限流与重试免费额度通常有速率限制脚本中加入退避重试机制避免被临时封禁。7.4 关注公式与特殊字符LaTeX 生成的 PDF 在提取时公式往往变成乱码或特殊符号。如果你的论文属于数学、物理领域公式缺失会很影响阅读体验。当前工程化的做法是PDF 提取时对公式区域不做强制解析保留原始片段。翻译时不要翻译公式编号。网页展示时可以使用 KaTeX 或 MathJax 渲染 LaTeX 源码。不过从 PDF 反推 LaTeX 源码的可靠度有限。如果论文源码在 arXiv 上可以下载优先使用源文件做公式提取会更准确。7.5 生产环境的安全与合规如果你要把这套工具链部署到公司或团队内部不要在脚本里硬编码 API Key。使用环境变量或密钥管理服务。下载 arXiv 论文时注意合理使用不要批量抓取后用于商业化再分发。如果部署到公网建议加访问鉴权避免被爬虫消耗流量。定期更新依赖库PDF 解析库和 HTTP 库都需要关注安全补丁。8. 总结与回顾从一个 arXiv 链接到一份中文交互网页完整流程并不复杂核心是把 PDF 结构化这件事做好。结构优化决定了翻译的上下文是否连贯也决定了最终网页的阅读质量。DeMinds 的思路是把这项工作拆成“拉取、解析、翻译、渲染、发布”五个独立阶段每个阶段都能单独替换和优化。如果你现在想动手试试可以从最小闭环开始手动下载一篇论文 PDF跑通parse_pdf.py和build_html.py先不接翻译 API只看结构化结果是否准确。等基础链路稳定后再逐步接入术语表、翻译引擎、自动发布。技术选型不是越复杂越好关键是围绕自己的阅读场景做减法。希望这篇文章能帮你少踩一些 PDF 解析和发布流程上的坑。