mcpField
B
biorxiv-database

biorxiv-database

github.com/jaechang-hits生产力38469 次安装1 周前更新
代码仓库

关于 biorxiv-database

此技能介绍如何以编程方式访问 bioRxiv 和 medRxiv 预印本,适用于研究者及文献监测流程。其 REST API 可按 DOI 或日期范围获取元数据和版本信息,并查询发表状态。

主要功能

  1. 01按 DOI 或日期范围搜索预印本
  2. 02获取元数据、摘要和版本
  3. 03监测研究类别
  4. 04查询同行评审发表状态
  5. 05分页读取 API 结果

适用场景

  1. 01汇总每周特定类别的预印本
  2. 02筛查一组 DOI 对应的摘要
  3. 03跟踪预印本更新与版本
  4. 04核查哪些预印本已发表

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill biorxiv-database

安装后在 Claude Code 中输入/biorxiv-database确认已加载。

详细介绍

bioRxiv / medRxiv 预印本数据库

概述

bioRxiv(生物学)和 medRxiv(健康科学)是免费的预印本服务平台,分别收录了 200,000+ 和 50,000+ 篇在同行评审前或评审期间发布的手稿。统一的 REST API 无需身份验证即可通过编程方式访问预印本元数据(标题、摘要、作者、类别、DOI、版本历史)。预印本以 PDF 格式提供,可通过 DOI、日期范围或类别检索。

适用场景

  • 在发展迅速的领域中,在同行评审前查找最新研究(例如,疫情期间的传染病研究)
  • 监控特定学科类别(例如,生物信息学、基因组学、神经科学)每周提交的预印本
  • 检索一组 bioRxiv DOI 的元数据和摘要,用于文献筛选
  • 构建预印本语料库,追踪预印本到正式发表的流程
  • 检查特定预印本是否已更新或发表于同行评审期刊
  • 对于经过同行评审的生物医学文献,请使用 pubmed-database;对于所有学科,请使用 openalex-database

前提条件

  • Python 包:requests、pandas
  • 数据要求:bioRxiv/medRxiv DOI、日期范围或类别名称
  • 环境:需要互联网连接;无需 API 密钥或身份验证
  • 速率限制:未说明硬性限制;批量查询时请合理设置请求间隔
pip install requests pandas

快速入门

import requests

BASE = "https://api.biorxiv.org"

# Retrieve recent bioinformatics preprints
r = requests.get(f"{BASE}/details/biorxiv/2024-01-01/2024-01-07/0",
                 params={"category": "bioinformatics"})
r.raise_for_status()
data = r.json()
print(f"Total preprints: {int(data['messages'][0]['total'])}")  # API returns total as a string
for article in data["collection"][:3]:
    print(f"\n{article['title'][:80]}")
    print(f"  Authors : {article['authors'][:60]}")
    print(f"  DOI     : {article['doi']}")
    print(f"  Category: {article['category']}")

核心 API

查询 1:按日期范围列出预印本

检索在某个日期范围内发布的所有预印本,也可以按类别筛选。

import requests, pandas as pd

BASE = "https://api.biorxiv.org"

def get_preprints(server, date_from, date_to, cursor=0, category=None):
    """
    server: 'biorxiv' or 'medrxiv'
    date_from, date_to: 'YYYY-MM-DD' strings
    cursor: page offset (increments of 100)
    """
    url = f"{BASE}/details/{server}/{date_from}/{date_to}/{cursor}"
    r = requests.get(url)
    r.raise_for_status()
    return r.json()

data = get_preprints("biorxiv", "2024-01-01", "2024-01-03")
total = int(data["messages"][0]["total"])  # API returns total as a string — cast for arithmetic
print(f"bioRxiv preprints Jan 1-3, 2024: {total}")

rows = []
for article in data["collection"][:10]:
    rows.append({
        "doi": article["doi"],
        "title": article["title"],
        "authors": article["authors"][:80],
        "category": article["category"],
        "date": article["date"],
        "version": article["version"],
    })
