关于 protocolsio-integration
这是面向生命科学研究者和实验室自动化开发者的 protocols.io REST API 使用技能,用于搜索并读取实验方案。它还介绍方案版本、试剂与材料提取,以及需要 OAuth2 的私有内容和编辑操作。
主要功能
- 01按关键词、技术或 DOI 搜索方案
- 02读取完整步骤与实验材料
- 03检索方案版本历史
- 04浏览方案分类
- 05通过 OAuth2 访问私有方案及编辑
适用场景
- 01为实验方法查找可引用的方案
- 02提取步骤和试剂以构建自动化流程
- 03核对方案版本及对应 DOI
- 04查找使用特定试剂或仪器的方案
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill protocolsio-integration安装后在 Claude Code 中输入/protocolsio-integration确认已加载。
详细介绍
protocols.io 集成
概述
protocols.io 是生命科学领域领先的实验方案库,收录了 90,000 多个开放获取实验方案,涵盖分子生物学、细胞生物学、生物信息学、临床研究和实验室自动化。REST API 提供对方案搜索、完整方案获取(步骤、试剂、材料、设备)、方案版本管理、工作区管理以及方案发布的程序化访问。公开方案可免费访问;访问私有方案或创建/编辑方案需要身份验证(OAuth2 令牌)。
适用场景
- 按关键词、技术或期刊文章 DOI 搜索经过验证的湿实验方案
- 获取方案的完整分步内容(试剂、时间、用量、备注),用于自动化或分析
- 查找与特定试剂、试剂盒或仪器相关的方案
- 通过程序化提取方案步骤和试剂列表,构建实验室自动化工作流
- 验证方案版本,并为方法部分引用正确的 DOI
- 寻找社区验证的方案,作为专有方法的替代方案
- 搭配
opentrons-protocol-api或benchling-integration使用,在自动化工作流中实施下载的方案
先决条件
- Python 包:
requests、pandas - 数据要求:方案关键词、DOI 或 protocols.io 方案 ID
- 环境:需要互联网连接;公开方案:无需身份验证;私有方案:需要从 https://www.protocols.io/developers 获取 OAuth2 令牌
- 速率限制:公开 API 每秒 10 个请求;访问公开方案时允许未认证请求
pip install requests pandas
# For private protocol access or publishing:
# Register at https://www.protocols.io/developers to obtain an API token
快速入门
import requests
BASE = "https://www.protocols.io/api/v4"
# For public protocols, no token needed (but add for higher rate limits)
HEADERS = {"Authorization": "Bearer YOUR_TOKEN_HERE"} # Optional for public
# Search for CRISPR protocols
r = requests.get(f"{BASE}/protocols",
params={"q": "CRISPR guide RNA design", "order_field": "views",
"page_size": 5},
headers=HEADERS)
r.raise_for_status()
data = r.json()
print(f"Total CRISPR protocols: {data['pagination']['total_results']}")
for p in data["items"][:3]:
print(f"\n {p['title']}")
print(f" DOI: {p.get('doi')} | Views: {p.get('stats', {}).get('number_of_views')}")
print(f" Authors: {', '.join(a['name'] for a in p.get('creators', [])[:3])}")
核心 API
查询 1:搜索方案
按关键词、技术或全文搜索 protocols.io 公共库。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def search_protocols(query, page_size=20, order_field="relevance", category_id=None):
params = {"q": query, "page_size": page_size, "order_field": order_field}
if category_id:
params["filter[categories_ids][]"] = category_id
r = requests.get(f"{BASE}/protocols", params=params)
r.raise_for_status()
return r.json()
data = search_protocols("RNA extraction tissue", page_size=10, order_field="views")
total = data["pagination"]["total_results"]
print(f"RNA extraction protocols: {total}")
rows = []
for p in data["items"][:10]:
rows.append({
"id": p.get("id"),
"title": p.get("title"),
"doi": p.get("doi"),
"views": p.get("stats", {}).get("number_of_views", 0),
"created": p.get("created_on"),
"category": p.get("categories", [{}])[0].get("name", "n/a"),
})
df = pd.DataFrame(rows).sort_values("views", ascending=False)
print(df.to_string(index=False))
# Search with category filter (get category IDs from /categories endpoint)
data_pcr = search_protocols("qPCR primer design", order_field="views")
print(f"\nqPCR protocols: {data_pcr['pagination']['total_results']}")
for p in data_pcr["items"][:3]:
print(f" {p['title'][:70]} (DOI: {p.get('doi', 'n/a')})")
查询 2:获取完整方案内容
获取包含步骤、试剂、材料和设备的完整方案。
import requests
BASE = "https://www.protocols.io/api/v4"
def get_protocol(protocol_id):
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
return r.json()
# Retrieve protocol by ID (from search results or DOI lookup)
protocol_id = 45979 # Example: a public protocol
data = get_protocol(protocol_id)
protocol = data.get("payload", data) # Handle API response structure
print(f"Title: {protocol.get('title')}")
print(f"DOI: {protocol.get('doi')}")
print(f"Authors: {', '.join(a['name'] for a in protocol.get('creators', []))}")
print(f"Steps: {len(protocol.get('steps', []))}")
print(f"Materials: {len(protocol.get('materials', []))}")
print(f"Abstract: {protocol.get('description', '')[:200]}")
# Parse protocol steps
protocol_steps = protocol.get("steps", [])
for i, step in enumerate(protocol_steps[:5], 1):
step_desc = step.get("description", "")
duration = step.get("duration", {})
print(f"\nStep {i}: {step_desc[:120]}")
if duration:
print(f" Duration: {duration.get('duration')} {duration.get('unit_label', '')}")
查询 3:按 DOI 获取方案
使用 DOI 获取方案,以便根据引用信息准确检索。
import requests, json
BASE = "https://www.protocols.io/api/v4"
def get_protocol_by_doi(doi):
"""Retrieve protocol using its DOI."""
# URL-encode the DOI for the query
r = requests.get(f"{BASE}/protocols",
params={"q": doi, "page_size": 5})
r.raise_for_status()
items = r.json()["items"]
for item in items:
if item.get("doi") == doi:
return item
return None
doi = "10.17504/protocols.io.bvb3n2qn" # Example protocols.io DOI
protocol = get_protocol_by_doi(doi)
if protocol:
print(f"Found: {protocol['title']}")
print(f" ID: {protocol['id']}")
print(f" Version: {protocol.get('version_id')}")
查询 4:提取试剂和材料
从已获取的方案中解析材料清单。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def get_reagents(protocol_id):
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
data = r.json()
protocol = data.get("payload", data)
return protocol.get("materials", [])
# Get reagents list
materials = get_reagents(45979) # Example protocol ID
print(f"Materials ({len(materials)} items):")
rows = []
for m in materials[:10]:
rows.append({
"name": m.get("name"),
"quantity": m.get("quantity"),
"unit": m.get("unit", {}).get("name", ""),
"supplier": m.get("supplier", {}).get("name", ""),
"catalog": m.get("sku"),
})
df = pd.DataFrame(rows)
print(df.to_string(index=False))
查询 5:浏览方案类别
列出可用的方案类别,以便进行有针对性的搜索。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
r = requests.get(f"{BASE}/categories")
r.raise_for_status()
data = r.json()
categories = data.get("items", data.get("payload", []))
print(f"protocols.io categories: {len(categories)}")
df = pd.DataFrame(categories)[["id", "name"]].head(20)
print(df.to_string(index=False))
查询 6:列出方案版本
获取方案版本历史,以跟踪更新。
import requests
BASE = "https://www.protocols.io/api/v4"
def get_protocol_versions(protocol_id):
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
protocol = r.json().get("payload", r.json())
return {
"title": protocol.get("title"),
"version": protocol.get("version_id"),
"published": protocol.get("published_on"),
"doi": protocol.get("doi"),
"parent_doi": protocol.get("parent_publication", {}).get("doi"),
}
info = get_protocol_versions(45979)
for k, v in info.items():
print(f" {k}: {v}")
核心概念
方案 DOI 和版本管理
每个已发布的 protocols.io 方案都有一个可引用的 DOI(格式:10.17504/protocols.io.XXXXX)。方案更新时会创建一个新版本,并分配新的 DOI,而原始 DOI 仍然有效。为确保可重复性,请始终在方法部分引用特定版本的 DOI。
API 身份验证
公开方案无需身份验证即可访问。以下操作需要 OAuth2 Bearer 令牌:访问私有方案、管理工作区、创建/编辑方案以及进行用户专属查询。请通过 https://www.protocols.io/developers 获取令牌。
常见工作流
工作流 1:方案发现与比较
目标:搜索符合某项技术的方案,对其进行比较,并选择最适合改编的方案。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def search_and_rank(query, top_n=20):
"""Search protocols and return ranked by views + forks."""
r = requests.get(f"{BASE}/protocols",
params={"q": query, "page_size": top_n, "order_field": "views"})
r.raise_for_status()
data = r.json()
rows = []
for p in data["items"]:
stats = p.get("stats", {})
rows.append({
"id": p.get("id"),
"title": p.get("title"),
"doi": p.get("doi"),
"views": stats.get("number_of_views", 0),
"forks": stats.get("number_of_forks", 0),
"steps": p.get("number_of_steps"),
"created": p.get("created_on")[:10] if p.get("created_on") else "n/a",
"category": p.get("categories", [{}])[0].get("name", "n/a"),
})
df = pd.DataFrame(rows)
df["popularity_score"] = df["views"] * 0.7 + df["forks"] * 0.3 * 100
return df.sort_values("popularity_score", ascending=False)
# Compare western blotting protocols
df = search_and_rank("western blot protein detection", top_n=15)
df.to_csv("western_blot_protocols.csv", index=False)
print("Top western blot protocols:")
print(df[["title", "views", "forks", "steps"]].head(8).to_string(index=False))
工作流 2:为自动化提取方案步骤
目标:提取方案步骤、时间和试剂用量,以用于后续自动化脚本编写。
import requests, pandas as pd
BASE = "https://www.protocols.io/api/v4"
def extract_protocol_steps(protocol_id):
"""Extract structured step data from a protocol."""
r = requests.get(f"{BASE}/protocols/{protocol_id}")
r.raise_for_status()
protocol = r.json().get("payload", r.json())
steps = []
for i, step in enumerate(protocol.get("steps", []), 1):
duration = step.get("duration", {})
steps.append({
"step_number": i,
"description": step.get("description", ""),
"duration_value": duration.get("duration"),
"duration_unit": duration.get("unit_label", ""),
"temperature": step.get("temperature", {}).get("value"),
"temp_unit": step.get("temperature", {}).get("unit_label", ""),
})
materials = [{
"name": m.get("name"),
"quantity": m.get("quantity"),
"unit": m.get("unit", {}).get("name", ""),
} for m in protocol.get("materials", [])]
return {
"title": protocol.get("title"),
"doi": protocol.get("doi"),
"steps": pd.DataFrame(steps),
"materials": pd.DataFrame(materials),
}
result = extract_protocol_steps(45979)
print(f"Protocol: {result['title']}")
print(f"\nSteps ({len(result['steps'])}):")
print(result["steps"][["step_number", "description", "duration_value", "duration_unit"]].head(5).to_string(index=False))
print(f"\nMaterials ({len(result['materials'])}):")
print(result["materials"].head(5).to_string(index=False))
# Export for automation
result["steps"].to_csv("protocol_steps.csv", index=False)
result["materials"].to_csv("protocol_materials.csv", index=False)
关键参数
| 参数 | 模块 | 默认值 | 范围/选项 | 作用 |
|---|---|---|---|---|
q | 搜索 | — | 关键词字符串 | 全文搜索查询 |
order_field | 搜索 | "relevance" | "relevance"、"views"、"date"、"activity" | 结果排序方式 |
page_size | 搜索 | 10 | 1–50 | 每页结果数 |
page_id | 搜索 | 1 | 整数 | 分页页码 |
filter[categories_ids][] | 搜索 | — | 类别整数 ID | 按方案类别筛选 |
| Protocol ID | 获取 | 必填 | 整数 | 要获取的特定方案 |
最佳实践
-
按浏览量排序以筛选优质内容:搜索经过充分验证的方案时,使用
order_field=views,因为浏览量高的方案已由许多团队测试过。 -
务必引用具体的 DOI:protocols.io 的 DOI 带有版本信息;在方法部分引用确切版本的 DOI(而不只是方案标题),以便读者复现你的确切方案。
-
使用前检查许可:所有公开的 protocols.io 方案默认采用 CC-BY 4.0。商业用途需要检查各方案的具体许可。
-
提取材料清单以订购试剂:材料 API 会返回目录编号和供应商名称,可据此直接生成采购清单。
-
保存方案 ID 和 DOI 以确保可复现性:为项目选择方案时,同时记录整数 ID(用于 API 访问)和 DOI(用于稳定引用)。
常见用法
用法:按试剂名称搜索
适用场景:查找使用特定商业试剂盒或试剂的方案。
import requests
r = requests.get("https://www.protocols.io/api/v4/protocols",
params={"q": "RNeasy Mini Kit RNA extraction", "page_size": 5,
"order_field": "views"})
data = r.json()
print(f"Protocols using RNeasy: {data['pagination']['total_results']}")
for p in data["items"][:3]:
print(f" {p['title'][:70]} ({p.get('doi', 'n/a')})")
用法:获取方法部分所需的方案引文
适用场景:为方法部分生成引文。
import requests
protocol_id = 45979
r = requests.get(f"https://www.protocols.io/api/v4/protocols/{protocol_id}")
p = r.json().get("payload", r.json())
authors = "; ".join(a["name"] for a in p.get("creators", [])[:3])
print(f"Citation: {authors} ({p.get('created_on', '')[:4]}). ")
print(f"{p.get('title')}. protocols.io. https://doi.org/{p.get('doi')}")
用法:查找分叉数最多的方案
适用场景:找出广泛改编的方案(分叉数越高,表示改编的实验室越多)。
import requests, pandas as pd
r = requests.get("https://www.protocols.io/api/v4/protocols",
params={"q": "ChIP-seq chromatin", "page_size": 20})
data = r.json()
df = pd.DataFrame([{
"title": p["title"][:60],
"forks": p.get("stats", {}).get("number_of_forks", 0),
"views": p.get("stats", {}).get("number_of_views", 0),
} for p in data["items"]])
print(df.sort_values("forks", ascending=False).head(5).to_string(index=False))
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
搜索结果中的 items 为空 | 查询过于具体或没有匹配项 | 扩大查询范围;移除特殊字符 |
访问方案时出现 HTTP 401 | 未经身份验证的私有方案 | 获取 OAuth2 令牌;访问公开方案不需要身份验证 |
| 方案步骤的描述为空 | 方案使用了富文本格式 | 使用 re.sub(r'<[^>]+>', '', text) 从 description 中移除 HTML 标签 |
materials 列表为空 | 方案没有结构化材料信息 | 材料可能以纯文本形式写在步骤描述中 |
| DOI 查询返回了错误的方案 | 匹配了相似标题,而不是 DOI | 精确比较 DOI 字段;使用字符串相等检查 if item.get("doi") == doi |
| 触发速率限制错误 | 每秒请求超过 10 次 | 在请求之间添加 time.sleep(0.15) |
相关技能
opentrons-protocol-api— 使用通过此技能提取的步骤,在 Opentrons 液体处理机器人上执行方案benchling-integration— 在 Benchling ELN 中存储检索到的方案并追踪试剂scientific-manuscript-writing— 在方法部分使用 protocols.io DOI 正确引用方案
参考资料
- protocols.io API 文档 — 官方 REST API 参考
- protocols.io 平台 — 公开方案库和搜索功能
- protocols.io 引用指南 — 如何在出版物中引用 protocols.io
- Teytelman 等人(2016),《Nature Methods》 — protocols.io 平台介绍论文