跳转至

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 bc8394cupdate paper-fetch module according to upstream repo)是原始上游脚本;commit 89eda06bac1f853254b04aee9e8916109c7771a1 是对它的第一次本地修改。以后需要回滚到原始模块时,以 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联系邮箱

export UNPAYWALL_EMAIL=you@example.com

以下参考 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 并下载。

export PAPER_FETCH_INSTITUTIONAL=1   # 只有在机构网络内才有效

关键前提(实测验证): 授权靠的是调用方所处的网络,不是脚本本身。只有机器位于校园网或机构 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 全文直链(付费墙记录该字段为空,会被自动跳过)。

export CORE_API_KEY=your_core_api_key   # 免费申请:https://core.ac.uk/services/api

原理与要点

  • CORE 是「仓库聚合器」而非单一出版商:它从机构库、学科库等海量 OA 来源汇总全文,能补上其他来源覆盖不到的仓库副本。
  • 该来源仅在前面的 OA 来源(Unpaywall / Semantic Scholar / arXiv / PMC / bioRxiv)都未命中时才触发——不会干扰正常 OA 下载路径,因此常开无副作用。
  • 需要免费 API key(Bearer 认证);不设 CORE_API_KEY 时该来源静默跳过。
  • 免费层限速约 5 请求 / 10 秒,超出会返回 403——单篇无感,批量抓取时已串行限速。
  • 返回直链同样经过 %PDF 魔数 + 50 MB 校验;命中记录带 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_CLOAK CloakBrowser 兜底。
  • 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