df = pd.DataFrame(rows)
print(df[["title", "category", "date"]].head())
# Paginate through all results for a date range
def get_all_preprints(server, date_from, date_to, max_results=500):
    all_articles = []
    cursor = 0
    while len(all_articles) < max_results:
        data = get_preprints(server, date_from, date_to, cursor)
        collection = data["collection"]
        if not collection:
            break
        all_articles.extend(collection)
        total = int(data["messages"][0]["total"])  # cast: API returns total as string
        cursor += 100
        if cursor >= total:
            break
    return all_articles[:max_results]

articles = get_all_preprints("biorxiv", "2024-01-01", "2024-01-07")
print(f"Retrieved {len(articles)} preprints from first week of 2024")
查询 2:按 DOI 获取预印本详情

按 DOI 检索特定预印本的完整元数据和版本历史。

import requests

BASE = "https://api.biorxiv.org"

# Retrieve specific preprint by DOI
doi = "10.1101/2024.01.01.000001"  # Replace with real DOI

def get_by_doi(server, doi):
    r = requests.get(f"{BASE}/details/{server}/{doi}")
    r.raise_for_status()
    return r.json()

# Generic example using bioRxiv DOI pattern
r = requests.get(f"{BASE}/details/biorxiv/10.1101/2024.05.28.596311")
if r.ok:
    data = r.json()
    articles = data.get("collection", [])
    if articles:
        art = articles[-1]  # Latest version
        print(f"Title   : {art['title']}")
        print(f"Authors : {art['authors'][:100]}")
        print(f"Category: {art['category']}")
        print(f"Date    : {art['date']}")
        print(f"Version : {art['version']}")
        print(f"DOI     : {art['doi']}")
        print(f"Abstract (first 300): {art['abstract'][:300]}")
查询 3:查询已发表的预印本

检查预印本是否已发表于同行评审期刊。

import requests

BASE = "https://api.biorxiv.org"

def check_published(server, doi):
    """Check if a preprint DOI has a corresponding published article."""
    r = requests.get(f"{BASE}/publisher/{server}/{doi}")
    r.raise_for_status()
    data = r.json()
    return data.get("collection", [])

# Check one known preprint
doi = "10.1101/2024.05.28.596311"
published = check_published("biorxiv", doi)
if published:
    pub = published[0]
    print(f"Published in: {pub.get('published_journal')}")
    print(f"Published DOI: {pub.get('published_doi')}")
else:
    print(f"Preprint {doi} has not been published yet (or not tracked)")
查询 4:按类别监控

按特定研究类别监控预印本。

import requests, pandas as pd
from datetime import date, timedelta

BASE = "https://api.biorxiv.org"

# bioRxiv categories include: bioinformatics, genomics, neuroscience,
# immunology, cell-biology, biochemistry, microbiology, etc.

def weekly_category_digest(category, days_back=7):
    """Get preprints from last N days for a specific category."""
    today = date.today()
    date_from = (today - timedelta(days=days_back)).strftime("%Y-%m-%d")
    date_to = today.strftime("%Y-%m-%d")

    all_articles = []
    cursor = 0
    while True:
        r = requests.get(f"{BASE}/details/biorxiv/{date_from}/{date_to}/{cursor}")
        data = r.json()
        batch = [a for a in data["collection"] if category.lower() in a["category"].lower()]
        all_articles.extend(batch)
        if len(data["collection"]) < 100:
            break
        cursor += 100

    return pd.DataFrame(all_articles)[["doi", "title", "authors", "date"]] if all_articles else pd.DataFrame()

df = weekly_category_digest("genomics", days_back=3)
print(f"Recent genomics preprints: {len(df)}")
print(df[["title", "date"]].head())
查询 5:medRxiv 临床/健康研究

查询 medRxiv 上的健康和临床科学预印本。

import requests, pandas as pd

BASE = "https://api.biorxiv.org"

# medRxiv categories: infectious diseases, epidemiology, oncology,
# cardiology, neurology, psychiatry, public and global health, etc.

