news 2026/9/26 17:13:31

一键导出参考文献列表:Crossref与OpenAlex API批量获取引文全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一键导出参考文献列表:Crossref与OpenAlex API批量获取引文全攻略

之前有个朋友问我,怎么才能把一篇经典综述的参考文献列表一次性导出来,最好是点个按钮就能拿到完整的文献清单。当时我愣了一下,因为这个问题看起来简单,实际操作起来却涉及“引文网络”“DOI解析”“API调用”好几层东西。后来我发现,很多做综述、写论文、追踪研究方向的人都会卡在这个需求上。今天就把我折腾下来的完整方案、踩过的坑和顺手用的代码一次性讲清楚。

1. 先说清楚:你要导出的到底是什么

1.1 文献引用的两种方向:被引与施引

在做这事之前,先把概念理清楚。我们平时说“参考文献”,严格讲有两种:一种是某篇论文后面列出的参考文献列表,这些文献是“被这篇论文引用”的;另一种是“有哪些后来的文献引用了这篇论文”,在数据库里叫“被引文献”或“引证文献”。

标题里说的“某篇参考文献的所有参考文献”,指的是前者——给定一篇目标文献,导出它引用的全部参考文献。比如你有篇2015年的综述,你想把综述里引用的300篇文献一键导成题录,方便导入Zotero或EndNote,这就是典型场景。

但实际做的时候你会发现,通常大家还想要反向关系:这篇论文被谁引用了?因为写“研究进展”时,往前看和往后看都是刚需。所以后面讲到的方案里,我会两个方向都给出来,只是侧重点不同。

1.2 从“一篇文献”到“参考文献网络”

做这件事的真正难点不在于“导出”,而在于数据从哪里来。一篇文章的参考文献列表,本质上是存在出版社或数据库服务器上的结构化数据。正规获取方式有四种:

  • 直接在出版社页面复制:简单但琐碎,只能一篇一篇复制粘贴。
  • 用文献管理软件的“抓取参考文献”功能:比如Zotero的“添加附件时抓取元数据”,但并不是所有页面都能正确识别。
  • 用学术数据库的导出功能:Web of Science、Scopus、PubMed等都有批量导出,但通常需要订阅权限。
  • 用开放API批量拉取:Crossref、OpenAlex、Semantic Scholar等都提供免费接口,一条条结构化返回,这才是“一键”的正确实现路径。

理解了这个链路,你就能明白为什么网上很多教程会先让你安装Python。因为“一键导出”的本质是:用一个标识符(DOI或标题)找到这篇文献,再向数据库请求它“references”字段里的所有条目,最后格式化输出。

1.3 三种需求场景适合不同的工具

我自己把需求分成三类,因为对不同场景,最优方案完全不一样:

场景一:只是临时用一下,需要一两篇文献的引用列表。直接上Connected Papers或OpenAlex网页版,复制结果即可。

场景二:需要整理多篇文献,并导入文献管理器。推荐Zotero + 浏览器插件,或脚本批量跑Crossref API。

场景三:需要构建引文网络、做可视化分析。必须用Python调API,把数据存成结构化表格,再用Gephi或NetworkX画图。

这篇文章会把场景二、场景三讲透,场景一顺带演示。

2. 主流工具怎么选:数据库、文献管理器和开放API

聊方案之前先做个简短的“工具盘点”,否则很多人不知道从哪里下手。我按推荐程度从低到高排。

2.1 数据库自带的“引文关系”功能

Web of Science和Scopus都有“参考文献”和“被引次数”的导出功能。如果学校或机构购买了权限,可以直接在检索结果页勾选“导出为RIS或BibTeX”。这个做法最稳,数据结构最完整,还能直接拿到引用次数。

问题是:很多人没有订阅权限。另外Web of Science的导出有数量限制,一次最多导出500条记录,而且操作界面年年在变,我之前帮学生导出时找新版界面的按钮找了好几分钟。所以我一般把它当作“校验工具”而不是“主力工具”。

2.2 文献管理器与浏览器插件

Zotero和EndNote都能在浏览器里抓取文献信息。装上Zotero Connector后,打开一篇论文的页面,点一下插件图标,它会自动识别页面中的题录信息。对于单篇文章很好用。

