需求: 我有几个 bib 文件,其中大多数 entries 没有 doi 字段,但现在发现这样做不规范,所有的 entries 都需要加上 doi. 几百个 entries, 手动添加比较麻烦,而且部分 entries 本来就没有 doi. 想问问据各位道友所知,批量添加 doi 最方便的方法是什么?
chatgpt 给我的几个推荐:
- org-ref: 我没用过,调用
(org-ref-get-doi-at-point)
不成功 (我不知道这个函数应该是把 point 放在哪里调用).
- zotero: 最大的问题是,我担心 zotero 导入再导出后,导致我的 bib 文件和之前有意料之外的不同。
- python.
方法可以不限于 emacs.
还是zotero+Better BibTex插件吧。实在担心影响原始bib,那就用python把Better BibTex输出的bib里的doi提取出来,再注入自己的bib。
我用的这种做法:
import requests
import bibtexparser
import sys
def get_doi_from_title(title):
url = f"https://api.crossref.org/works?query.title={title}&rows=1"
try:
response = requests.get(url, timeout=10)
if response.status_code == 200:
data = response.json()
items = data.get("message", {}).get("items", [])
if items:
return items[0].get("DOI")
except:
return None
def process_bib_file(filename):
with open(filename) as bibtex_file:
bib_database = bibtexparser.load(bibtex_file)
updated = False
for entry in bib_database.entries:
if entry.get('ENTRYTYPE') == 'misc':
continue
if 'doi' not in entry and 'title' in entry:
doi = get_doi_from_title(entry['title'])
if doi:
entry['doi'] = doi
updated = True
print(f"Updated DOI for: {entry['ID']} - {entry['title']}")
else:
print(f"Failed to find DOI for: {entry['ID']} - {entry['title']}")
if updated:
with open(filename, 'w') as bibtex_file:
bibtexparser.dump(bib_database, bibtex_file)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python script.py <bib_file1.bib> <bib_file2.bib> ...")
sys.exit(1)
for bib_file in sys.argv[1:]:
print(f"Processing {bib_file}...")
process_bib_file(bib_file)
这样直接:
python get-doi.py local-bib.bib
就会自动添加所有没有 doi fields 的 fields. 不需要用 zotero 之类的, 也不用任何 packages, 我觉得这个方法足够方便。