mcpField
G
gene-database

gene-database

github.com/jaechang-hits数据与数据库38438 次安装1 周前更新
代码仓库

关于 gene-database

gene-database 是通过 E-utilities 和 NCBI Datasets API 查询 NCBI Gene 的技能,适用于研究人员和生物信息学工作流。它可解析基因标识符,并获取整理过的注释、序列登录号、GO 术语和直系同源基因。

主要功能

  1. 01按符号、名称或功能搜索基因
  2. 02将符号映射为 NCBI Gene ID
  3. 03获取摘要和完整基因记录
  4. 04提取 RefSeq 登录号和 GO 注释
  5. 05查找跨物种直系同源基因

适用场景

  1. 01将基因别名解析为官方符号
  2. 02构建基因注释表
  3. 03获取基因的 RefSeq 登录号
  4. 04查找不同物种间的直系同源基因

安装

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

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

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

详细介绍

NCBI Gene 数据库

概述

NCBI Gene 是以基因为中心的信息权威整理数据库,涵盖数十万个分类群中的 100 多万个基因。每条基因记录都包含官方符号、别名、全名、功能摘要、基因组坐标(GRCh38/GRCh37)、RefSeq 登录号、GO 注释、相互作用伙伴以及相关数据库的链接。可通过 E-utilities REST API 免费访问(无需 API 密钥,但建议使用)。

适用场景

  • 将基因别名和同义词解析为当前官方 HGNC/NCBI 符号
  • 获取基因符号对应的 NCBI Gene ID(整数),用于下游 API 调用(例如 dbSNP、ClinVar、GEO)
  • 以编程方式检索整理后的基因摘要和功能描述
  • 获取与基因相关的 RefSeq mRNA(NM_)和蛋白质(NP_)登录号
  • 查询 GO 功能注释(生物过程、分子功能、细胞组分)
  • 通过 NCBI Datasets v2 orthologs 端点查找跨物种直系同源基因(旧版 E-utilities gene_gene_homolog 随 HomoloGene 于 2019 年停用)
  • 如需跨条件的表达谱,请使用 geo-database;如需变异注释,请使用 clinvar-database 或 ensembl-database

先决条件

  • Python 包:requests、xml.etree.ElementTree(标准库)、pandas(可选)
  • 数据要求:基因符号、NCBI Gene ID 或 tax ID
  • 环境:需要互联网连接和 NCBI 电子邮箱(设置 email 参数)
  • 速率限制:未认证时为每秒 3 次请求;使用免费的 NCBI API 密钥时为每秒 10 次请求
pip install requests pandas

快速开始

import requests

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def gene_search(query, retmax=5):
    r = requests.get(f"{BASE}/esearch.fcgi",
                     params={"db": "gene", "term": query,
                             "retmax": retmax, "retmode": "json", "email": EMAIL})
    r.raise_for_status()
    return r.json()["esearchresult"]["idlist"]

# Find human BRCA1 gene ID
ids = gene_search("BRCA1[sym] AND Homo sapiens[orgn]")
print(f"Gene IDs for BRCA1: {ids}")  # → ['672']

核心 API

查询 1:按符号、名称或功能搜索

使用带字段标签的 ESearch 进行精确查询。

import requests

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

# Exact symbol match for human gene
r = requests.get(f"{BASE}/esearch.fcgi",
                 params={"db": "gene", "email": EMAIL, "retmode": "json",
                         "term": "TP53[sym] AND Homo sapiens[orgn] AND alive[prop]"})
ids = r.json()["esearchresult"]["idlist"]
print(f"TP53 Gene ID: {ids}")  # → ['7157']
# Search by function keyword
r = requests.get(f"{BASE}/esearch.fcgi",
                 params={"db": "gene", "email": EMAIL, "retmode": "json",
                         "term": "CRISPR[title] AND Homo sapiens[orgn]", "retmax": 5})
ids = r.json()["esearchresult"]["idlist"]
print(f"CRISPR-related gene IDs: {ids}")
查询 2:获取基因摘要(JSON/ESummary)

检索一组 Gene ID 的关键元数据字段。

import requests

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def esummary_gene(gene_ids):
    r = requests.post(f"{BASE}/esummary.fcgi",
                      data={"db": "gene", "id": ",".join(gene_ids),
                            "retmode": "json", "email": EMAIL})
    r.raise_for_status()
    return r.json()["result"]

result = esummary_gene(["672", "675", "7157"])  # BRCA1, BRCA2, TP53