r = requests.get(f"{BASE}/details/medrxiv/2024-01-01/2024-01-07/0")
r.raise_for_status()
data = r.json()
total = int(data["messages"][0]["total"])  # cast: API returns total as string
print(f"medRxiv preprints Jan 1-7, 2024: {total}")

# Group by category
from collections import Counter
category_counts = Counter(a["category"] for a in data["collection"])
print("\nTop categories:")
for cat, count in category_counts.most_common(5):
    print(f"  {cat}: {count}")
查询 6:批量解析 DOI 并提取摘要

检索一组 bioRxiv DOI 对应的摘要。

import requests, time, pandas as pd

BASE = "https://api.biorxiv.org"

dois = [
    "10.1101/2024.05.28.596311",
    "10.1101/2023.11.28.569048",
    "10.1101/2023.03.07.531523",
]

rows = []
for doi in dois:
    r = requests.get(f"{BASE}/details/biorxiv/{doi}")
    if r.ok:
        collection = r.json().get("collection", [])
        if collection:
            art = collection[-1]  # Latest version
            rows.append({
                "doi": doi,
                "title": art.get("title"),
                "category": art.get("category"),
                "date": art.get("date"),
                "abstract": art.get("abstract", "")[:300],
            })
    time.sleep(0.2)

df = pd.DataFrame(rows)
if not df.empty:
    df.to_csv("preprint_abstracts.csv", index=False)
    print(df[["doi", "title", "category"]].to_string(index=False))
else:
    print("No valid preprints found for provided DOIs")

关键概念

API 端点结构

bioRxiv API 遵循以下模式:https://api.biorxiv.org/details/{server}/{interval}/{cursor}

  • server:biorxiv 或 medrxiv
  • interval:DOI(用于获取单条记录)或 date_from/date_to(用于指定日期范围)
  • cursor:分页偏移量(0、100、200…)
版本追踪

预印本可以更新;每次更新都会创建一个新版本(v1、v2、v3…)。API 按时间顺序返回所有版本;collection 中的最后一项始终是最新版本。

常见工作流

工作流 1:每周预印本摘要流水线

目标:自动收集目标类别中上周发布的预印本,并导出以供审阅。

import requests, time, pandas as pd
from datetime import date, timedelta

BASE = "https://api.biorxiv.org"

TARGET_CATEGORIES = ["bioinformatics", "genomics", "systems biology"]
DAYS_BACK = 7

today = date.today()
date_from = (today - timedelta(days=DAYS_BACK)).strftime("%Y-%m-%d")
date_to = today.strftime("%Y-%m-%d")

print(f"Fetching bioRxiv preprints from {date_from} to {date_to}")

all_articles = []
cursor = 0
while True:
    r = requests.get(f"{BASE}/details/biorxiv/{date_from}/{date_to}/{cursor}")
    r.raise_for_status()
    data = r.json()
    batch = data["collection"]
    if not batch:
        break
    all_articles.extend(batch)
    total = int(data["messages"][0]["total"])  # cast: API returns total as string
    cursor += 100
    if cursor >= total:
        break
    time.sleep(0.1)

# Filter by target categories
filtered = [a for a in all_articles
            if any(cat in a.get("category", "").lower() for cat in TARGET_CATEGORIES)]

df = pd.DataFrame(filtered)[["doi", "title", "authors", "category", "date"]]
df = df.drop_duplicates(subset="doi")  # Remove duplicate versions

output_file = f"biorxiv_digest_{date_to}.csv"
df.to_csv(output_file, index=False)
print(f"\nSaved {len(df)} preprints across {len(TARGET_CATEGORIES)} categories → {output_file}")
print(df[["title", "category", "date"]].head(5).to_string(index=False))
工作流 2:预印本到正式发表的追踪器

目标:对于一组预印本 DOI,检查哪些已发表,并检索发表详情。

import requests, time, pandas as pd

BASE = "https://api.biorxiv.org"

preprint_dois = [
    "10.1101/2024.05.28.596311",
    "10.1101/2023.11.28.569048",
]