但“一键导出参考文献的参考文献”这件事,Zotero默认做不到。它只能抓当前页面描述的文献,不能自动抓取被引列表里的每一条再递归入库。不过有一个变通办法:先把目标文献抓进Zotero,右键选择“查找可用元数据”,或者用“MS Word插件”里的“引用”功能——这都只能解决“管理”问题,解决不了“批量获取引文数据”的问题。

2.3 开放API:Crossref与OpenAlex

这才是“一键导出”的真正答案。Crossref是最权威的DOI注册机构,几乎所有有DOI的英文文献,它的参考文献数据都能查到。OpenAlex是后起之秀,数据覆盖更广,能覆盖更多中文文献和灰色文献。

两个服务都有公共API,无需注册就能使用基础功能。但公共接口有速率限制,如果是大量请求,建议注册免费API Key。

2.4 方案对比表

方案数据完整度是否需要权限是否支持批量适合人群
Web of Science / Scopus高需要订阅支持,但有限额有机构权限的研究人员
Zotero/EndNote中免费/付费弱想管理文献的人
Crossref API高(英文期刊)免费支持会一点点技术的人
OpenAlex API高(国际+部分中文)免费支持全面替代型需求
Connected Papers中(只有主路径节点)免费弱快速探索引文网络

这个表格基本回答了一个常见问题:“为什么不用某些数据库自带功能?”答案是:不是不用,而是很多人没有权限;在没有权限的情况下,Crossref和OpenAlex就是最优解。

3. 手把手:用Python调用Crossref API一键导出

这里给出一个可以直接把“某篇文献的所有参考文献”导成CSV/Excel的完整方案。前提是你电脑里装了Python,不用装太新版本,3.9以上即可。需要用到requests和pandas两个库,没装的话在终端执行:

pip install requests pandas

这一节的代码可以直接保存成文件,比如export_refs.py,然后在终端运行。全程大概能解决80%的英文文献导出需求。

3.1 准备工作:确定文献的唯一标识(DOI)

先弄清楚目标文献的DOI,这是后期的关键。DOI通常是一串形如10.xxxx/xxxxx的字符串。最省事的方式是在Google Scholar或期刊页面找“Cite”里的DOI。如果是中文文献,DOI不是标配,可以用OpenAlex或Crossref的检索接口,用标题反查。

我习惯先手动确认一次DOI再写进代码,因为标题反查偶尔会匹配到版本不同的预印本或撤稿文章。举个例子,假设我们要导出这篇文献的参考文献:

10.1038/s41586-020-2649-2

这是Nature那篇著名的SARS-CoV-2论文。接下来所有代码都用这个DOI做示例。

3.2 核心代码:一键导出所有参考文献

直接上代码,解释直接放在注释里。

import requests import pandas as pd import time def get_references(doi): # 用Crossref API获取文献元数据,包括references字段 url = f"https://api.crossref.org/works/{doi}" headers = { "User-Agent": "MyResearchScript/1.0 (mailto:your_email@example.com)" } resp = requests.get(url, headers=headers) if resp.status_code != 200: print(f"请求失败,状态码: {resp.status_code}") return None data = resp.json()["message"] refs = data.get("references", []) return data, refs def refs_to_dataframe(refs): rows = [] for ref in refs: row = { "key": ref.get("key"), "doi": ref.get("DOI", ""), "title": ref.get("article-title") or ref.get("volume-title", ""), "author": ref.get("author", ""), "year": ref.get("year", ""), "journal": ref.get("journal-title", ""), "volume": ref.get("volume", ""), "page": ref.get("page", ""), } rows.append(row) df = pd.DataFrame(rows) return df if __name__ == "__main__": target_doi = "10.1038/s41586-020-2649-2" meta, references = get_references(target_doi) if references is None: print("没有获取到参考文献数据") else: print(f"目标文献标题: {meta.get('title', [''])[0]}") print(f"参考文献总数: {len(references)}") df = refs_to_dataframe(references) df.to_csv("references_output.csv", index=False, encoding="utf-8-sig") print("已导出到 references_output.csv")

这段代码的运行逻辑很清楚:先请求Crossref的/works/{doi}接口,拿到JSON格式的记录,再从记录的references字段提取所有被引文献的题录信息,最后用pandas整理成表格。

很多人第一次跑的时候会忽略User-Agent,结果被Crossref限流。人家官方文档明确要求带上联系邮箱,不带的话,短时间多次请求会收到HTTP 429。这也是一个比较容易踩的坑。