for uid in result.get("uids", []):
    g = result[uid]
    print(f"\n{g.get('name')} (ID {uid})")
    print(f"  Official symbol : {g.get('nomenclaturesymbol', g.get('name'))}")
    print(f"  Chr location    : {g.get('maplocation')}")
    print(f"  Summary (first 100): {g.get('summary', '')[:100]}...")
    print(f"  Aliases: {g.get('otheraliases', 'none')}")
查询 3:获取完整基因记录(XML)

以 XML 格式检索完整基因记录,其中包含 RefSeq 登录号、GO 术语和相互作用数据。

import requests
import xml.etree.ElementTree as ET

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def efetch_gene_xml(gene_id):
    r = requests.get(f"{BASE}/efetch.fcgi",
                     params={"db": "gene", "id": gene_id,
                             "rettype": "gene_table", "retmode": "text", "email": EMAIL})
    r.raise_for_status()
    return r.text

# Get gene table (tab-delimited overview)
table = efetch_gene_xml("672")
print(table[:500])
# XML for RefSeq accession extraction
r = requests.get(f"{BASE}/efetch.fcgi",
                 params={"db": "gene", "id": "672",
                         "rettype": "xml", "retmode": "xml", "email": EMAIL})
root = ET.fromstring(r.text)

# Extract RefSeq mRNA accessions
for ref in root.iter("Gene-commentary"):
    acc = ref.find("Gene-commentary_accession")
    ver = ref.find("Gene-commentary_version")
    typ = ref.find("Gene-commentary_type")
    if acc is not None and acc.text and acc.text.startswith("NM_"):
        print(f"RefSeq mRNA: {acc.text}.{ver.text if ver is not None else ''}")
查询 4:批量将符号映射到 ID

高效地将一组基因符号映射到 NCBI Gene ID。

import requests, time

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def symbols_to_ids(symbols, organism="Homo sapiens"):
    """Map gene symbols to NCBI Gene IDs. Returns dict {symbol: gene_id}."""
    mapping = {}
    for sym in symbols:
        r = requests.get(f"{BASE}/esearch.fcgi",
                         params={"db": "gene", "email": EMAIL, "retmode": "json",
                                 "term": f"{sym}[sym] AND {organism}[orgn] AND alive[prop]"})
        ids = r.json()["esearchresult"]["idlist"]
        mapping[sym] = ids[0] if ids else None
        time.sleep(0.1)
    return mapping

genes = ["EGFR", "KRAS", "BRAF", "PIK3CA", "PTEN"]
id_map = symbols_to_ids(genes)
for sym, gid in id_map.items():
    print(f"{sym:10s} → Gene ID {gid}")
查询 5:获取 GO 注释

从基因 XML 记录中解析 GO 术语。

import requests
import xml.etree.ElementTree as ET

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

r = requests.get(f"{BASE}/efetch.fcgi",
                 params={"db": "gene", "id": "7157",
                         "rettype": "xml", "retmode": "xml", "email": EMAIL})
root = ET.fromstring(r.text)

# Extract GO annotations
go_terms = []
for ref in root.iter("Gene-commentary"):
    heading = ref.find("Gene-commentary_heading")
    label = ref.find("Gene-commentary_label")
    if heading is not None and "Gene Ontology" in heading.text:
        if label is not None:
            go_terms.append(label.text)

print(f"TP53 GO terms ({len(go_terms)} found):")
for term in go_terms[:10]:
    print(f"  {term}")
查询 6:跨物种直系同源基因(NCBI Datasets v2)

查找跨物种直系同源基因。注意:旧版 E-utilities 链接 gene_gene_homolog 随 HomoloGene 于 2019 年停用;现代方案是 NCBI Datasets v2 REST API,它提供专用的 orthologs 端点。

import requests, time

DATASETS_BASE = "https://api.ncbi.nlm.nih.gov/datasets/v2"

def get_orthologs(gene_id, taxon_filter=None):
    """Return ortholog Gene reports for a given NCBI Gene ID.
    taxon_filter: optional tax_id (int) or list of tax_ids to narrow species."""
    params = {}
    if taxon_filter is not None:
        # tax_ids: human=9606, mouse=10090, rat=10116, zebrafish=7955, fly=7227
        ids = taxon_filter if isinstance(taxon_filter, (list, tuple)) else [taxon_filter]
        params["taxon_filter"] = [str(t) for t in ids]
    r = requests.get(f"{DATASETS_BASE}/gene/id/{gene_id}/orthologs",
                     params=params, timeout=30)
    r.raise_for_status()
    return r.json().get("reports", [])

