批量从NCBI下载基因序列(进化版)

我:如何从NCBI批量下载数据?
鸨:找叶老啊!
我:打扰了!

之前在一篇文章中批量从NCBI下载指定物种中指定基因的序列介绍用NCBIBatch Entrez来批量下载序列,那种方法确实很方便,但是那种方法需要我们先通过NCBI网页端下载得到ID的列表,然后用列表来批量下载序列。如果我只有一个基因,那么这样下载起来还算方便,但是如果我有n个基因然后想下载n个基因在m个不同物种当中的序列,那么用这种方法我起码要先在NCBI中搜索n次,但是我不想搜索n次,我只想一步到位,即利用一个关键词就得到所有我需要的结果。
NCBI除了之前介绍的Batch Entrez之外,还有另外一个比较好用的api工具Entrez Programming Utilities,这个工具主要依托于perl,安装方法可参考但是今天我在perl上面尝试了一下,总是报错,恰好我在Biopython里面也有这个api的模块,于是干脆用Biopython
经过一番研究后,我发现可以这么做:

确认搜索语法

先在NCBI中搜索下,确认下搜索语法,比方说我想在NCBI的nucleotide数据库中搜索鸟类中的VAPA基因,那么我先在NCBI的搜索框中输入VAPA avian,然后可以看见在NCBI的右侧有搜索语法显示(VAPA[All Fields] AND ("Aves"[Organism] OR avian[All Fields])) AND biomol_mrna[PROP]

Esearch获得符合条件的数据列表

于是我们可以先用Esearch来搜索得到所有的id列表

1
2
3
4
5
from Bio import Entrez
Entrez.email = "history.user@example.com" # Always tell NCBI who you are
search_handle = Entrez.esearch(db="nucleotide",term="(VAPA[All Fields] AND (\"Aves\"[Organism] OR avian[All Fields])) AND biomol_mrna[PROP]",usehistory="y", idtype="acc")
search_results = Entrez.read(search_handle)
search_handle.close()

Esearch的功能是通过特定关键词在数据库中进行检索,返回符合条件的条目的列表。我们需要修改的地方是Entrez.email, Entrez.esearch里的term

利用EFetchEsearch的结果来下载序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#以下代码来自bioython文档
acc_list = search_results["IdList"] ###获得结果的id
count = int(search_results["Count"]) ###获得结果长度
webenv = search_results["WebEnv"] ###获得前一次搜索的WebEnv
query_key = search_results["QueryKey"] ###获得前一次搜索的QueryKey
try:
from urllib.error import HTTPError # for Python 3
except ImportError:
from urllib2 import HTTPError # for Python 2

batch_size = 3 ###设定每次下载的序列条数为3
#out_handle = open("orchid_rpl16.fasta", "w")
out_handle = open("VAPA.fasta", "w") ###修改输出文件名
for start in range(0, count, batch_size):
end = min(count, start+batch_size)
print("Going to download record %i to %i" % (start+1, end))
attempt = 0
while attempt < 3:
attempt += 1
try:
fetch_handle = Entrez.efetch(db="nucleotide",
rettype="fasta", retmode="text",
retstart=start, retmax=batch_size,
webenv=webenv, query_key=query_key,
idtype="acc")
except HTTPError as err:
if 500 <= err.code <= 599:
print("Received error from server %s" % err)
print("Attempt %i of 3" % attempt)
time.sleep(15)
else:
raise
data = fetch_handle.read()
fetch_handle.close()
out_handle.write(data)
out_handle.close()

在这里先解释一下,为什么要先通过ESearch来获得序列的编号列表,然后再通过EFetch来下载序列呢?首先ESearch只有搜索关键词并返回结果的id的功能,没有下载的功能,而EFetch只有根据id来下载序列的功能没有根据关键词term来下载序列的功能。
ESearch的主要参数有如下几个

参数 功能 是否必选?
db 指定数据库
term 搜索限定词
usehistory 当设定为y时,可以通过query_key和WebEnv来再次使用之前的数据
WebEnv 之前搜索(ESearch/EPost/ ELink)时返回的参数,用于保存之前的搜索结果,跟query_key一起使用
rettype 返回数据的格式,有uilist(默认)和count
retmode 返回数据的格式,有xml(默认)和json
idtype 返回数据为Accession number(s) 可选

EFetch主要参数有如下几个

参数 功能 是否必选?
db 指定数据库
id 要下载序列的id,在biopython中以列表形式存在
usehistory 当设定为y时,可以通过query_key和WebEnv来再次使用之前的数据
WebEnv 之前搜索(ESearch/EPost/ ELink)时返回的参数,用于保存之前的搜索结果,跟query_key一起使用
retmode 返回数据的格式,有xml(默认)和text
rettype 返回数据格式,有fasta,uilist等等,参考https://www.ncbi.nlm.nih.gov/books/NBK25499/#chapter4.EFetch
retmax 每次下载序列的数量,最多为10000,本次设定为3
retstart 每次下载时要下载的第一条序列对应id在id列表中的下标

运行以上代码后,就可以下载nucleotide数据库中所有鸟类的VAPA基因的mRNA序列,我检查了一下,用这个脚本下载下来的序列数量和序列与直接从NCBI网页端下载下来的相同。
另外我根据上面的代码写了一个脚本,现在已经上传到github

------本文结束欢迎留言(你的邮箱将不会被显示)------