3.3 代码解读:返回的JSON里到底有什么

跑完上面的代码,你会在终端看到类似这样的输出:

目标文献标题: A pneumonia outbreak associated with a new coronavirus of probable bat origin 参考文献总数: 92

输出的JSON里其实有两个大块:message里是目标文献自身的元数据,references是一个数组,每个元素代表一条参考文献。常见字段包括:

  • DOI:该参考文献的DOI,最关键的字段
  • article-title:论文标题
  • author:作者列表(有时是字符串,有时是数组)
  • year:年份(有时在journal-issue里)
  • journal-title:期刊名
  • volume/page:卷号和页码

Crossref的数据是出版社提交的,不是每个出版社都会结构化提交全部参考文献,所以会有缺失、字段不全的情况。这也是后面“常见问题”部分要重点讲的。

3.4 批量处理多篇文献的扩展版

实际工作中,很少有人只导出那一篇文献。比如你要写综述,手里有20篇核心文献,想把它们引用的参考文献全部汇总去重,做成“候选阅读清单”。

下面这段代码就是对上面的升级:接受一个DOI列表,循环批量拉取,并把所有参考文献合并到一个Excel文件里,增加一列“来源文献DOI”用来追溯。

import requests import pandas as pd import time def fetch_refs_batch(doi_list): all_rows = [] for doi in doi_list: url = f"https://api.crossref.org/works/{doi}" headers = {"User-Agent": "MyResearchScript/1.0 (mailto:your_email@example.com)"} try: r = requests.get(url, headers=headers, timeout=20) if r.status_code == 200: msg = r.json()["message"] for ref in msg.get("references", []): all_rows.append({ "来源文献DOI": doi, "参考文献DOI": ref.get("DOI", ""), "标题": ref.get("article-title") or ref.get("volume-title", ""), "作者": ref.get("author", ""), "年份": ref.get("year", ""), "期刊": ref.get("journal-title", ""), }) else: print(f"{doi} 返回 {r.status_code}") except Exception as e: print(f"{doi} 请求异常: {e}") time.sleep(1) # 控制请求频率,避免触发限流 df = pd.DataFrame(all_rows) return df if __name__ == "__main__": dois = [ "10.1038/s41586-020-2649-2", "10.1126/science.abc9753", # 示例,请替换成真实想查的DOI ] result = fetch_refs_batch(dois) print(f"共收集 {len(result)} 条参考文献记录") result.to_excel("all_references.xlsx", index=False)

跑这个批量版本时,注意一定要在每次请求后加time.sleep(1)或至少0.5秒的间隔。不加间隔的话,50篇文献的请求会在很短时间内打过去,很容易触发限流或封禁IP。我实测过,间隔1秒,100篇文献跑下来大概2分钟左右,完全可接受。

如果想更进一步,还能对拿到的“参考文献DOI”做“去重”和“反向引流”——把第一轮得到的DOI再作为输入,继续往回追,这样一层层就能建出一棵引文树。不过要控制层数,两层就足够一般综述使用了,三层以上数据量会爆炸式增长,而且噪声特别大。

4. 常见问题与排查技巧实录

这部分是我实际使用中总结出来的,比代码本身更有价值,建议收藏。

4.1 参考文献列表为空或字段缺失

用Crossref拉某篇论文的参考文献,最常遇到的坑就是:返回结果里references字段为空。这里要先分清楚情况:

  • 有些早期文献(1990年代以前)本来就没在Crossref注册参考文献,这种情况怎么请求都没用。
  • 有些出版社虽然提交了参考文献,但没有结构化,Crossref拿不到引用关系。
  • 有些中文期刊的DOI在Crossref上查不到“references”数据,因为中文期刊的参考文献数据往往只存在于知网或万方。

遇到这种情况,我的做法是换OpenAlex换个数据源试试。OpenAlex的接口更简单:

https://api.openalex.org/works/doi:10.1038/s41586-020-2649-2

返回结果里的referenced_works字段就是参考文献列表(这里存的是OpenAlex自己的ID,需要再请求一下把ID换成元数据)。这个方法经常能拿到Crossref缺失的部分。如果两个API都没有,那基本可以断定是数据源没收录,只能去出版社页面人工复制了。

4.2 中英文文献的处理差异