results = []
for doi in preprint_dois:
    # Get preprint metadata
    r_meta = requests.get(f"{BASE}/details/biorxiv/{doi}")
    meta = {}
    if r_meta.ok and r_meta.json().get("collection"):
        art = r_meta.json()["collection"][-1]
        meta = {"title": art["title"], "category": art["category"],
                "preprint_date": art["date"]}

    # Check publication status
    r_pub = requests.get(f"{BASE}/publisher/biorxiv/{doi}")
    published = {}
    if r_pub.ok and r_pub.json().get("collection"):
        pub = r_pub.json()["collection"][0]
        published = {"journal": pub.get("published_journal"),
                     "pub_doi": pub.get("published_doi")}

    results.append({"preprint_doi": doi, **meta, **published})
    time.sleep(0.25)

df = pd.DataFrame(results)
print(df.to_string(index=False))
df.to_csv("preprint_publication_status.csv", index=False)

关键参数

参数模块默认值范围 / 选项作用
serverURL 路径必填"biorxiv"、"medrxiv"选择预印本服务平台
date_fromURL 路径必填"YYYY-MM-DD"日期范围的起始日期
date_toURL 路径必填"YYYY-MM-DD"日期范围的结束日期
cursorURL 路径00、100、200…分页偏移量(每页 100 条)
category筛选条件—例如,"bioinformatics"按类别名称子字符串匹配(后置筛选)
version—所有版本—API 返回所有版本;使用 [-1] 获取最新版本

最佳实践

  1. 始终使用最后一个元素获取最新版本:collection 数组按版本从旧到新排序。使用 collection[-1] 获取预印本的最新版本。

  2. 按类别进行后置筛选:API 不支持原生按类别筛选;请获取指定日期范围内的所有预印本,然后在客户端使用 if category in article["category"].lower() 进行筛选。

  3. 尊重服务端资源:单独查询 DOI 时,每次查询之间添加 time.sleep(0.2);避免向 API 发送大量请求。

  4. 与 PubMed 交叉核对:publisher 端点会显示预印本的发表时间;使用 pubmed-database 获取经过同行评审的完整文章元数据。

  5. 处理缺失的摘要:有些预印本的 abstract 字段为空。请始终使用 art.get("abstract", "") or "No abstract available" 进行保护。

常见操作示例

操作示例:下载预印本 PDF(适应 Cloudflare)

适用场景:获取 bioRxiv 预印本的全文 PDF。注意:截至 2026 年,www.biorxiv.org 前置了 Cloudflare 反机器人验证机制——即使使用 Session 并预先访问着陆页,直接调用 requests.get(..., headers={"User-Agent": "Mozilla/5.0"}) 也会持续返回 HTTP 403(“Just a moment...”)。以下模式会先尝试使用逼真的浏览器标头尽力下载;如果被拦截,则回退到 EuropePMC 获取元数据。

import requests

def download_biorxiv_pdf(doi, out_path=None):
    """Best-effort PDF download. If Cloudflare blocks, return False so the caller
    can fall back to EuropePMC metadata or open the landing page in a browser."""
    pdf_url = f"https://www.biorxiv.org/content/{doi}.full.pdf"
    s = requests.Session()
    s.headers.update({
        "User-Agent": ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
                       "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,application/pdf,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
    })
    # Warm up the landing page first (sometimes lets Cloudflare's "trust" cookie set)
    s.get(f"https://www.biorxiv.org/content/{doi}v1", timeout=30)
    r = s.get(pdf_url, timeout=60)
    if r.ok and r.content.startswith(b"%PDF"):
        out = out_path or f"{doi.replace('/', '_')}.pdf"
        with open(out, "wb") as f:
            f.write(r.content)
        print(f"Downloaded {out} ({len(r.content)//1024} KB)")
        return True
    print(f"PDF blocked (HTTP {r.status_code}); falling back to metadata-only via EuropePMC")
    return False