# Mouse ortholog of human TP53 (Gene ID 7157)
reports = get_orthologs("7157", taxon_filter=10090)
for rep in reports[:5]:
    g = rep.get("gene", {})
    print(f"  {g.get('symbol'):8s} (tax {g.get('tax_id')}, gene_id {g.get('gene_id')}): "
          f"{g.get('description', '')[:60]}")
# Expect:  Trp53    (tax 10090, gene_id 22059): transformation related protein 53

time.sleep(0.34)
# All orthologs (every species in the orthology group)
all_orthologs = get_orthologs("7157")
print(f"\nTotal TP53 orthologs across species: {len(all_orthologs)}")

关键概念

NCBI Gene ID、HGNC ID 与 Ensembl ID

NCBI Gene ID 是按基因和生物体分配的整数(例如,人类 TP53 = 7157)。它们与 HGNC ID(例如 HGNC:11998)和 Ensembl ID(ENSG00000141510)不同。许多下游 NCBI 数据库(ClinVar、dbSNP、GEO)都在内部使用 NCBI Gene ID。

alive[prop] 过滤器

已停用基因的 NCBI Gene 记录具有 status=discontinued。在符号查询中务必添加 AND alive[prop],以排除已退役条目并避免检索过时数据。

常见工作流

工作流 1:构建基因注释表

目标:针对一组基因符号,检索 Gene ID、官方名称、染色体位置和描述。

import requests, time, pandas as pd

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

def search_gene(sym, organism="Homo sapiens"):
    r = requests.get(f"{BASE}/esearch.fcgi",
                     params={"db": "gene", "email": EMAIL, "retmode": "json",
                             "term": f"{sym}[sym] AND {organism}[orgn] AND alive[prop]"})
    ids = r.json()["esearchresult"]["idlist"]
    return ids[0] if ids else None

def batch_summary(gene_ids):
    r = requests.post(f"{BASE}/esummary.fcgi",
                      data={"db": "gene", "id": ",".join(gene_ids),
                            "retmode": "json", "email": EMAIL})
    return r.json()["result"]

symbols = ["BRCA1", "BRCA2", "TP53", "EGFR", "MYC", "KRAS", "PTEN"]

# Step 1: Symbol → Gene ID
id_map = {}
for sym in symbols:
    gid = search_gene(sym)
    id_map[sym] = gid
    time.sleep(0.12)

# Step 2: Batch summary
valid_ids = [v for v in id_map.values() if v]
result = batch_summary(valid_ids)

rows = []
sym_to_id = {v: k for k, v in id_map.items() if v}
for uid in result.get("uids", []):
    g = result[uid]
    rows.append({
        "symbol": sym_to_id.get(uid, g.get("name")),
        "gene_id": uid,
        "full_name": g.get("description"),
        "chr_location": g.get("maplocation"),
        "summary": g.get("summary", "")[:200],
    })

df = pd.DataFrame(rows)
df.to_csv("gene_annotations.csv", index=False)
print(df[["symbol", "gene_id", "full_name", "chr_location"]].to_string(index=False))
工作流 2:查找通路关键词对应的所有基因

目标:从 NCBI Gene 摘要字段中检索与某个生物学关键词相关的所有人类基因。

import requests, time, pandas as pd

EMAIL = "[email protected]"
BASE = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"

keyword = "DNA mismatch repair"
r = requests.get(f"{BASE}/esearch.fcgi",
                 params={"db": "gene", "email": EMAIL, "retmode": "json",
                         "retmax": 50,
                         "term": f"{keyword}[title/abstract] AND Homo sapiens[orgn] AND alive[prop]"})
ids = r.json()["esearchresult"]["idlist"]
print(f"Found {len(ids)} genes related to '{keyword}'")

# Fetch summaries
r2 = requests.post(f"{BASE}/esummary.fcgi",
                   data={"db": "gene", "id": ",".join(ids), "retmode": "json", "email": EMAIL})
result = r2.json()["result"]

rows = []
for uid in result.get("uids", []):
    g = result[uid]
    rows.append({"gene_id": uid, "symbol": g.get("name"),
                 "description": g.get("description"),
                 "location": g.get("maplocation")})

df = pd.DataFrame(rows)
print(df.to_string(index=False))
df.to_csv(f"{keyword.replace(' ', '_')}_genes.csv", index=False)

关键参数

参数模块默认值范围 / 选项作用
retmaxESearch201–10000返回的记录数上限
retmodeESearch/ESummary"xml""json"、"xml"响应格式
rettypeEFetch视情况而定"xml"、"gene_table"、"text"完整获取时的记录格式
[sym] 字段标签ESearch—基因符号仅匹配完全一致的官方符号
[orgn] 字段标签ESearch—生物名称或分类 ID按分类筛选
alive[prop]ESearch—布尔标记排除已停用的基因记录