中文文献的DOI普及率很低,这是很多国内学生的痛点。针对中文文献,有两个替代方案:

  • 方案一:用Crossref的检索接口按标题查中文标题或拼音标题,能查到部分被收录的中文文献,但参考文献字段通常不完整。
  • 方案二:直接用“知网研学”或“NoteExpress”这类国产文献工具。知网研学支持正则表达式批量提取参考文献,选中一篇文献,右键就能导出引文列表,虽然还是不够“一键”,但已经比手工复制强很多。

如果你已经拿到了中文学术论文的PDF,还有个土办法:用pdftotext提取PDF里的参考文献部分,然后用正则表达式切分条目。这个方法效率不高,但对付扫描版以外的PDF是可行的,适合少量文献兜底。

4.3 把“参考文献”变成“被引文献”

在写文献综述时,除了向前追溯,你可能还想知道这篇文章被哪些后来者引用。这个方向的API同样可以用:

  • OpenAlex的cites反查:https://api.openalex.org/works?filter=cites:W000000000
  • Semantic Scholar API:https://api.semanticscholar.org/graph/v1/paper/DOI:10.xxxx/citations

以Semantic Scholar为例,也可以直接请求引用它的文献列表:

import requests paper_doi = "10.1038/s41586-020-2649-2" url = f"https://api.semanticscholar.org/graph/v1/paper/DOI:{paper_doi}/citations" params = {"fields": "title,year,authors,externalIds"} r = requests.get(url, params=params) data = r.json() print(f"被引文献数量: {len(data.get('data', []))}")

注意Semantic Scholar这个接口默认只返回100条,需要设置limit或翻页。而且它的限流比Crossref更严格,一本正经地写个“会礼貌等待”的循环是必要的。

4.4 反爬与限流:User-Agent与请求间隔

很多人第一次跑API就发现跑到一半就报429或403。这里有两个“软技巧”:

第一,把User-Agent写清楚,最好带邮箱。官方文档对“有礼貌的机器人”是很友好的。我用的是:

User-Agent: MyResearchScript/1.0 (mailto:yourname@example.com)

第二,控制频率。Crossref的免费额度大概是每秒一次,OpenAlex也能到每秒十次。但为了稳定,我习惯把每篇文献之间的间隔设置在1秒以上。做研究又不差这几分钟,别把自己IP搞进黑名单。

4.5 引文网络可视化:让数据真正有用

导出数据只是第一步。很多人把“参考文献列表”导出后,发现几百条文献根本看不完,这时候就需要可视化。

我这里提供一个最简单的方法:把导出的CSV整理成两列——来源文献DOI和目标文献DOI,然后直接导入Gephi生成引文网络图。操作步骤:

  • 用pandas读CSV,去掉空白DOI的行。
  • 生成一个edges.csv(source, target)。
  • Gephi打开边表,选择“布局→Force Atlas 2”,跑一遍布局就能出图。

Gephi对新手不算友好,但做引文关系图还挺直观。如果不想装软件,可以用NetworkX画一张基础图:

import networkx as nx import pandas as pd df = pd.read_csv("references_output.csv") G = nx.from_pandas_edgelist(df, "key", "doi", create_using=nx.DiGraph()) print(nx.info(G))

这里直接用“key”字段作为起点,因为Crossref的references里每个引用都带一个形如“ref1”“ref2”的key。画图的意义在于,你能一眼看到哪几篇文献是整个综述的“枢纽”,这对锁定必读文献非常有帮助。

4.6 常见问题速查表

问题原因解决办法
API返回429请求太频繁加长sleep间隔,设置User-Agent
references字段为空出版社未提交引文数据换OpenAlex或Crossref搜索接口
标题只有半个或不完整元数据质量差用DOI而不是标题匹配
中文文献导不出DOI不普及用知网/NoteExpress或PDF正则
没有DOI怎么办早期文献或灰色文献用标题+年份+作者组合检索
想拿施引文献不知道去哪用OpenAlex或Semantic Scholar见4.3节代码

这张表里最后一条,我几乎每次讲这个主题都会被问到。所以如果只让你记住一个工具,我推荐OpenAlex,原因是它把“给一篇文献,返回它的引用和被引”这件事做得最顺,而且完全免费。

5. 实操总结与我的个人体会

工具和方法讲到这,基本算是闭环了。下面聊点纯经验的东西。

5.1 工具的边界要心里有数