def europepmc_metadata(doi):
    """Fetch preprint metadata via EuropePMC when bioRxiv PDF is blocked.
    EuropePMC indexes bioRxiv as source 'PPR' and exposes a stable landing URL."""
    r = requests.get("https://www.ebi.ac.uk/europepmc/webservices/rest/search",
                     params={"query": f"DOI:{doi}", "format": "json"}, timeout=30)
    r.raise_for_status()
    hits = r.json().get("resultList", {}).get("result", [])
    if not hits:
        return None
    h = hits[0]
    return {
        "source": h.get("source"),                      # 'PPR' for preprints
        "epmc_id": h.get("id"),                         # e.g. 'PPR860608'
        "title": h.get("title"),
        "landing_url": f"https://europepmc.org/article/{h.get('source')}/{h.get('id')}",
    }

doi = "10.1101/2024.05.28.596311"
if not download_biorxiv_pdf(doi):
    meta = europepmc_metadata(doi)
    print(f"  EuropePMC landing: {meta['landing_url']}")
    print(f"  Title: {meta['title'][:80]}")
操作示例:按类别统计预印本数量

适用场景:分析指定时间范围内 bioRxiv 各类别预印本的分布情况。

import requests, pandas as pd
from collections import Counter

r = requests.get("https://api.biorxiv.org/details/biorxiv/2024-01-01/2024-01-07/0")
data = r.json()
total = int(data["messages"][0]["total"])  # cast: API returns total as a string

# Fetch all pages
all_articles = data["collection"]
for cursor in range(100, min(total, 1000), 100):
    r2 = requests.get(f"https://api.biorxiv.org/details/biorxiv/2024-01-01/2024-01-07/{cursor}")
    all_articles.extend(r2.json()["collection"])

counts = Counter(a["category"] for a in all_articles)
df = pd.DataFrame(counts.most_common(), columns=["category", "count"])
print(df.head(10).to_string(index=False))
操作示例:检查预印本是否已发表

适用场景:快速检查单篇预印本的发表情况。

import requests

doi = "10.1101/2024.05.28.596311"
r = requests.get(f"https://api.biorxiv.org/publisher/biorxiv/{doi}")
collection = r.json().get("collection", [])
if collection:
    print(f"Published: {collection[0]['published_journal']} | DOI: {collection[0]['published_doi']}")
else:
    print("Not published or not tracked")

故障排查

问题原因解决方案
collection 为空未找到 DOI,或日期范围内没有结果核实 DOI 格式(以 10.1101/ 开头);检查日期范围
结果中存在重复预印本返回了多个版本按 DOI 去重:df.drop_duplicates(subset='doi', keep='last')
缺少摘要字段有些预印本没有结构化摘要使用 art.get("abstract", "") or "N/A" 进行保护
total 计数与检索数量不一致分页期间新增了预印本接受近似总数;预印本会持续添加
PDF 下载被拦截(HTTP 403 “Just a moment...”)www.biorxiv.org/.../*.full.pdf 上的 Cloudflare 反机器人机制(仅使用 Mozilla/5.0 UA 无法绕过,使用 Session 加预先访问着陆页也不行)尝试使用 Session 加预热的操作示例;如果仍被拦截,则回退到 EuropePMC(source=PPR)获取元数据,或在浏览器中从 bioRxiv 着陆页手动获取 PDF
cursor >= total 始终不成立;循环无限运行data['messages'][0]['total'] 返回的是字符串(例如 '1119');int_cursor >= str_total 会引发 TypeError 或进行字典序比较显式转换类型:在每个分页循环中使用 int(data["messages"][0]["total"])
特定 DOI 对应的 collection 为空该 DOI 无法解析为真实预印本(例如伪造的占位符,如 2023.01.01.000001,或已过期/撤回的 DOI)先在 https://www.biorxiv.org/content/{doi}v1 上核实 DOI;日期范围列表中的近期 DOI 是最可靠的示例
大日期范围的分页速度较慢预印本数量较多在繁忙时段使用更短的时间窗口(3–7 天)

相关技能

  • pubmed-database — 同行评审的生物医学文献,可用于核实预印本的已发表版本
  • openalex-database — 范围更广的学术索引,索引延迟后也会收录 bioRxiv 内容
  • literature-review — 将预印本纳入系统综述的指南
  • scientific-brainstorming — 将预印本提醒用作生成假设的输入

参考资料

评论

支持 Markdown