Use Bio.Entrez to access NCBI databases (e.g., PubMed/GenBank) for searching, fetching summaries, and downloading records when your workflow needs to call the NCBI E-utilities API over the network.
59
70%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./scientific-skills/Evidence Insight/biopython-entrez/SKILL.mdBio.Entrez: esearch, efetch, esummary, elink.config/task_config.json.python scripts/<task_name>.py.-- parameters; prefer config files.ensure_ascii=False for JSON output.biopython>=1.80The following example is a complete, runnable script that:
1) Create config/task_config.json:
{
"email": "your-email@example.com",
"api_key": "",
"db": "pubmed",
"term": "CRISPR Cas9 2020[PDAT]",
"retmax": 5,
"out_json": "outputs/pubmed_summaries.json"
}2) Create scripts/pubmed_summaries.py:
import json
import os
import time
from typing import Any, Dict, List
from Bio import Entrez
def load_config(path: str) -> Dict[str, Any]:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
def ensure_parent_dir(path: str) -> None:
parent = os.path.dirname(path)
if parent:
os.makedirs(parent, exist_ok=True)
def main() -> None:
cfg = load_config("config/task_config.json")
Entrez.email = cfg["email"]
api_key = cfg.get("api_key") or ""
if api_key:
Entrez.api_key = api_key
db = cfg.get("db", "pubmed")
term = cfg["term"]
retmax = int(cfg.get("retmax", 20))
out_json = cfg.get("out_json", "outputs/pubmed_summaries.json")
# 1) ESearch: get IDs
with Entrez.esearch(db=db, term=term, retmax=retmax, usehistory="n") as handle:
search_result = Entrez.read(handle)
id_list: List[str] = search_result.get("IdList", [])
if not id_list:
ensure_parent_dir(out_json)
with open(out_json, "w", encoding="utf-8") as f:
json.dump({"query": term, "count": 0, "items": []}, f, ensure_ascii=False, indent=2)
return
# Be polite with NCBI: small delay (especially without API key)
time.sleep(0.34 if api_key else 0.5)
# 2) ESummary: get summaries for IDs
with Entrez.esummary(db=db, id=",".join(id_list), retmode="xml") as handle:
summary_result = Entrez.read(handle)
items = []
for docsum in summary_result:
items.append({
"id": str(docsum.get("Id", "")),
"title": str(docsum.get("Title", "")),
"pubdate": str(docsum.get("PubDate", "")),
"source": str(docsum.get("Source", "")),
"authors": [str(a.get("Name", "")) for a in docsum.get("AuthorList", [])],
})
payload = {
"query": term,
"count": len(items),
"items": items,
}
ensure_parent_dir(out_json)
with open(out_json, "w", encoding="utf-8") as f:
json.dump(payload, f, ensure_ascii=False, indent=2)
if __name__ == "__main__":
main()3) Run:
python scripts/pubmed_summaries.pyCore E-utilities mapping
ESearch: builds a query against an NCBI database and returns matching IDs (and optionally WebEnv/QueryKey for history-based batching).ESummary: returns lightweight document summaries for a list of IDs.EFetch: downloads full records (e.g., GenBank/FASTA/XML) for IDs; choose rettype/retmode based on the target database.ELink: discovers cross-database relationships (e.g., PubMed → PMC, Gene → Protein).Batching strategy
ESearch to obtain IDs, then call ESummary/EFetch in chunks (e.g., 100–500 IDs per request depending on payload size).usehistory="y" in ESearch and then fetch via WebEnv/QueryKey to avoid very long ID lists.Rate limiting and API key
Parsing
Entrez.read(handle) for structured parsing of XML responses into Python objects.handle.read() and write to disk with encoding="utf-8" where applicable.Configuration and I/O conventions
config/task_config.json as an intermediate artifact.python scripts/<task_name>.py.encoding="utf-8" for file I/O and use ensure_ascii=False for JSON outputs.Reference
references/databases.md for database notes and selection guidance.63c61d3
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.