ADR-0004:下载逻辑收进包,scripts/download_paper.py 变薄壳¶
Context¶
仓库里「把一篇论文的 PDF 搞到手」有两个入口:
scripts/download_paper.py |
hydrolitagent/literature/download_pdf.py |
|
|---|---|---|
| 行数 | 650 | 484 |
| 形态 | 脚本,逻辑全在文件里,零测试 | 包内模块,有 tests/test_literature_download_pdf.py |
| 路由方式 | 按 DOI 前缀 | 按 URL 主机 |
| 覆盖 | Copernicus · science.org · SD · Wiley+AGU · AMS · Nature · SSRN | Elsevier · Springer · Wiley · T&F · AGU |
| 谁在用 | 全部 3 个 skill(download-pdf / paper-to-zotero / run-paper-to-zotero) |
只有文档 |
先澄清一个误判:这两个不是两份重复实现 —— 路由维度与覆盖面都不同,是互补的。
真正的问题是形态:scripts/ 下另外两个脚本(paper_input.py / paper_validate.py)
都已是「薄壳转发到包内」的形态,就它把 650 行逻辑内联在脚本里,且没有测试。
另有两处小病:verify_pdf 在两个文件里同名不同物
(脚本里返 bool 只查 %PDF-;模块里返 PdfMetadata 且会抛异常);
sd_flow 里手写了 https://www.sciencedirect.com/science/article/pii/{pii},
而模块里已有 pii_to_sciencedirect_url。
Decision¶
把下载逻辑收进包,scripts/download_paper.py 变薄壳。
- 新增
hydrolitagent/literature/download_browser.py(内部模块,无 CLI):浏览器流程 (stealth / MCP 档案、5 个出版商 flow、playwright 惰性导入)。 单独成文件是为了不让download_pdf.py过千行。 hydrolitagent/literature/download_pdf.py成为公开模块:原有工具函数 + 并入 curl 优先、Crossref/Unpaywall、setup_check、sync_to_zotero,以及公开入口download_paper(...) -> int。原有 6 个子命令 CLI 不动。scripts/download_paper.py只解析 CLI → 调包内入口。 参数、help 文本、退出码逐项不变(3 个 skill 与多篇文档依赖它)。verify_pdf(bool 那个)改名is_pdf_file;sd_flow改用pii_to_sciencedirect_url。
明确不做:不合并 literature/ 与 cards/ 的取文献层(无重复代码,且 ADR-0002 仍然有效
——那两套 Zotero 客户端读的是不同库:群组库 vs 个人库)。
Consequences¶
- 下载逻辑可测了:
tests/test_literature_download_pdf.py41 → 59 个用例。 scripts/三个脚本形态一致:都是薄壳。脚本 650 → 68 行。- 同一件事不再有两个名字(
verify_pdf撞名消除;pii_to_sciencedirect_url不再有第二份)。 - 代价:付费墙浏览器流程(SD / Wiley / AMS / Nature / SSRN)本地跑不了 —— 本次只做到「原样搬运 + 可编译 + 静态核对」,其实跑行为未验证。将来改动这些流程时, 仍需真实 Chrome + 机构会话才能验证。
- 想统一的读者注意:
download_pdf.py的 6 个子命令(detect/doi/decode/verify/classify/output-path)仍在原处 —— 那是它的公开 CLI,未迁移。