3. 文献获取(及全文下载)¶
一旦确定目标文献,或因检索阶段获取的元数据不足以支撑进一步筛选、需批量下载全文时,即可启动文献下载流程。
以 PubMed 数据库为例:针对 PubMed 收录文献,优先下载 PMC 开放获取全文(若存在);若无 PMC 全文资源,则仅抓取 PubMed 平台的元数据(以摘要为主)及基础文献信息。此外,我们还提供了一个文献 pdf 文件抓取模块(paper-fetch)作为文献获取兜底策略。只有上述手段获取 PubMed文献数据都失败了,我们才建议你通过人工手段去搜索并获取文献pdf 文本数据。
pubmed 数据库输出文件支持 JSON 格式与 Markdown 格式两种,推荐采用JSON格式后续分析,markdown 格式为大语言模型(LLM)的输入数据,我们的工具会同时生成两类文件供选择。
pubmed-content 模块可帮助你下载 PMC 开放获取全文(若存在),并将其保存到指定存储目录。
❯ paperflow pubmed-content --help
Usage: paperflow pubmed-content [OPTIONS]
Download full text (PMC) for given PMIDs if the paper has a PMC ID.
Notes:
- 1, This currently only supports PMC full text fetching if the paper has a PMC ID.
Example usage:
- 1. Download full text for PMIDs listed in a file:
paperflow pubmed-content --file ./pmid_list.txt --email "YOUR_EMAIL@example" --api-key "YOUR_NCBI_API_KEY" --output-dir ./MyPapers
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --file -f TEXT File containing PMIDs (one per line). │
│ * --email TEXT Entrez Email. [required] │
│ --api-key TEXT NCBI API Key (recommended). │
│ --storage-dir -s TEXT Directory in Repository-level to store paper data for Initialization. [default: ./Papers] │
│ --max-retries INTEGER Maximum number of retries for Entrez API calls. [default: 3] │
│ --output-dir -o TEXT Directory in result-level to store output full texts, default is current directory. If not specified, will be set to root │
│ directory of the repository-level which is storage_dir. 🌟 We will create a '/pubmed' subfolder under the output directory │
│ to save all pubmed related data │
│ [default: .] │
│ --pmid -p TEXT Single PMID to download full text for, can be repeated. │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
此外,可采用元数据获取 + 全文下载的分步执行模式,建议两类操作分开处理。
pubmed-all 模块可帮助你同时获取 PubMed 文献元数据和 PMC 开放获取全文(若存在),并将其保存到指定存储目录。
❯ paperflow pubmed-all --help
Usage: paperflow pubmed-all [OPTIONS]
Fetch BOTH metadata and full text (if available) for papers. Also extracts URLs from full text and updates metadata links.
Example usage:
- 1. Fetch full papers for a query:
paperflow pubmed-all --query "machine learning" --output-dir ./MyPapers --email "YOUR_EMAIL"
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --query -q TEXT PubMed search query. │
│ --file -f TEXT Text file containing PMIDs (one per line), -q and -f are mutually exclusive. │
│ --pmid -p TEXT Single PMID to download full text for, can be repeated. │
│ --batch-size -b INTEGER Batch size for fetching. [default: 50] │
│ --max-retries INTEGER Maximum number of retries for Entrez API calls. [default: 3] │
│ * --email TEXT Entrez Email. [required] │
│ --api-key TEXT NCBI API Key (recommended). │
│ --storage-dir -s TEXT Directory in Repository-level to store paper data for Initialization. [default: ./Papers] │
│ --output-dir -o TEXT Directory in result-level to store output papers. If not specified, defaults to storage-dir. │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
对于无 PMC 全文的 PubMed 文献,或其他数据库来源的文献,若仅持有 DOI(pubmed‑meta 模块可确保获取 DOI 信息),可直接通过 DOI 下载开放获取全文。
paper-fetch 模块可帮助你通过 DOI 下载开放获取的 PDF 文件。
❯ paperflow paper-fetch --help
usage: paper-fetch [-h] [--title TITLE] [--batch FILE] [--out DIR] [--dry-run] [--format {json,text}] [--pretty] [--stream] [--overwrite]
[--idempotency-key KEY] [--timeout SECONDS] [--version]
[doi]
Fetch legal open-access PDFs by DOI via Unpaywall, Semantic Scholar, arXiv, PMC, and bioRxiv/medRxiv.
positional arguments:
doi DOI to fetch (e.g. 10.1038/s41586-020-2649-2). Use '-' to read from stdin.
options:
-h, --help show this help message and exit
--title TITLE paper title; resolved to a DOI via Crossref before download. Mutually exclusive with positional DOI / --batch.
--batch FILE file with one DOI per line for bulk download. Use '-' to read from stdin.
--out DIR output directory (default: pdfs)
--dry-run resolve sources without downloading; preview the PDF URL and filename
--format {json,text} output format. json for agents, text for humans. Default: json when stdout is not a TTY, text otherwise.
--pretty pretty-print JSON output (2-space indent)
--stream emit one NDJSON result per line on stdout as each DOI resolves (batch mode)
--overwrite re-download even if the destination file already exists
--idempotency-key KEY
safe-retry key; re-running with the same key replays the original envelope from <out>/.paper-fetch-idem/
--timeout SECONDS HTTP timeout in seconds per request (default: 30)
--version show program's version number and exit
exit codes:
0 all DOIs resolved successfully
1 unresolved (some DOIs had no OA copy; no transport failure)
3 validation error (bad arguments)
4 transport error (network / download / IO failure; retryable class)
subcommands:
schema print the machine-readable CLI schema and exit (no network)
stdin:
paper-fetch - read a single DOI from stdin
paper-fetch --batch - read DOIs line-by-line from stdin
output:
stdout emits one JSON object per invocation (NDJSON with --stream).
stderr emits NDJSON progress events when --format json, prose when --format text.
stdout format auto-detects TTY: json when piped/captured, text in a terminal.
examples:
paper-fetch 10.1038/s41586-020-2649-2
paper-fetch 10.1038/s41586-020-2649-2 --dry-run
paper-fetch --batch dois.txt --out ./papers --format text
echo 10.1038/s41586-020-2649-2 | paper-fetch --batch -
paper-fetch schema
感谢paper-fetch的工作!我们魔改并封装了其中的一个脚本,并且进一步增加了其他的回退来源。
🔙 paper-fetch 模块的回滚边界:commit
bc8394c(update paper-fetch module according to upstream repo)是原始上游脚本;commit89eda06bac1f853254b04aee9e8916109c7771a1是对它的第一次本地修改。以后需要回滚到原始模块时,以89eda06为边界即可——例如git show 89eda06^:src/pyPaperFlow/integrations/pdf_fetch.py(内容与bc8394c一致)。
目前我们的文献获取模块处理逻辑如下:
┌─────────────────────────────────────────┐
│ 输入:DOI / 标题 / 批量文件 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 标题模式?→ Crossref → Semantic Scholar │
│ (解析为 DOI,带置信度评分) │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 1. Unpaywall(需 UNPAYWALL_EMAIL) │
│ → 最快 OA 链接,含元数据 │
└─────────────────────────────────────────┘
失败/跳过 ↓
┌─────────────────────────────────────────┐
│ 2. Semantic Scholar │
│ → PDF URL + 外部ID(arXiv/PMCID) │
└─────────────────────────────────────────┘
失败 ↓
┌─────────────────────────────────────────┐
│ 3. arXiv(通过 S2 的 externalIds.ArXiv) │
│ 4. Europe PMC → PMC(通过 PMCID) │
│ 无 PMCID 时:DOI→PMCID 恢复 │
│ (Europe PMC hasPDF=Y / OpenAIRE) │
│ 5. bioRxiv/medRxiv(DOI 前缀 10.1101/) │
└─────────────────────────────────────────┘
全部失败 ↓
┌─────────────────────────────────────────┐
│ 6. 出版商直链(仅 institutional 模式) │
│ Nature/Science/Elsevier/Springer等 │
│ 需机构IP/订阅/EZproxy授权 │
└─────────────────────────────────────────┘
仍失败 ↓
┌─────────────────────────────────────────┐
│ 7. CORE 仓库聚合(可选,需 CORE_API_KEY) │
│ → core.ac.uk 聚合 OA 全文 downloadUrl │
└─────────────────────────────────────────┘
仍失败 ↓
┌─────────────────────────────────────────┐
│ 8. Sci-Hub 镜像回退(默认启用,可禁用) │
│ → 1 req/s 限速,防 CAPTCHA │
│ → 自动发现新镜像 │
└─────────────────────────────────────────┘
解析顺序
Unpaywall — 全出版社 OA 最佳位置(命中率最高)
Semantic Scholar — openAccessPdf 字段 + externalIds
arXiv — 论文有 arXiv ID 时
PubMed Central OA 子集 — 论文有 PMCID 时;无 PMCID 时先做 DOI→PMCID 恢复(Europe PMC 搜索 hasPDF=Y / OpenAIRE originalId)
bioRxiv / medRxiv — DOI 前缀为 10.1101/
出版商直链 — 仅机构模式(PAPER_FETCH_INSTITUTIONAL=1)下启用,由调用方的订阅 IP / Cookies / EZproxy 授权
CORE 仓库聚合 — 可选,需 CORE_API_KEY;聚合多仓库 OA 全文,仅当其他 OA 来源均未命中时尝试(免费层约 5 req/10s)
Sci-Hub 镜像 — 兜底来源,默认开启。优先按 PAPER_FETCH_SCIHUB_MIRRORS 设定的镜像顺序尝试(默认列表:sci-hub.ru、sci-hub.st、sci-hub.su、sci-hub.box、sci-hub.red、sci-hub.al、sci-hub.mk、sci-hub.ee);全部失败时会从 https://www.sci-hub.pub/ 抓取最新镜像列表再试一次。设置 PAPER_FETCH_NO_SCIHUB=1 可关闭。
都失败 → 输出元数据提示走馆际互借
⚠️ 在使用
paper-fetch模块前,建议先设置 unpaywall联系邮箱以下参考 https://github.com/Agents365-ai/paper-fetch/blob/main/README_CN.md
被 Cloudflare 拦截的 PDF(可选)
部分出版商(如 science.org)位于 Cloudflare 之后,普通 HTTP 客户端会收到 403/429 或 "Just a moment…" JS 挑战页而非 PDF。设置 PAPER_FETCH_CLOAK=1 可将这些链接改用 CloakBrowser(可通过挑战的隐身 Chromium)重试。该回退位于下载层(覆盖所有来源),CloakBrowser 不可用时静默回退,仅由操作者控制(Agent 无法自行启用),返回字节仍经过相同的 %PDF + 50 MB 校验;成功的 cloak 下载结果带 via:"cloak" 标记。
配置——装一次,然后把 PAPER_FETCH_CLOAK 当作常开安全网:
# 一次性安装:把 cloakbrowser 装进运行 paperflow 的同一 Python(自动识别),
# 或装进独立 venv 并用 CLOAKBROWSER_PYTHON 指向它。
pip install cloakbrowser
# 推荐:常开安全网(仅在下载被拦时触发,正常 OA 下载不受影响)。
export PAPER_FETCH_CLOAK=1
# 更干净的按需单次写法(偶尔遇到被拦 URL 时):
PAPER_FETCH_CLOAK=1 paperflow paper-fetch 10.1126/sciadv.aee6105 --out ./pdfs
# ⚠️ PAPER_FETCH_CLOAK_HEADED=1 不是默认项——仅在强挑战(如 science.org)
# 且机器有显示环境时才设:
# export PAPER_FETCH_CLOAK_HEADED=1
实践要点(实测经验)
- Cloak 不是付费墙绕过工具:只在"OA 论文下载被 Cloudflare 拦截"时触发。付费墙论文(无 OA 副本,如
10.1016/j.cels.2025.101486)根本到不了下载层,Cloak 永远不会被调用。science.org属于"强挑战",headless 过不去(会卡在 "Just a moment…")——必须PAPER_FETCH_CLOAK_HEADED=1+ 真实显示环境(桌面;无桌面服务器可用xvfb-run包一层)。- Cloak 只有在来源返回了直接
url_for_pdf时才有 URL 可重试。仅有 PMC 副本(Unpaywall 只给落地页、无url_for_pdf)的论文,上游原版脚本不会去尝试。PAPER_FETCH_CLOAK=1常开对正常下载无影响,但装了 cloakbrowser 后,每个被拦 URL 会先花 ~30–90s 做浏览器尝试才放弃;不想等就改用按需内联写法。- Sci-Hub 发现阶段会访问
www.sci-hub.pub——网络若屏蔽该域名 DNS,会看到scihub_discover_failed,最后一个兜底随之失效。确实拿不到的论文,请用机构模式(PAPER_FETCH_INSTITUTIONAL=1)或浏览器手动下载 / 文献传递。
机构访问(可选)
有些付费墙论文恰好是你所在机构的订阅范围——只是普通 OA 来源拿不到。设置 PAPER_FETCH_INSTITUTIONAL=1 会启用第 6 步的「出版商直链」来源:脚本按 DOI 为对应出版商构造直链 PDF 并下载。
关键前提(实测验证): 授权靠的是调用方所处的网络,不是脚本本身。只有机器位于校园网或机构 VPN 内,出版商直链才能成功——出版商识别的是你机构的 IP 段(或 Cookies / EZproxy)。若从机构外 IP(数据中心或家用网络)运行,URL 仍会正确构造,但出版商会回
HTTP 403 Forbidden,最终报download_network_error(可重试)而不是not_found——凭这个错误类型变化就能判断机构模式确实生效了。
- 结果信封的
auth_mode字段会显示"institutional"(vs"public")。- 直链模板按 DOI 前缀匹配;Elsevier(
10.1016/)还需经 Crossref 查询 PII 并落到sciencedirect.com/.../pdfft——实测可用。支持的出版商:Nature、Science、Wiley、Springer、ACS、PNAS、NEJM、SAGE、Taylor & Francis、Elsevier、MDPI。- 自动 1 req/s 限速以遵守出版商 ToS(保护你机构 IP 不被出版商限流)。
- 公开模式下,论文疑似付费墙时错误负载会带
suggest_institutional: true,提示设置该变量并在校园网 / VPN 内重跑。
CORE 仓库聚合回退(可选)
当论文在 Unpaywall / Semantic Scholar / arXiv / PMC / bioRxiv 等 OA 来源均未命中、而机构库或学科库可能存有全文时,可设置 CORE_API_KEY 启用 CORE(core.ac.uk)聚合回退。CORE 聚合全球数千个 OA 仓库与期刊的全文元数据;其 v3 搜索 API 按 DOI 查询,命中记录的 downloadUrl 字段即为可直接下载的 OA 全文直链(付费墙记录该字段为空,会被自动跳过)。
原理与要点
- CORE 是「仓库聚合器」而非单一出版商:它从机构库、学科库等海量 OA 来源汇总全文,能补上其他来源覆盖不到的仓库副本。
- 该来源仅在前面的 OA 来源(Unpaywall / Semantic Scholar / arXiv / PMC / bioRxiv)都未命中时才触发——不会干扰正常 OA 下载路径,因此常开无副作用。
- 需要免费 API key(Bearer 认证);不设
CORE_API_KEY时该来源静默跳过。- 免费层限速约 5 请求 / 10 秒,超出会返回
403——单篇无感,批量抓取时已串行限速。- 返回直链同样经过
source:"core"标记。- 仅采纳
downloadUrl非空的记录,天然过滤掉无 OA 副本的付费墙条目。
推荐配置(最佳实践)
面对混合任务——OA 论文、被 Cloudflare 拦截的 OA 论文、以及偶尔一两篇机构有订阅的付费墙论文——常开三个开关即可:
export UNPAYWALL_EMAIL=you@example.com # 最快、覆盖面最广的 OA 来源
export PAPER_FETCH_CLOAK=1 # 被 Cloudflare 拦截的 OA PDF 安全网(其余场景无副作用)
# 下面这一行只在校园网 / 机构 VPN 内执行:
export PAPER_FETCH_INSTITUTIONAL=1 # 付费墙论文的出版商直链
单篇论文的决策逻辑:
- OA 论文 → Unpaywall / Semantic Scholar / arXiv / PMC 即可;
PAPER_FETCH_CLOAK只在下载被 Cloudflare 拦截时多一次重试。 - 被 Cloudflare 拦截的 OA(如
science.org)→ Cloak 重试(headless 可能卡住,需在有显示环境的机器上设PAPER_FETCH_CLOAK_HEADED=1)。 - 付费墙论文(如
10.1016/j.cels.2025.101486)→ 只有机构链路能取到,且必须在校内 / VPN:Unpaywall → Semantic Scholar → 出版商直链(Elsevier 经 PII 查询落到sciencedirect.com/.../pdfft)→ Sci-Hub 兜底。从机构外 IP 出版商会回403,没有任何自动化路径可走——请用图书馆门户 / EZproxy 或馆际互借。
注意事项与环境变量
所有设置均通过环境变量在进程启动时读取——无配置文件。下列变量可自由组合。
| 环境变量 | 作用 | 默认 | 何时设置 |
|---|---|---|---|
UNPAYWALL_EMAIL |
Unpaywall API 联系邮箱(写入 User-Agent);不设则跳过 Unpaywall 来源 | 空 | 建议设置——Unpaywall 是最快、覆盖面最广的来源 |
CORE_API_KEY |
CORE (core.ac.uk) 聚合器 API key;不设则跳过 core 仓库聚合来源 | 空 | 需要覆盖机构库 / 学科库等 OA 仓库副本时 |
PAPER_FETCH_NO_SCIHUB |
设为 1 关闭 Sci-Hub 镜像兜底 |
Sci-Hub 开 | 机构 / 合规不允许 Sci-Hub 时 |
PAPER_FETCH_SCIHUB_MIRRORS |
逗号分隔的镜像列表,按优先级尝试(仅主机名) | 内置默认列表 | 默认镜像失效时 |
PAPER_FETCH_INSTITUTIONAL |
设为 1 启用出版商直链(由机构 IP / Cookies / EZproxy 授权),自动 1 req/s 限速以遵守出版商 ToS |
关 | 有机构订阅时 |
PAPER_FETCH_CLOAK |
设为 1 对被 Cloudflare 拦截的 PDF 改用 CloakBrowser 重试 |
关 | 出版商在 Cloudflare 之后(如 science.org) |
CLOAKBROWSER_PYTHON |
可 import cloakbrowser 的 Python 解释器 |
自动探测 | 仅未自动识别时 |
PAPER_FETCH_CLOAK_HEADED |
设为 1 用有头浏览器(需显示环境) |
headless | 强挑战 headless 过不了时(如 science.org) |
⚠️ 布尔变量是「存在即真」,不认值。 代码用
os.environ.get(...)判断,任何非空值都会启用该特性。设PAPER_FETCH_CLOAK=0或=false依然会启用 Cloak;设PAPER_FETCH_NO_SCIHUB=0依然会禁用 Sci-Hub。要关闭请用unset,切勿写=0/=false。
已知限制
- 部分出版商重定向会落到 HTML 落地页而非 PDF——
%PDF魔数校验会拒绝。 - 默认不做浏览器自动化(不解 CAPTCHA)——仅可选的
PAPER_FETCH_CLOAKCloakBrowser 兜底。 - SSRF 防护拒绝私网 IP、非
http(s)协议、非 80/443 端口、云元数据主机。 - 单个 PDF 上限 50 MB。
与 PMC 全文解析逻辑不同,非 PubMed 来源文献可通过 paper‑fetch 模块获取 PDF 格式原文(预印本则可通过相应*-fetch模块实现pdf下载)。
建议统一将所有文献信息标准化为 Markdown 格式或 JSON 格式。
鉴于后续需开展语段分割与信息提取,从编程调用便捷性角度,优先选用 JSON 格式作为中间转换载体。
我们这里的实现是,工具内置 pdf‑parser 模块,依托 MinerU 解析引擎将 PDF 文件解析为基础 Markdown 文件与结构化 JSON 文件。
具体规范参考 MinerU 官方文档(https://github.com/opendatalab/mineru)。考虑到普通用户通常无 GPU 算力用于加速解析,本工具默认启用基础解析模式(即 pipeline 后端)。
❯ paperflow pdf-parse --help
Usage: paperflow pdf-parse [OPTIONS]
Parse a PDF file using MinerU engine, and clean up the output directory.
Notes:
- 1, MinerU generates a subfolder /auto under --output with .md, .json, .pdf, and images/. Use --clear to strip anything unnecessary,
note that we only use .md files and _content_list_v2.json/_content_list.json files for further processing like structuring.
- 2, ⚠️ Remember to switch to domestic mirror source when you can not access huggingface.
Example usage:
paperflow pdf-parse -i paper.pdf -o ./output
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --input -i TEXT Input PDF file path. [required] │
│ * --output -o TEXT Output directory for parsed output. [required] │
│ --clear After conversion, keep only the .md files and necessary .json files(_content_list_v2.json/_content_list.json). │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
🌟 关于pdf文献获取模块,我们也提供了一系列第三方skill/MCP工具参考,你可以将其整合到 skill 中或独立实现: paper pdf fetch