最佳实践

  1. 始终添加 alive[prop]:数据库中仍保留已停用的基因记录。如果不使用此筛选条件,按符号搜索可能会返回过时记录。

  2. 在流水线中使用 Gene ID:下游 NCBI 数据库(ClinVar、dbSNP、GEO)接受 Gene ID;避免每次调用都按符号重新搜索。

  3. 使用 ESummary 获取元数据,使用 EFetch 获取完整记录:ESummary 会以 JSON 格式返回所有常用字段;只有在需要 RefSeq 登录号、GO 术语或相互作用链接时才需要 EFetch XML。

  4. 注册免费 API 密钥:在 https://www.ncbi.nlm.nih.gov/account/ 将速率限制提高 3 倍(3 → 10 req/s)。通过 api_key 参数传入。

  5. 使用 ESummary 批量查询:每次调用 ESummary 可 POST 最多 200 个 Gene ID,而不是逐个查询。

常用方案

方案:从 Gene ID 获取 RefSeq NM 登录号

适用场景:获取蛋白质编码基因的规范 mRNA 登录号。

import requests, re

EMAIL = "[email protected]"
GENE_ID = "672"  # BRCA1

r = requests.get(
    "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi",
    params={"db": "gene", "id": GENE_ID, "rettype": "gene_table",
            "retmode": "text", "email": EMAIL}
)
nm_accessions = re.findall(r"NM_\d+\.\d+", r.text)
print(f"RefSeq mRNA accessions: {list(set(nm_accessions))}")
方案:获取基因别名

适用场景:将旧版 / 别名符号解析为当前的 NCBI 官方符号。

import requests

EMAIL = "[email protected]"

# P53 is an alias for TP53
r = requests.get(
    "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi",
    params={"db": "gene", "email": EMAIL, "retmode": "json",
            "term": "p53[sym] AND Homo sapiens[orgn] AND alive[prop]"}
)
ids = r.json()["esearchresult"]["idlist"]

r2 = requests.post("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi",
                   data={"db": "gene", "id": ",".join(ids[:1]),
                         "retmode": "json", "email": EMAIL})
g = r2.json()["result"][ids[0]]
print(f"Official symbol : {g.get('nomenclaturesymbol', g.get('name'))}")
print(f"Other aliases   : {g.get('otheraliases')}")
print(f"Designations    : {g.get('otherdesignations', '')[:100]}")
方案:列出染色体上的所有基因

适用场景:获取特定人类染色体上的所有蛋白质编码基因。

import requests

EMAIL = "[email protected]"

r = requests.get(
    "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi",
    params={"db": "gene", "email": EMAIL, "retmode": "json", "retmax": 5,
            "term": "17[chr] AND Homo sapiens[orgn] AND protein coding[filter] AND alive[prop]"}
)
result = r.json()["esearchresult"]
print(f"Protein-coding genes on chr17: {result['count']} total")
print(f"Sample IDs: {result['idlist']}")

故障排查

问题原因解决方案
已知符号对应的 idlist 为空该符号是别名,而非官方名称使用 [gene name] 或 [title] 字段标签;通过 ESummary 检查别名
返回了错误物种缺少生物筛选条件添加 AND Homo sapiens[orgn] 或目标分类 ID(9606[taxid])
返回了已停用的基因缺少 alive[prop] 筛选条件在所有符号查询后追加 AND alive[prop]
HTTP 429 速率限制请求过多在调用之间添加 time.sleep(0.35);使用 NCBI API 密钥
ESummary 缺少 uids 键所有 ID 均无效或不存在检查 id 值是否为有效整数,而非空字符串
XML 解析错误罕见基因的 XML 格式错误将 ET.fromstring 包装在 try/except 中;使用 rettype=text 重试
ELink 返回的直系同源基因列表为空旧版 linkname=gene_gene_homolog 随 HomoloGene 于 2019 年停用改用 NCBI Datasets v2 /gene/id/{gene_id}/orthologs(查询 6)

相关技能

  • geo-database — 用于获取此处所找到基因的表达数据的 Gene Expression Omnibus
  • clinvar-database — 按 NCBI Gene ID 编入索引的临床变异数据
  • ensembl-database — 提供 VEP 和比较基因组学的补充基因注释
  • biopython-molecular-biology — Biopython Entrez 模块封装了 E-utilities,并提供类型化返回值

参考资料

评论

支持 Markdown