没有哪个工具能把所有参考文献100%完整导出,这是必须接受的事实。Crossref的优缺点是“覆盖广”和“字段不全”并存,OpenAlex覆盖更全面但部分数据是自动解析出来的,偶尔会有错误。所以无论如何,对于自己论文里真正引用的文献,最后都要用人工校对一遍,千万别把API跑出来的结果直接当成最终文献列表交给导师。

我自己的习惯是,批量导出后,在Excel里做三轮筛查:第一轮去掉没有DOI的记录,第二轮把标题明显残缺的挑出来人工补齐,第三轮把重复文献去重。几轮下来,几十篇的错误率能被压到极低。

5.2 我的最终习惯流程

如果你只需要一个行动指南,按下面这个来:

  • 单篇英文文献:用3.2节的脚本,直接导出CSV。
  • 多篇核心文献做综述:用3.4节的批量脚本,汇总后去重,再加一层OpenAlex补充缺失。
  • 需要可视化引文网络:先把结果用NetworkX或Gephi画图,把“枢纽文献”挑出来优先阅读。
  • 中文文献:直接用知网研学或NoteExpress,不用花时间调API。

这个流程我用了快三年,从硕士到博士阶段一直都在用,写综述的效率确实比周围人快不少。最后再分享一个命令行里的小技巧:如果只是想要一眼看清这篇文献引用了哪些年份的文献,可以在导出后加一行代码:

df["年份"] = pd.to_numeric(df["年份"], errors="coerce") print(df["年份"].value_counts().sort_index())

这样就能知道这篇文献的引用是否偏旧,是否遗漏了近几年的重要文章——论文审稿人最爱问的“近三年文献引用不足”问题,用这个办法可以提前自查。做研究没有银弹,但把工具链路跑通之后,省下来的时间足够你多读几篇真正有价值的论文了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 17:12:55

Python全栈项目工程化实战:测试、Git与生产部署全解析

1. 工程化到底在讲什么,为什么单独占了一讲很多同学在学Python全栈开发的时候,前八讲可能都在写代码、调接口、做页面,到了第9讲突然画风一变,开始讲测试、Git和生产部署。有学员问我,这些东西跟写业务代码有什么关系&…

作者头像 李华
网站建设 2026/9/26 17:11:21

Linux信号处理全解:从异步通知原理到EINTR排查实战

新手阶段我啃《APUE》信号那一章,啃了三遍才敢说自己入门了。但真正让我对信号机制“开窍”的,不是书本上的定义,而是线上一次诡异的服务“假死”事故——进程还在,CPU 占用为 0,就是什么活都不干。后来 strace 一挂&a…

作者头像 李华
网站建设 2026/9/26 17:11:16

ghcr.io镜像拉不下来?亲测有效的六种加速与搬运方案

1. 为什么每次 docker pull ghcr.io 都卡在半路:一次拉取背后的完整链路群里又有人喊 ghcr.io 镜像拉不动了。这种事我一年能碰上好几次:docker pull ghcr.io/xxx/yyy:latest敲下去,进度条长时间停在 0%,等几分钟直接弹i/o timeou…

作者头像 李华
网站建设 2026/9/26 17:11:16

校园文件管理系统源代码实战:部署、权限控制与二次开发指南

简介:一套面向校园网环境的文件管理系统源代码,覆盖学校班级文件共享、课件资源管理、内容发布与存储备份等典型场景。系统由桃源企业文件管理系统V2.4演进而来,在通用文件功能的基础上强化了文件发布、教育课件管理和权限控制能力&#xff0…

作者头像 李华
网站建设 2026/9/26 17:08:18

Claude Code Skills实战指南:从安装配置到API报错排查

做 AI 编程这块的朋友,最近应该都注意到一个事:Claude Code 从单纯的命令行助手,开始往“带技能”的方向发展了。这个 Skills 扩展机制刚出来的时候我还没太当回事,直到自己在两个项目里连续踩了上下文失控和 API 调用混乱的坑&am…

作者头像 李华
网站建设 2026/9/26 17:07:37

Linux Socket编程:从底层通信原理到常见错误排查

我们直接聊Socket编程,但聊的是写第一行代码之前,你必须先搞明白的那些底层的、通信层面的东西。很多教程一上来就甩给你socket()、bind()、listen()的函数签名,然后让你抄一个 echo server,跑通了就以为会了。但一旦遇到高并发、…

作者头像 李华