如何用 paper-lookup 技能检索学术文献并返回可复现的出处信息
【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills
paper-lookup 是 scientific-agent-skills 仓库中的一个技能:它把 11 个学术文献 API(PubMed、PMC、Europe PMC、bioRxiv、medRxiv、arXiv、OpenAlex、Crossref、Semantic Scholar、CORE、Unpaywall)整理成带文档端点和已知故障模式的参考文件,配套四个只用标准库的 Python 脚本。它的目标是把"找一篇文献"变成一次可复现的检索——回答里要带足端点、参数、标识符和访问日期,让人或另一个 agent 能够原样重放这次调用。
适用前提(来自技能 frontmatter 的 compatibility 说明):
- 需要网络访问和
curl; - 随附脚本要求Python 3.11+,只用标准库;
- 不需要任何凭据即可基本使用;
NCBI_API_KEY、S2_API_KEY、CORE_API_KEY、OPENALEX_API_KEY四个环境变量只用于提高速率上限或解锁全文(例如 NCBI 无 key 为 3 req/s,有 key 为 10 req/s;CORE 的全文检索需要 key)。
准备工作:先读参考文件,再发请求
技能的硬性要求是:调用某个数据库之前,先读它对应的参考文件。每个数据库在 skills/paper-lookup/references/ 下有一个.md文件,包含端点、参数表、示例调用、响应结构和"该 API 具体会在哪里悄悄出错"。技能文档明确写着:故障章节不是可选背景,错误答案就是从那里来的(见 skills/paper-lookup/SKILL.md)。
按意图选库,这是文档给出的选型规则(节选自 SKILL.md 的 Database Selection Guide):
| 用户意图 | 首选库 | 也可考虑 |
|---|---|---|
| 生物医学话题的论文 | PubMed | Europe PMC、Semantic Scholar、OpenAlex |
| 在全文里做关键词检索 | Europe PMC | CORE |
| 生物预印本(按主题) | Europe PMC(SRC:"PPR") | Semantic Scholar、OpenAlex |
| 预印本按日期或 DOI 浏览 | bioRxiv / medRxiv | Europe PMC |
| 物理、数学、CS 预印本 | arXiv | Semantic Scholar、OpenAlex |
| 跨所有学科的论文 | OpenAlex | Semantic Scholar、Crossref |
| 按 DOI 查特定论文 | Crossref | Unpaywall、Semantic Scholar |
| 论文的开放获取 PDF | Unpaywall | CORE、PMC |
| 引用关系图 / 某作者的发表 | Semantic Scholar | OpenAlex |
注意两点选型边界:bioRxiv 和 medRxiv 自己的 API没有关键词检索,只有日期浏览和 DOI 查询,所以"按主题找预印本"要路由到 Europe PMC;PubMed 只有引文和摘要,没有全文,全文要走 PMC 或 Europe PMC。
如果约束影响正确性但缺失("最近"却没给年份、作者同名很多),文档的要求是先问清再查,而不是猜。
主路径:一次带出处信息的主题检索
以"检索某个生物医学话题的近期论文,并核对其中哪些有开放获取全文"为例,按下面顺序执行。所有命令都在 skills/paper-lookup/ 目录下运行(脚本路径是相对于该目录的)。
第 1 步:PubMed eSearch 拿 PMIDs 和总数
curl -s --get "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi" \ --data-urlencode 'db=pubmed' \ --data-urlencode 'term=CRISPR gene therapy' \ --data-urlencode 'retmax=5' \ --data-urlencode 'retmode=json' \ --data-urlencode 'sort=pub_date' \ --data-urlencode 'tool=your_app_name' \ --data-urlencode 'email=you@example.com'其中tool和email是 NCBI 要求带上的参数,替换成你自己的应用名和邮箱。term支持 PubMed 字段标签([TI]标题、[AU]作者、[MH]MeSH)和布尔运算(参数表见 references/pubmed.md)。
响应(文档示例,数值会随查询变化):
{ "esearchresult": { "count": "224107", "idlist": ["39984857", "39984678", "39984543", "39984210", "39983901"] } }count是预计总数,先记下它,最后要拿来做对账。定向查找时首页通常就够;穷尽式检索("某作者的全部论文")才需要分页。
第 2 步:eSummary 取书目字段
curl -s "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=39984857,39984678&retmode=json"返回字段包括uid、pubdate、source(期刊)、authors、title、elocationid(DOI)和articleids(DOI、PMC 等标识符)。摘要本身要用 eFetch(rettype=abstract&retmode=text或retmode=xml)单独取。
第 3 步(可选分支):逐 DOI 核对开放获取状态
从 eSummary 拿到 DOI 后查 Unpaywall。它不接收占位邮箱——文档明确写了test@example.com这类值会被 HTTP 422 拒绝,所以必须替换成你自己的真实邮箱:
curl -s "https://api.unpaywall.org/v2/10.1038/nature12373?email=you@example.com"判断依据:is_oa为 true 时取best_oa_location.url_for_pdf作为免费 PDF 地址;oa_status区分gold/hybrid/bronze/green/closed。注意 Unpaywall 的 search 端点自 2026 年 3 月起持续返回 HTTP 500,文档要求只走 DOI 查询,先用 PubMed/OpenAlex/Semantic Scholar 找到论文,再逐 DOI 核对 OA 状态(见 references/unpaywall.md)。
替代入口:Europe PMC 一条命令跨库检索
如果意图是"在全文里搜关键词"或"按主题找 bioRxiv 预印本",直接查 Europe PMC——它对 PubMed、PMC 全文、预印本做统一索引,且完全免 key、免邮箱。预印本主题检索的文档范例:
curl -s --get "https://www.ebi.ac.uk/europepmc/webservices/rest/search" \ --data-urlencode 'query=(SRC:"PPR" AND PUBLISHER:"bioRxiv" AND "organoid")' \ --data-urlencode 'format=json&pageSize=10&resultType=lite'从结果的doi(形如10.1101/...)可以继续到 bioRxiv API 取预印本专属元数据(如 published-version 链接)。resultType=core会增加摘要、全文链接、MeSH 和资助信息。
arXiv 检索:用随附脚本解析 Atom XML
arXiv 只返回 Atom XML,没有 JSON 选项,且限流是1 次请求 / 3 秒。文档要求把响应交给解析脚本而不是手写的解析逻辑:
curl -s "https://export.arxiv.org/api/query?id_list=1706.03762" | python3 scripts/arxiv_atom.py -脚本输出每条记录的 JSON(arxiv_id、title、abstract、authors、pdf_url等),并处理了版本后缀、命名空间等已知陷阱。完整参数用python3 scripts/arxiv_atom.py --help查看。
穷尽式分页:paginate.py 与 --dry-run
跨 bioRxiv、medRxiv、Europe PMC、OpenAlex、Crossref 的分页行为各不相同(绝对偏移、不透明游标、continuation token、1-based 页码),技能把这套逻辑固化在 scripts/paginate.py 里。花调用之前先用--dry-run只打印第一个 URL 不实际请求,确认查询无误:
python3 scripts/paginate.py --api europepmc --query 'SRC:"PPR" AND "organoid"' --max-records 200 --dry-run python3 scripts/paginate.py --api europepmc --query 'SRC:"PPR" AND "organoid"' --max-records 200脚本按响应实际报告的页大小步进(不是假设的常数),默认上限约 1,000 条记录 / 50 次调用,超过会停下来要求确认而不是静默截断。--list-apis打印各 API 的查询格式。
返回可复现的出处信息
检索做完后,按 SKILL.md 规定的输出结构组织回答:答案在前,出处在后。
## Retrieval Summary - Query: <用户问了什么> - Scope: targeted lookup | exhaustive retrieval - Databases queried: PubMed (esearch+esummary), Unpaywall (DOI lookup) - Access date: <日期> ## Results ### PubMed <论文:标题、作者、年份、期刊、DOI/PMID —— 用户需要的字段> ### Unpaywall <OA 状态和最佳 PDF 链接> ## Provenance - Endpoints & parameters: <足以重放这次调用的端点与参数> - Identifier conversions: <如有标识符转换> - Count reconciliation: <穷尽式检索时:预期总数 vs 实取数、抓了几页> - Warnings: <空结果、分页不全、只有元数据无全文、缺 key、端点过期等>三条硬性规则:
- 不要默认输出原始 JSON 堆。默认给可读的字段摘要;只有用户明确要原始 JSON 或载荷很小时才引用相关切片,并标注为不受信任的第三方数据。大型全文拉取(PMC、Europe PMC、CORE)应存到本地文件并报告路径,而不是灌满回答。
- 不要把元数据冒充全文。如果
jats_to_text.py退出码为 2,诚实的报告是"该文章拿不到全文,这里是摘要,开放获取副本可能在这里",而不是用标题和作者列表编一段"总结"。 - 空结果要明说。查不到就是查不到,静默的缺口会被误读成"这篇文献不存在"。
验证结果:HTTP 200 不等于成功
这是技能文档反复强调的核心风险:这 11 个 API 会在 200 响应体里报失败。验证方式是检查拿到的数据的形状,而不是状态码。逐项核对:
| 现象 | 出现位置 | 判断方法 |
|---|---|---|
条目<title>Error</title>,totalResults: 1 | arXiv 参数写错时 | 把任何条目前先检查标题是否为Error;arxiv_atom.py遇到该 feed 会以退出码 3 结束并回显查询 |
200 响应体内含errCode、无resultList | Europe PMC(如pageSize=1001返回errCode: 404) | 解析结果前先检查errCode或resultList缺失 |
status: "no articles found"配空集合 | bioRxiv | 与"真没查到"无法区分,除非读status字段 |
JATS 有完整引文但没有<body> | NCBI eFetch(出版商禁止再分发时) | jats_to_text.py以退出码 2 报告"只有元数据,不是全文" |
14 字节纯文本Rate exceeded. | arXiv 限流(HTTP 429;持续限流时直接断连,curl 报HTTP=000) | 检查状态码和原始字节再下结论;修复方式是等待而不是加力重试 |
另外两个查询回显检查,用于发现查询本身被改写:
- Europe PMC 响应的
request.queryString是解析后的查询——和你发出去的做 diff,抓到被截断或变形的查询再信任hitCount; - arXiv 的 feed
<title>回显实际执行的查询。拼错字段前缀(author:而不是au:)时,arXiv 会静默改写成all:全文检索并照常返回"合理"的结果。
计数对账是穷尽式检索的验证方式:第一响应的hitCount/count是总数,逐页抓完后报告"预期总数 vs 实取数、抓了几页、做了哪些本地过滤"。paginate.py把实取数少于总数时的退出码定为4(记录丢了,而不是你设了上限),并区分"你设了边界"和"记录真的缺失"。这些脚本的非零退出码被文档定义为信息而不是障碍:报告它说了什么,不要绕过它自己重新解析。
标识符格式核对与已知限制
检索失败时,文档要求先查标识符格式——这是最常见的原因:
| 标识符 | 格式 | 使用方 |
|---|---|---|
| DOI | 10.xxxx/xxxxx | 所有库 |
| PMID | 整数 | PubMed、PMC、Europe PMC、Semantic Scholar |
| PMCID | PMC+ 数字 | PMC、Europe PMC |
| arXiv ID | YYMM.NNNNN | arXiv、Semantic Scholar |
| OpenAlex ID | W+ 数字 | OpenAlex |
| Europe PMC ID | {source}/{id}对(如MED/32117569) | Europe PMC |
跨库转换有前缀约定:Semantic Scholar 接受DOI:、PMID:、ARXIV:前缀,OpenAlex 接受doi:、pmid:前缀,PMID/PMCID/DOI 之间用 PMC ID Converter 互转。两个文档点名的坑:Europe PMC 的id单独用不唯一,必须连source一起带;构造出来的 arXiv DOI(10.48550/arXiv.{id})不是可移植键——它在 doi.org 可解析,但 Crossref 会 404(DataCite DOI,未注册到 Crossref),OpenAlex 对部分论文也查不到,所以跨库引用 arXiv 论文应优先用 arXiv ID 或标题检索(详见 references/arxiv.md)。
速率与规模的边界:NCBI 无 key 3 req/s、有 key 10 req/s;arXiv 1 次 / 3 秒,且被 arXiv 拒绝过的请求不要原样重试(文档记录到坏请求的限流惩罚远重于正常请求);Crossref 公开池 5 req/s,加mailto进礼貌池 10 req/s。同一限流主机上的请求必须串行,只有不同开放 API(OpenAlex、Crossref、Semantic Scholar、Europe PMC、Unpaywall)之间才允许并行,且在途请求保持个位数。单次检索超过约 1,000 条记录或约 50 次调用时,先和用户确认计划;真正的大批量需求应指向数据库的快照/转储(Unpaywall、OpenAlex、CORE 都提供)。
API key 的处理规则也属于出处纪律的一部分:两个 API 用查询字符串认证,所以你请求的 URL 本身就是凭据。paginate.py在输出的出处中自动抹掉api_key、email、mailto、tool的值;你手写的任何 URL 记录要做同样处理,key 永远不能出现在回答里。
【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考