访问 NCBI 的 Entrez 数据库
Entrez (https://www.ncbi.nlm.nih.gov/Web/Search/entrezfs.html) 是一个数据检索系统,允许用户访问 NCBI 的数据库,例如 PubMed、GenBank、GEO 等等。你可以从 Web 浏览器访问 Entrez 以手动输入查询,或者使用 Biopython 的 Bio.Entrez
模块以编程方式访问 Entrez。后者允许你在 Python 脚本中搜索 PubMed 或下载 GenBank 记录。
The Bio.Entrez
模块使用 Entrez 编程工具(也称为 EUtils),包含八个工具,这些工具在 NCBI 的页面上进行了详细描述 https://www.ncbi.nlm.nih.gov/books/NBK25501/。每个工具都对应于 Bio.Entrez
模块中的一个 Python 函数,如下面的部分所述。该模块确保使用正确的 URL 进行查询,并且遵循 NCBI 的负责任数据访问指南。
Entrez 编程工具返回的输出通常为 XML 格式。要解析此类输出,你有几个选择
使用
Bio.Entrez
的解析器将 XML 输出解析为 Python 对象;使用 Python 标准库中可用的 XML 解析器之一;
将 XML 输出作为原始文本读取,并通过字符串搜索和操作来解析它。
请参阅 Python 文档以了解 Python 标准库中 XML 解析器的描述。在这里,我们将讨论 Biopython 的 Bio.Entrez
模块中的解析器。此解析器可用于解析通过 Bio.Entrez
的以编程方式访问 Entrez 函数提供的数据,也可用于解析存储在文件中的 NCBI Entrez 的 XML 数据。在后一种情况下,应以二进制模式打开 XML 文件(例如 open("myfile.xml", "rb")
)才能使 Bio.Entrez
中的 XML 解析器正常工作。或者,你可以传递 XML 文件的文件名或路径,并让 Bio.Entrez
负责打开和关闭文件。
NCBI 使用 DTD(文档类型定义)文件来描述包含在 XML 文件中的信息的结构。NCBI 使用的大多数 DTD 文件都包含在 Biopython 发行版中。The Bio.Entrez
解析器在解析 NCBI Entrez 返回的 XML 文件时使用 DTD 文件。
有时,你可能会发现与特定 XML 文件关联的 DTD 文件在 Biopython 发行版中丢失。特别是,这可能发生在 NCBI 更新其 DTD 文件时。如果发生这种情况,Entrez.read
将显示一条警告消息,其中包含缺少的 DTD 文件的名称和 URL。解析器将继续通过互联网访问缺少的 DTD 文件,允许继续解析 XML 文件。但是,如果 DTD 文件在本地可用,解析器会快得多。为此,请从警告消息中的 URL 下载 DTD 文件,并将其放在包含其他 DTD 文件的目录 ...site-packages/Bio/Entrez/DTDs
中。如果你没有写访问此目录的权限,你也可以将 DTD 文件放在 ~/.biopython/Bio/Entrez/DTDs
中,其中 ~
表示你的主目录。由于此目录在目录 ...site-packages/Bio/Entrez/DTDs
之前读取,因此如果 ...site-packages/Bio/Entrez/DTDs
中的 DTD 文件过时,你也可以将更新版本的 DTD 文件放在那里。或者,如果你从源代码安装了 Biopython,你可以将 DTD 文件添加到源代码的 Bio/Entrez/DTDs
目录中,然后重新安装 Biopython。这将把新的 DTD 文件与其他 DTD 文件一起安装到正确的位置。
Entrez 编程工具还可以生成其他格式的输出,例如序列数据库的 Fasta 或 GenBank 文件格式,或者文献数据库的 MedLine 格式,在第 专门的解析器 节中讨论。
The Bio.Entrez
中用于以编程方式访问 Entrez 的函数以二进制格式或文本格式返回数据,具体取决于请求的数据类型。在大多数情况下,这些函数通过将从 NCBI Entrez 获得的数据解码为 Python 字符串(假设编码为 UTF-8)来以文本格式返回数据。但是,XML 数据以二进制格式返回。这样做的原因是编码在 XML 文档本身中指定,这意味着在我们开始解析文件之前,我们无法知道要使用的正确编码。因此,Bio.Entrez
的解析器接受二进制格式的数据,从 XML 中提取编码,并使用它将 XML 文档中的所有文本解码为 Python 字符串,确保所有文本(尤其是非英语语言的文本)被正确解释。这也是你应该以二进制模式打开 XML 文件的原因,如果你想使用 Bio.Entrez
的解析器来解析文件。
Entrez 指南
在使用 Biopython 访问 NCBI 的在线资源(通过 Bio.Entrez
或其他一些模块)之前,请阅读 NCBI 的 Entrez 用户要求。如果 NCBI 发现你滥用其系统,他们可以并会禁止你访问!
概括一下
对于超过 100 个请求的任何系列,请在周末或美国非高峰时间进行。这由你自己遵守。
使用 https://eutils.ncbi.nlm.nih.gov 地址,而不是标准 NCBI Web 地址。Biopython 使用此 Web 地址。
如果你使用的是 API 密钥,每秒最多可以进行 10 次查询,否则每秒最多可以进行 3 次查询。Biopython 会自动执行此操作。在参数列表中包含
api_key="MyAPIkey"
或将其设置为模块级变量>>> from Bio import Entrez >>> Entrez.api_key = "MyAPIkey"
使用可选的电子邮件参数,以便 NCBI 在出现问题时可以联系你。你可以将此显式设置为每个 Entrez 调用的参数(例如,在参数列表中包含
email="[email protected]"
),或者你可以设置全局电子邮件地址>>> from Bio import Entrez >>> Entrez.email = "[email protected]"
Bio.Entrez
然后将使用此电子邮件地址与每个 Entrez 调用。Theexample.com
地址是专门用于文档的保留域名(RFC 2606)。请不要使用随机电子邮件 - 最好不要提供任何电子邮件。电子邮件参数自 2010 年 6 月 1 日起成为强制性参数。如果使用过多,NCBI 将尝试在阻止访问 E-utilities 之前联系用户提供的电子邮件地址。如果你在某个更大的软件套件中使用 Biopython,请使用工具参数指定此软件套件。你可以将工具名称显式设置为每个 Entrez 调用的参数(例如,在参数列表中包含
tool="MyLocalScript"
),或者你可以设置全局工具名称>>> from Bio import Entrez >>> Entrez.tool = "MyLocalScript"
工具参数将默认为 Biopython。
对于大型查询,NCBI 还建议使用他们的会话历史功能(WebEnv 会话 cookie 字符串,请参阅第 使用历史记录和 WebEnv 节)。这只是稍微复杂一点。
总之,请合理使用你的使用级别。如果你计划下载大量数据,请考虑其他选择。例如,如果你想轻松访问所有人类基因,请考虑通过 FTP 获取每个染色体作为 GenBank 文件,并将它们导入到自己的 BioSQL 数据库中(请参阅第 BioSQL - 将序列存储在关系数据库中 节)。
EInfo:获取有关 Entrez 数据库的信息
EInfo 提供每个 NCBI 数据库的字段索引词计数、上次更新和可用链接。此外,你可以使用 EInfo 获取通过 Entrez 工具访问的所有数据库名称的列表
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.einfo()
>>> result = stream.read()
>>> stream.close()
变量 result
现在包含一个以 XML 格式表示的数据库列表
>>> print(result)
<?xml version="1.0"?>
<!DOCTYPE eInfoResult PUBLIC "-//NLM//DTD eInfoResult, 11 May 2002//EN"
"https://www.ncbi.nlm.nih.gov/entrez/query/DTD/eInfo_020511.dtd">
<eInfoResult>
<DbList>
<DbName>pubmed</DbName>
<DbName>protein</DbName>
<DbName>nucleotide</DbName>
<DbName>nuccore</DbName>
<DbName>nucgss</DbName>
<DbName>nucest</DbName>
<DbName>structure</DbName>
<DbName>genome</DbName>
<DbName>books</DbName>
<DbName>cancerchromosomes</DbName>
<DbName>cdd</DbName>
<DbName>gap</DbName>
<DbName>domains</DbName>
<DbName>gene</DbName>
<DbName>genomeprj</DbName>
<DbName>gensat</DbName>
<DbName>geo</DbName>
<DbName>gds</DbName>
<DbName>homologene</DbName>
<DbName>journals</DbName>
<DbName>mesh</DbName>
<DbName>ncbisearch</DbName>
<DbName>nlmcatalog</DbName>
<DbName>omia</DbName>
<DbName>omim</DbName>
<DbName>pmc</DbName>
<DbName>popset</DbName>
<DbName>probe</DbName>
<DbName>proteinclusters</DbName>
<DbName>pcassay</DbName>
<DbName>pccompound</DbName>
<DbName>pcsubstance</DbName>
<DbName>snp</DbName>
<DbName>taxonomy</DbName>
<DbName>toolkit</DbName>
<DbName>unigene</DbName>
<DbName>unists</DbName>
</DbList>
</eInfoResult>
由于这是一个相当简单的 XML 文件,我们可以通过字符串搜索来提取它包含的信息。使用 Bio.Entrez
的解析器,我们可以直接将此 XML 文件解析为 Python 对象。
>>> from Bio import Entrez
>>> stream = Entrez.einfo()
>>> record = Entrez.read(stream)
现在 record
是一个字典,只有一个键。
>>> record.keys()
dict_keys(['DbList'])
存储在此键中的值是上面 XML 中显示的数据库名称列表。
>>> record["DbList"]
['pubmed', 'protein', 'nucleotide', 'nuccore', 'nucgss', 'nucest',
'structure', 'genome', 'books', 'cancerchromosomes', 'cdd', 'gap',
'domains', 'gene', 'genomeprj', 'gensat', 'geo', 'gds', 'homologene',
'journals', 'mesh', 'ncbisearch', 'nlmcatalog', 'omia', 'omim', 'pmc',
'popset', 'probe', 'proteinclusters', 'pcassay', 'pccompound',
'pcsubstance', 'snp', 'taxonomy', 'toolkit', 'unigene', 'unists']
对于这些数据库中的每一个,我们可以再次使用 EInfo 来获取更多信息。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.einfo(db="pubmed")
>>> record = Entrez.read(stream)
>>> record["DbInfo"]["Description"]
'PubMed bibliographic record'
>>> record["DbInfo"]["Count"]
'17989604'
>>> record["DbInfo"]["LastUpdate"]
'2008/05/24 06:45'
尝试 record["DbInfo"].keys()
以获取存储在此记录中的其他信息。其中最有用的信息是用于 ESearch 的可能搜索字段列表。
>>> for field in record["DbInfo"]["FieldList"]:
... print("%(Name)s, %(FullName)s, %(Description)s" % field)
...
ALL, All Fields, All terms from all searchable fields
UID, UID, Unique number assigned to publication
FILT, Filter, Limits the records
TITL, Title, Words in title of publication
WORD, Text Word, Free text associated with publication
MESH, MeSH Terms, Medical Subject Headings assigned to publication
MAJR, MeSH Major Topic, MeSH terms of major importance to publication
AUTH, Author, Author(s) of publication
JOUR, Journal, Journal abbreviation of publication
AFFL, Affiliation, Author's institutional affiliation and address
...
这是一个很长的列表,但它间接地告诉您,对于 PubMed 数据库,您可以执行类似于 Jones[AUTH]
来搜索作者字段,或者 Sanger[AFFL]
来限制 Sanger 中心作者的搜索。这非常方便 - 尤其是当您不熟悉某个特定数据库时。
ESearch:搜索 Entrez 数据库
要搜索这些数据库中的任何一个,我们使用 Bio.Entrez.esearch()
。例如,让我们在 PubMed 中搜索标题中包含 Biopython 的出版物。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(db="pubmed", term="biopython[title]", retmax="40")
>>> record = Entrez.read(stream)
>>> "19304878" in record["IdList"]
True
>>> print(record["IdList"])
['22909249', '19304878']
在此输出中,您将看到 PubMed ID(包括 19304878,这是 Biopython 应用说明的 PMID),这些 ID 可以通过 EFetch 获取(见第 EFetch:从 Entrez 下载完整记录 节)。
您也可以使用 ESearch 搜索 GenBank。在这里,我们将对Cypripedioideae兰花中的matK基因进行快速搜索(见第 EInfo:获取有关 Entrez 数据库的信息 节,了解有关 EInfo 的信息,它可以帮助您找到可以在每个 Entrez 数据库中搜索的字段)。
>>> stream = Entrez.esearch(
... db="nucleotide", term="Cypripedioideae[Orgn] AND matK[Gene]", idtype="acc"
... )
>>> record = Entrez.read(stream)
>>> record["Count"]
'348'
>>> record["IdList"]
['JQ660909.1', 'JQ660908.1', 'JQ660907.1', 'JQ660906.1', ..., 'JQ660890.1']
每个 ID(JQ660909.1、JQ660908.1、JQ660907.1,…)都是一个 GenBank 标识符(登录号)。有关如何实际下载这些 GenBank 记录的信息,请参阅第 EFetch:从 Entrez 下载完整记录 节。
请注意,您可以使用 NCBI 分类单元标识符限制搜索,而不是像 Cypripedioideae[Orgn]
这样的物种名称,在这里将是 txid158330[Orgn]
。这在 ESearch 帮助页面上目前没有记录 - NCBI 在回复电子邮件查询时解释了这一点。您通常可以通过玩 Entrez 网络界面来推断搜索词的格式。例如,在基因组搜索中包含 complete[prop]
将限制在仅已完成的基因组。
作为最后一个例子,让我们获取计算期刊标题列表。
>>> stream = Entrez.esearch(db="nlmcatalog", term="computational[Journal]", retmax="20")
>>> record = Entrez.read(stream)
>>> print("{} computational journals found".format(record["Count"]))
117 computational Journals found
>>> print("The first 20 are\n{}".format(record["IdList"]))
['101660833', '101664671', '101661657', '101659814', '101657941',
'101653734', '101669877', '101649614', '101647835', '101639023',
'101627224', '101647801', '101589678', '101585369', '101645372',
'101586429', '101582229', '101574747', '101564639', '101671907']
同样,我们可以使用 EFetch 获取这些期刊 ID 的更多信息。
ESearch 具有许多有用的选项 - 有关更多信息,请参阅 ESearch 帮助页面。
EPost:上传标识符列表
EPost 上传一个 UI 列表,供后续搜索策略使用;有关更多信息,请参阅 EPost 帮助页面。它可以通过 Bio.Entrez.epost()
函数从 Biopython 中获得。
为了举例说明这有什么用,假设您有一长串要使用 EFetch 下载的 ID(可能是序列,可能是引用 - 任何东西)。当您使用 EFetch 发出请求时,您的 ID 列表、数据库等都会被转换成一个长 URL 发送到服务器。如果您的 ID 列表很长,那么这个 URL 就会变长,而长 URL 会断开(例如,某些代理无法很好地处理)。
相反,您可以将此分成两个步骤,首先使用 EPost 上传 ID 列表(这在内部使用“HTML post”,而不是“HTML get”,从而解决了长 URL 问题)。有了历史记录支持,您就可以参考这个长 ID 列表,并使用 EFetch 下载相关数据。
让我们看一个简单的例子,看看 EPost 如何工作 - 上传一些 PubMed 标识符。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> id_list = ["19304878", "18606172", "16403221", "16377612", "14871861", "14630660"]
>>> print(Entrez.epost("pubmed", id=",".join(id_list)).read())
<?xml version="1.0"?>
<!DOCTYPE ePostResult PUBLIC "-//NLM//DTD ePostResult, 11 May 2002//EN"
"https://www.ncbi.nlm.nih.gov/entrez/query/DTD/ePost_020511.dtd">
<ePostResult>
<QueryKey>1</QueryKey>
<WebEnv>NCID_01_206841095_130.14.22.101_9001_1242061629</WebEnv>
</ePostResult>
返回的 XML 包含两个重要的字符串,QueryKey
和 WebEnv
,它们共同定义了您的历史记录会话。您将提取这些值以供其他 Entrez 调用(如 EFetch)使用。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> id_list = ["19304878", "18606172", "16403221", "16377612", "14871861", "14630660"]
>>> search_results = Entrez.read(Entrez.epost("pubmed", id=",".join(id_list)))
>>> webenv = search_results["WebEnv"]
>>> query_key = search_results["QueryKey"]
第 使用历史记录和 WebEnv 节介绍了如何使用历史记录功能。
ESummary:从主 ID 中检索摘要
ESummary 从主 ID 列表中检索文档摘要(有关更多信息,请参阅 ESummary 帮助页面)。在 Biopython 中,ESummary 可用作 Bio.Entrez.esummary()
。使用上面的搜索结果,我们可以例如找出更多有关 ID 为 30367 的期刊的信息。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esummary(db="nlmcatalog", id="101660833")
>>> record = Entrez.read(stream)
>>> info = record[0]["TitleMainList"][0]
>>> print("Journal info\nid: {}\nTitle: {}".format(record[0]["Id"], info["Title"]))
Journal info
id: 101660833
Title: IEEE transactions on computational imaging.
EFetch:从 Entrez 下载完整记录
当您想要从 Entrez 中检索完整记录时,EFetch 就是您要使用的工具。它涵盖了多个可能的数据库,如主 EFetch 帮助页面 中所述。
对于大多数数据库,NCBI 支持多种不同的文件格式。使用 Bio.Entrez.efetch()
从 Entrez 中请求特定文件格式需要指定 rettype
和/或 retmode
可选参数。每种数据库类型的不同组合在 NCBI efetch 网页 上链接到的页面中进行了描述。
一个常见的用法是下载 FASTA 或 GenBank/GenPept 纯文本格式的序列(然后可以使用 Bio.SeqIO
解析,见第 从网络解析 GenBank 记录 和 EFetch:从 Entrez 下载完整记录 节)。从上面的Cypripedioideae示例中,我们可以使用 Bio.Entrez.efetch
下载 GenBank 记录 EU490707。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.efetch(db="nucleotide", id="EU490707", rettype="gb", retmode="text")
>>> print(stream.read())
LOCUS EU490707 1302 bp DNA linear PLN 26-JUL-2016
DEFINITION Selenipedium aequinoctiale maturase K (matK) gene, partial cds;
chloroplast.
ACCESSION EU490707
VERSION EU490707.1
KEYWORDS .
SOURCE chloroplast Selenipedium aequinoctiale
ORGANISM Selenipedium aequinoctiale
Eukaryota; Viridiplantae; Streptophyta; Embryophyta; Tracheophyta;
Spermatophyta; Magnoliopsida; Liliopsida; Asparagales; Orchidaceae;
Cypripedioideae; Selenipedium.
REFERENCE 1 (bases 1 to 1302)
AUTHORS Neubig,K.M., Whitten,W.M., Carlsward,B.S., Blanco,M.A., Endara,L.,
Williams,N.H. and Moore,M.
TITLE Phylogenetic utility of ycf1 in orchids: a plastid gene more
variable than matK
JOURNAL Plant Syst. Evol. 277 (1-2), 75-84 (2009)
REFERENCE 2 (bases 1 to 1302)
AUTHORS Neubig,K.M., Whitten,W.M., Carlsward,B.S., Blanco,M.A.,
Endara,C.L., Williams,N.H. and Moore,M.J.
TITLE Direct Submission
JOURNAL Submitted (14-FEB-2008) Department of Botany, University of
Florida, 220 Bartram Hall, Gainesville, FL 32611-8526, USA
FEATURES Location/Qualifiers
source 1..1302
/organism="Selenipedium aequinoctiale"
/organelle="plastid:chloroplast"
/mol_type="genomic DNA"
/specimen_voucher="FLAS:Blanco 2475"
/db_xref="taxon:256374"
gene <1..>1302
/gene="matK"
CDS <1..>1302
/gene="matK"
/codon_start=1
/transl_table=11
/product="maturase K"
/protein_id="ACC99456.1"
/translation="IFYEPVEIFGYDNKSSLVLVKRLITRMYQQNFLISSVNDSNQKG
FWGHKHFFSSHFSSQMVSEGFGVILEIPFSSQLVSSLEEKKIPKYQNLRSIHSIFPFL
EDKFLHLNYVSDLLIPHPIHLEILVQILQCRIKDVPSLHLLRLLFHEYHNLNSLITSK
KFIYAFSKRKKRFLWLLYNSYVYECEYLFQFLRKQSSYLRSTSSGVFLERTHLYVKIE
HLLVVCCNSFQRILCFLKDPFMHYVRYQGKAILASKGTLILMKKWKFHLVNFWQSYFH
FWSQPYRIHIKQLSNYSFSFLGYFSSVLENHLVVRNQMLENSFIINLLTKKFDTIAPV
ISLIGSLSKAQFCTVLGHPISKPIWTDFSDSDILDRFCRICRNLCRYHSGSSKKQVLY
RIKYILRLSCARTLARKHKSTVRTFMRRLGSGLLEEFFMEEE"
ORIGIN
1 attttttacg aacctgtgga aatttttggt tatgacaata aatctagttt agtacttgtg
61 aaacgtttaa ttactcgaat gtatcaacag aattttttga tttcttcggt taatgattct
121 aaccaaaaag gattttgggg gcacaagcat tttttttctt ctcatttttc ttctcaaatg
181 gtatcagaag gttttggagt cattctggaa attccattct cgtcgcaatt agtatcttct
241 cttgaagaaa aaaaaatacc aaaatatcag aatttacgat ctattcattc aatatttccc
301 tttttagaag acaaattttt acatttgaat tatgtgtcag atctactaat accccatccc
361 atccatctgg aaatcttggt tcaaatcctt caatgccgga tcaaggatgt tccttctttg
421 catttattgc gattgctttt ccacgaatat cataatttga atagtctcat tacttcaaag
481 aaattcattt acgccttttc aaaaagaaag aaaagattcc tttggttact atataattct
541 tatgtatatg aatgcgaata tctattccag tttcttcgta aacagtcttc ttatttacga
601 tcaacatctt ctggagtctt tcttgagcga acacatttat atgtaaaaat agaacatctt
661 ctagtagtgt gttgtaattc ttttcagagg atcctatgct ttctcaagga tcctttcatg
721 cattatgttc gatatcaagg aaaagcaatt ctggcttcaa agggaactct tattctgatg
781 aagaaatgga aatttcatct tgtgaatttt tggcaatctt attttcactt ttggtctcaa
841 ccgtatagga ttcatataaa gcaattatcc aactattcct tctcttttct ggggtatttt
901 tcaagtgtac tagaaaatca tttggtagta agaaatcaaa tgctagagaa ttcatttata
961 ataaatcttc tgactaagaa attcgatacc atagccccag ttatttctct tattggatca
1021 ttgtcgaaag ctcaattttg tactgtattg ggtcatccta ttagtaaacc gatctggacc
1081 gatttctcgg attctgatat tcttgatcga ttttgccgga tatgtagaaa tctttgtcgt
1141 tatcacagcg gatcctcaaa aaaacaggtt ttgtatcgta taaaatatat acttcgactt
1201 tcgtgtgcta gaactttggc acggaaacat aaaagtacag tacgcacttt tatgcgaaga
1261 ttaggttcgg gattattaga agaattcttt atggaagaag aa
//
请注意,从 2016 年 10 月开始,GI 标识符已停用,取而代之的是登录号。您仍然可以根据 GI 获取序列,但新序列不再使用此标识符。您应该改为使用示例中所示的“登录号”。
参数 rettype="gb"
和 retmode="text"
使我们能够以 GenBank 格式下载此记录。
请注意,直到 2009 年复活节,Entrez EFetch API 允许您使用“genbank”作为返回类型,但 NCBI 现在坚持使用官方的返回类型“gb”或“gbwithparts”(或蛋白质的“gp”,如在线描述)。另请注意,直到 2012 年 2 月,Entrez EFetch API 默认返回纯文本文件,但现在默认返回 XML。
或者,您可以例如使用 rettype="fasta"
获取 Fasta 格式;有关其他选项,请参阅 EFetch 序列帮助页面。请记住 - 可用的格式取决于您要从哪个数据库下载 - 请参阅主 EFetch 帮助页面。
如果您以 Bio.SeqIO
接受的一种格式获取记录(见第 序列输入/输出 章),您可以直接将其解析为 SeqRecord
。
>>> from Bio import SeqIO
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.efetch(db="nucleotide", id="EU490707", rettype="gb", retmode="text")
>>> record = SeqIO.read(stream, "genbank")
>>> stream.close()
>>> print(record.id)
EU490707.1
>>> print(record.name)
EU490707
>>> print(record.description)
Selenipedium aequinoctiale maturase K (matK) gene, partial cds; chloroplast
>>> print(len(record.features))
3
>>> record.seq
Seq('ATTTTTTACGAACCTGTGGAAATTTTTGGTTATGACAATAAATCTAGTTTAGTA...GAA')
请注意,更典型的用法是将序列数据保存到本地文件,然后用 Bio.SeqIO
解析它。这可以避免您在处理脚本时反复重新下载相同的文件,并减轻 NCBI 服务器的负担。例如
import os
from Bio import SeqIO
from Bio import Entrez
Entrez.email = "[email protected]" # Always tell NCBI who you are
filename = "EU490707.gbk"
if not os.path.isfile(filename):
# Downloading...
stream = Entrez.efetch(db="nucleotide", id="EU490707", rettype="gb", retmode="text")
output = open(filename, "w")
output.write(streame.read())
output.close()
stream.close()
print("Saved")
print("Parsing...")
record = SeqIO.read(filename, "genbank")
print(record)
要以 XML 格式获取输出,您可以使用 Bio.Entrez.read()
函数解析,请使用 retmode="xml"
。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.efetch(db="nucleotide", id="EU490707", retmode="xml")
>>> record = Entrez.read(stream)
>>> stream.close()
>>> record[0]["GBSeq_definition"]
'Selenipedium aequinoctiale maturase K (matK) gene, partial cds; chloroplast'
>>> record[0]["GBSeq_source"]
'chloroplast Selenipedium aequinoctiale'
因此,我们已经处理了序列。有关解析特定于其他数据库的文件格式的示例(例如,PubMed 中使用的 MEDLINE
格式),请参阅第 专用解析器 节。
如果您想使用 Bio.Entrez.esearch()
进行搜索,然后使用 Bio.Entrez.efetch()
下载记录,您应该使用 WebEnv 历史记录功能 - 请参阅第 使用历史记录和 WebEnv 节。
EGQuery:全局查询 - 搜索词计数
EGQuery 提供了每个 Entrez 数据库中搜索词的计数(即全局查询)。这对于在不实际执行大量使用 ESearch 的单独搜索的情况下找出您的搜索词在每个数据库中能找到多少项特别有用(请参阅下面的 搜索、下载和解析 Entrez 核苷酸记录 中的示例)。
在这个例子中,我们使用 Bio.Entrez.egquery()
获取“Biopython”的计数。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.egquery(term="biopython")
>>> record = Entrez.read(stream)
>>> for row in record["eGQueryResult"]:
... print(row["DbName"], row["Count"])
...
pubmed 6
pmc 62
journals 0
...
有关更多信息,请参阅 EGQuery 帮助页面。
ESpell:获取拼写建议
ESpell 获取拼写建议。在这个例子中,我们使用 Bio.Entrez.espell()
获取 Biopython 的正确拼写。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.espell(term="biopythooon")
>>> record = Entrez.read(stream)
>>> record["Query"]
'biopythooon'
>>> record["CorrectedQuery"]
'biopython'
有关更多信息,请参阅 ESpell 帮助页面。这主要用于 GUI 工具,为搜索词提供自动建议。
解析大型 Entrez XML 文件
Entrez.read
函数将 Entrez 返回的整个 XML 文件读取到一个 Python 对象中,该对象保存在内存中。要解析超出内存容量的 Entrez XML 文件,可以使用 Entrez.parse
函数。这是一个生成器函数,它逐个读取 XML 文件中的记录。此函数仅在 XML 文件反映 Python 列表对象时才有用(换句话说,如果具有无限内存资源的计算机上的 Entrez.read
将返回一个 Python 列表)。
例如,您可以从 NCBI 的 ftp 站点下载给定生物体的整个 Entrez Gene 数据库作为文件。这些文件可能非常大。例如,2009 年 9 月 4 日,包含人类 Entrez Gene 数据库的文件 Homo_sapiens.ags.gz
的大小为 116576 kB。此文件以 ASN
格式,可以使用 NCBI 的 gene2xml
程序转换为 XML 文件(有关更多信息,请参阅 NCBI 的 ftp 站点)。
$ gene2xml -b T -i Homo_sapiens.ags -o Homo_sapiens.xml
生成的 XML 文件大小为 6.1 GB。尝试对该文件执行 Entrez.read
将导致许多计算机上的 MemoryError
。
XML 文件 Homo_sapiens.xml
由一个 Entrez 基因记录列表组成,每个记录对应人类中的一个 Entrez 基因。 Entrez.parse
逐个检索这些基因记录。然后,您可以通过迭代记录来打印或存储每个记录中的相关信息。例如,此脚本迭代 Entrez 基因记录,并打印出所有当前基因的基因编号和名称。
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = open("Homo_sapiens.xml", "rb")
>>> records = Entrez.parse(stream)
或者,您可以使用
>>> records = Entrez.parse("Homo_sapiens.xml")
让 Bio.Entrez
负责打开和关闭文件。这更安全,因为文件在解析后会自动关闭,或者如果出现错误。
>>> for record in records:
... status = record["Entrezgene_track-info"]["Gene-track"]["Gene-track_status"]
... if status.attributes["value"] == "discontinued":
... continue
... geneid = record["Entrezgene_track-info"]["Gene-track"]["Gene-track_geneid"]
... genename = record["Entrezgene_gene"]["Gene-ref"]["Gene-ref_locus"]
... print(geneid, genename)
...
1 A1BG
2 A2M
3 A2MP
8 AA
9 NAT1
10 NAT2
11 AACP
12 SERPINA3
13 AADAC
14 AAMP
15 AANAT
16 AARS
17 AAVS1
...
HTML 转义字符
PubMed 记录可能包含 HTML 标签以指示例如下标、上标或斜体文本,以及通过 MathML 的数学符号。默认情况下,Bio.Entrez
解析器将所有文本视为无标记的纯文本;例如,PubMed 记录摘要中的片段“\(P < 0.05\)”,在 Entrez 返回的 XML 中编码为
<i>P</i> < 0.05
由 Bio.Entrez
解析器转换为 Python 字符串
'<i>P</i> < 0.05'
。虽然这更易于人阅读,但它不是有效的 HTML,因为小于号,而且使得通过 HTML 解析器进一步处理文本变得不切实际。为了确保解析器返回的所有字符串都是有效的 HTML,请使用 escape
参数设置为 True
来调用 Entrez.read
或 Entrez.parse
>>> record = Entrez.read(stream, escape=True)
解析器将用其 HTML 转义的等效项替换所有在 HTML 中不允许的字符;在上面的例子中,解析器将生成
'<i>P</i> < 0.05'
这是一个有效的 HTML 片段。默认情况下,escape
为 False
。
处理错误
该文件不是 XML 文件
例如,如果您尝试将 Fasta 文件解析为 XML 文件,则会发生此错误。
>>> from Bio import Entrez
>>> stream = open("NC_005816.fna", "rb") # a Fasta file
>>> record = Entrez.read(stream)
Traceback (most recent call last):
...
Bio.Entrez.Parser.NotXMLError: Failed to parse the XML data (syntax error: line 1, column 0). Please make sure that the input data are in XML format.
这里,解析器没有找到应该以 XML 文件开头的 <?xml ...
标签,因此(正确地)判定该文件不是 XML 文件。
该文件过早结束或已损坏
当您的文件处于 XML 格式但已损坏(例如,过早结束)时,解析器将引发 CorruptedXMLError。
这是一个过早结束的 XML 文件的示例
<?xml version="1.0"?>
<!DOCTYPE eInfoResult PUBLIC "-//NLM//DTD eInfoResult, 11 May 2002//EN" "https://www.ncbi.nlm.nih.gov/entrez/query/DTD/eInfo_020511.dtd">
<eInfoResult>
<DbList>
<DbName>pubmed</DbName>
<DbName>protein</DbName>
<DbName>nucleotide</DbName>
<DbName>nuccore</DbName>
<DbName>nucgss</DbName>
<DbName>nucest</DbName>
<DbName>structure</DbName>
<DbName>genome</DbName>
<DbName>books</DbName>
<DbName>cancerchromosomes</DbName>
<DbName>cdd</DbName>
这将生成以下跟踪
>>> Entrez.read(stream)
Traceback (most recent call last):
...
Bio.Entrez.Parser.CorruptedXMLError: Failed to parse the XML data (no element found: line 16, column 0). Please make sure that the input data are not corrupted.
请注意,错误消息会告诉您在 XML 文件的哪个位置检测到错误。
该文件包含与关联 DTD 中缺少的项目
这是一个包含在相应 DTD 文件中没有描述的标签的 XML 文件的示例
<?xml version="1.0"?>
<!DOCTYPE eInfoResult PUBLIC "-//NLM//DTD eInfoResult, 11 May 2002//EN" "https://www.ncbi.nlm.nih.gov/entrez/query/DTD/eInfo_020511.dtd">
<eInfoResult>
<DbInfo>
<DbName>pubmed</DbName>
<MenuName>PubMed</MenuName>
<Description>PubMed bibliographic record</Description>
<Count>20161961</Count>
<LastUpdate>2010/09/10 04:52</LastUpdate>
<FieldList>
<Field>
...
</Field>
</FieldList>
<DocsumList>
<Docsum>
<DsName>PubDate</DsName>
<DsType>4</DsType>
<DsTypeName>string</DsTypeName>
</Docsum>
<Docsum>
<DsName>EPubDate</DsName>
...
</DbInfo>
</eInfoResult>
在这个文件中,由于某种原因,标签 <DocsumList>
(以及其他几个)没有在 DTD 文件 eInfo_020511.dtd
中列出,该文件在第二行指定为该 XML 文件的 DTD。默认情况下,如果解析器在 DTD 中找不到某些标签,它将停止并引发 ValidationError
>>> from Bio import Entrez
>>> stream = open("einfo3.xml", "rb")
>>> record = Entrez.read(stream)
Traceback (most recent call last):
...
Bio.Entrez.Parser.ValidationError: Failed to find tag 'DocsumList' in the DTD. To skip all tags that are not represented in the DTD, please call Bio.Entrez.read or Bio.Entrez.parse with validate=False.
您可以选择指示解析器跳过此类标签,而不是引发 ValidationError。这可以通过使用 validate
参数等于 False 来调用 Entrez.read
或 Entrez.parse
来完成。
>>> from Bio import Entrez
>>> stream = open("einfo3.xml", "rb")
>>> record = Entrez.read(stream, validate=False)
>>> stream.close()
当然,在 DTD 中没有的 XML 标签中包含的信息不会出现在 Entrez.read
返回的记录中。
该文件包含错误消息
例如,当您尝试访问不存在的 PubMed ID 的 PubMed 记录时,可能会发生这种情况。默认情况下,这将引发 RuntimeError
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esummary(db="pubmed", id="99999999")
>>> record = Entrez.read(stream)
Traceback (most recent call last):
...
RuntimeError: UID=99999999: cannot get document summary
如果您正在访问多个 PubMed 记录,则 RuntimeError
将阻止您接收任何 PubMed 记录的结果,即使其中一个 PubMed ID 不正确。为了避免这种情况,您可以将 ignore_errors
参数设置为 True
。这将返回对有效 PubMed ID 的请求结果,以及对不正确 ID 的 ErrorElement
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esummary(db="pubmed", id="19304878,99999999,31278684")
>>> record = Entrez.read(stream, ignore_errors=True)
>>> len(record)
3
>>> record[0].tag
'DocSum'
>>> record[0]["Title"]
'Biopython: freely available Python tools for computational molecular biology and bioinformatics.'
>>> record[1].tag
'ERROR'
>>> record[1]
ErrorElement('UID=99999999: cannot get document summary')
>>> record[2].tag
'DocSum'
>>> record[2]["Title"]
'Sharing Programming Resources Between Bio* Projects.'
专用解析器
Bio.Entrez.read()
函数可以解析 Entrez 返回的大多数(如果不是全部)XML 输出。Entrez 通常允许您以其他格式检索记录,与 XML 格式相比,这些格式在可读性(或下载大小)方面可能具有一些优势。
要使用 Bio.Entrez.efetch()
从 Entrez 请求特定文件格式,需要指定 rettype
和/或 retmode
可选参数。不同的组合在 NCBI efetch 网页 上针对每个数据库类型进行了描述。
一个明显的例子是您可能更愿意以 FASTA 或 GenBank/GenPept 纯文本格式下载序列(然后可以使用 Bio.SeqIO
进行解析,请参见第 从网络解析 GenBank 记录 和 EFetch:从 Entrez 下载完整记录节)。对于文献数据库,Biopython 包含一个用于 PubMed 中使用的 MEDLINE
格式的解析器。
解析 Medline 记录
您可以在 Bio.Medline
中找到 Medline 解析器。假设我们要解析包含一个 Medline 记录的文件 pubmed_result1.txt
。您可以在 Biopython 的 Tests\Medline
目录中找到此文件。该文件如下所示
PMID- 12230038
OWN - NLM
STAT- MEDLINE
DA - 20020916
DCOM- 20030606
LR - 20041117
PUBM- Print
IS - 1467-5463 (Print)
VI - 3
IP - 3
DP - 2002 Sep
TI - The Bio* toolkits--a brief overview.
PG - 296-302
AB - Bioinformatics research is often difficult to do with commercial software. The
Open Source BioPerl, BioPython and Biojava projects provide toolkits with
...
我们首先打开文件,然后解析它
>>> from Bio import Medline
>>> with open("pubmed_result1.txt") as stream:
... record = Medline.read(stream)
...
record
现在包含 Medline 记录作为 Python 字典
>>> record["PMID"]
'12230038'
>>> record["AB"]
'Bioinformatics research is often difficult to do with commercial software.
The Open Source BioPerl, BioPython and Biojava projects provide toolkits with
multiple functionality that make it easier to create customized pipelines or
analysis. This review briefly compares the quirks of the underlying languages
and the functionality, documentation, utility and relative advantages of the
Bio counterparts, particularly from the point of view of the beginning
biologist programmer.'
Medline 记录中使用的键名可能比较模糊;使用
>>> help(record)
获得简要摘要。
要解析包含多个 Medline 记录的文件,可以使用 parse
函数代替
>>> from Bio import Medline
>>> with open("pubmed_result2.txt") as stream:
... for record in Medline.parse(stream):
... print(record["TI"])
...
A high level interface to SCOP and ASTRAL implemented in python.
GenomeDiagram: a python package for the visualization of large-scale genomic data.
Open source clustering software.
PDB file parser and structure class implemented in Python.
除了解析存储在文件中的 Medline 记录外,您还可以解析由 Bio.Entrez.efetch
下载的 Medline 记录。例如,让我们看看与 Biopython 相关的 PubMed 中的所有 Medline 记录
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(db="pubmed", term="biopython")
>>> record = Entrez.read(stream)
>>> record["IdList"]
['19304878', '18606172', '16403221', '16377612', '14871861', '14630660', '12230038']
我们现在使用 Bio.Entrez.efetch
下载这些 Medline 记录
>>> idlist = record["IdList"]
>>> stream = Entrez.efetch(db="pubmed", id=idlist, rettype="medline", retmode="text")
这里,我们指定 rettype="medline", retmode="text"
以获得纯文本 Medline 格式的 Medline 记录。现在我们使用 Bio.Medline
解析这些记录
>>> from Bio import Medline
>>> records = Medline.parse(stream)
>>> for record in records:
... print(record["AU"])
...
['Cock PJ', 'Antao T', 'Chang JT', 'Chapman BA', 'Cox CJ', 'Dalke A', ..., 'de Hoon MJ']
['Munteanu CR', 'Gonzalez-Diaz H', 'Magalhaes AL']
['Casbon JA', 'Crooks GE', 'Saqi MA']
['Pritchard L', 'White JA', 'Birch PR', 'Toth IK']
['de Hoon MJ', 'Imoto S', 'Nolan J', 'Miyano S']
['Hamelryck T', 'Manderick B']
['Mangalam H']
为了比较,这里我们展示一个使用 XML 格式的示例
>>> stream = Entrez.efetch(db="pubmed", id=idlist, rettype="medline", retmode="xml")
>>> records = Entrez.read(stream)
>>> for record in records["PubmedArticle"]:
... print(record["MedlineCitation"]["Article"]["ArticleTitle"])
...
Biopython: freely available Python tools for computational molecular biology and
bioinformatics.
Enzymes/non-enzymes classification model complexity based on composition, sequence,
3D and topological indices.
A high level interface to SCOP and ASTRAL implemented in python.
GenomeDiagram: a python package for the visualization of large-scale genomic data.
Open source clustering software.
PDB file parser and structure class implemented in Python.
The Bio* toolkits--a brief overview.
请注意,在这两个例子中,为了简单起见,我们简单地将ESearch和EFetch组合在一起。在这种情况下,NCBI希望您使用他们的历史功能,如“使用历史记录和WebEnv”一节中所示。
解析GEO记录
GEO (基因表达综合数据库) 是一个高通量基因表达和杂交芯片数据的数据库。可以使用Bio.Geo
模块解析GEO格式的数据。
以下代码片段展示了如何将示例GEO文件GSE16.txt
解析为记录并打印记录
>>> from Bio import Geo
>>> stream = open("GSE16.txt")
>>> records = Geo.parse(stream)
>>> for record in records:
... print(record)
...
您可以使用ESearch搜索“gds”数据库(GEO数据集)
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(db="gds", term="GSE16")
>>> record = Entrez.read(stream)
>>> stream.close()
>>> record["Count"]
'27'
>>> record["IdList"]
['200000016', '100000028', ...]
在Entrez网站上,UID“200000016”是GDS16,而另一个命中“100000028”是与之相关的平台GPL28。不幸的是,在撰写本文时,NCBI似乎不支持使用Entrez下载GEO文件(既不支持XML格式,也不支持“简单总线格式文本”(SOFT)格式)。
但是,实际上可以直接从ftp://ftp.ncbi.nih.gov/pub/geo/通过FTP下载GEO文件。在这种情况下,您可能需要ftp://ftp.ncbi.nih.gov/pub/geo/DATA/SOFT/by_series/GSE16/GSE16_family.soft.gz(一个压缩文件,请参见Python模块gzip)。
解析UniGene记录
UniGene是NCBI的转录组数据库,每个UniGene记录显示与特定生物体中特定基因相关的转录组集合。典型的UniGene记录如下所示
ID Hs.2
TITLE N-acetyltransferase 2 (arylamine N-acetyltransferase)
GENE NAT2
CYTOBAND 8p22
GENE_ID 10
LOCUSLINK 10
HOMOL YES
EXPRESS bone| connective tissue| intestine| liver| liver tumor| normal| soft tissue/muscle tissue tumor| adult
RESTR_EXPR adult
CHROMOSOME 8
STS ACC=PMC310725P3 UNISTS=272646
STS ACC=WIAF-2120 UNISTS=44576
STS ACC=G59899 UNISTS=137181
...
STS ACC=GDB:187676 UNISTS=155563
PROTSIM ORG=10090; PROTGI=6754794; PROTID=NP_035004.1; PCT=76.55; ALN=288
PROTSIM ORG=9796; PROTGI=149742490; PROTID=XP_001487907.1; PCT=79.66; ALN=288
PROTSIM ORG=9986; PROTGI=126722851; PROTID=NP_001075655.1; PCT=76.90; ALN=288
...
PROTSIM ORG=9598; PROTGI=114619004; PROTID=XP_519631.2; PCT=98.28; ALN=288
SCOUNT 38
SEQUENCE ACC=BC067218.1; NID=g45501306; PID=g45501307; SEQTYPE=mRNA
SEQUENCE ACC=NM_000015.2; NID=g116295259; PID=g116295260; SEQTYPE=mRNA
SEQUENCE ACC=D90042.1; NID=g219415; PID=g219416; SEQTYPE=mRNA
SEQUENCE ACC=D90040.1; NID=g219411; PID=g219412; SEQTYPE=mRNA
SEQUENCE ACC=BC015878.1; NID=g16198419; PID=g16198420; SEQTYPE=mRNA
SEQUENCE ACC=CR407631.1; NID=g47115198; PID=g47115199; SEQTYPE=mRNA
SEQUENCE ACC=BG569293.1; NID=g13576946; CLONE=IMAGE:4722596; END=5'; LID=6989; SEQTYPE=EST; TRACE=44157214
...
SEQUENCE ACC=AU099534.1; NID=g13550663; CLONE=HSI08034; END=5'; LID=8800; SEQTYPE=EST
//
此特定记录显示了来自人类NAT2基因(编码N-乙酰转移酶)的转录组集合(在SEQUENCE
行中显示)。PROTSIM
行显示与NAT2有显着相似性的蛋白质,而STS
行显示基因组中相应的序列标记位点。
要解析UniGene文件,请使用Bio.UniGene
模块
>>> from Bio import UniGene
>>> input = open("myunigenefile.data")
>>> record = UniGene.read(input)
由UniGene.read
返回的record
是一个Python对象,其属性对应于UniGene记录中的字段。例如,
>>> record.ID
"Hs.2"
>>> record.title
"N-acetyltransferase 2 (arylamine N-acetyltransferase)"
EXPRESS
和RESTR_EXPR
行存储为Python字符串列表
[
"bone",
"connective tissue",
"intestine",
"liver",
"liver tumor",
"normal",
"soft tissue/muscle tissue tumor",
"adult",
]
针对STS
,PROTSIM
和SEQUENCE
行返回专门的对象,将每行中显示的键存储为属性
>>> record.sts[0].acc
'PMC310725P3'
>>> record.sts[0].unists
'272646'
以及PROTSIM
和SEQUENCE
行类似。
要解析包含多个UniGene记录的文件,请使用Bio.UniGene
中的parse
函数
>>> from Bio import UniGene
>>> input = open("unigenerecords.data")
>>> records = UniGene.parse(input)
>>> for record in records:
... print(record.ID)
...
使用代理
通常您不必担心使用代理,但如果您的网络上出现此问题,请了解如何处理它。Bio.Entrez
在内部使用标准Python库urllib
来访问NCBI服务器。这将检查名为http_proxy
的环境变量,以自动配置任何简单的代理。不幸的是,此模块不支持使用需要身份验证的代理。
您可以选择设置http_proxy
环境变量一次(如何操作取决于您的操作系统)。或者,您可以在Python脚本的开头设置此变量,例如
import os
os.environ["http_proxy"] = "http://proxyhost.example.com:8080"
有关更多详细信息,请参见urllib 文档。
示例
PubMed和Medline
如果您从事医疗行业或对人类问题感兴趣(即使您不感兴趣,很多时候也是如此!),PubMed (https://www.ncbi.nlm.nih.gov/PubMed/) 是各种好东西的绝佳来源。因此,与其他事物一样,我们希望能够从中获取信息并在Python脚本中使用它。
在此示例中,我们将查询PubMed以获取所有与兰花相关的文章(请参阅“使用示例”一节,了解我们的动机)。我们首先检查有多少这样的文章
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.egquery(term="orchid")
>>> record = Entrez.read(stream)
>>> for row in record["eGQueryResult"]:
... if row["DbName"] == "pubmed":
... print(row["Count"])
...
463
现在,我们使用Bio.Entrez.efetch
函数下载这463篇文章的PubMed ID
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(db="pubmed", term="orchid", retmax=463)
>>> record = Entrez.read(stream)
>>> stream.close()
>>> idlist = record["IdList"]
这将返回一个Python列表,其中包含与兰花相关的文章的所有PubMed ID
>>> print(idlist)
['18680603', '18665331', '18661158', '18627489', '18627452', '18612381',
'18594007', '18591784', '18589523', '18579475', '18575811', '18575690',
...
现在我们已经得到了它们,我们显然希望获得相应的Medline记录并从中提取信息。在这里,我们将以Medline平面文件格式下载Medline记录,并使用Bio.Medline
模块解析它们
>>> from Bio import Medline
>>> stream = Entrez.efetch(db="pubmed", id=idlist, rettype="medline", retmode="text")
>>> records = Medline.parse(stream)
注意 - 我们只是在这里进行了单独的搜索和获取,NCBI更希望您在这种情况下利用其历史支持功能。请参阅“使用历史记录和WebEnv”一节。
请记住,records
是一个迭代器,因此您只能迭代一次记录。如果要保存记录,可以将它们转换为列表
>>> records = list(records)
现在让我们遍历记录,打印出有关每条记录的一些信息
>>> for record in records:
... print("title:", record.get("TI", "?"))
... print("authors:", record.get("AU", "?"))
... print("source:", record.get("SO", "?"))
... print("")
...
此操作的输出如下所示
title: Sex pheromone mimicry in the early spider orchid (ophrys sphegodes):
patterns of hydrocarbons as the key mechanism for pollination by sexual
deception [In Process Citation]
authors: ['Schiestl FP', 'Ayasse M', 'Paulus HF', 'Lofstedt C', 'Hansson BS',
'Ibarra F', 'Francke W']
source: J Comp Physiol [A] 2000 Jun;186(6):567-74
特别值得注意的是作者列表,它作为标准Python列表返回。这使得使用标准Python工具很容易操纵和搜索。例如,我们可以循环遍历大量条目,用以下代码搜索特定作者
>>> search_author = "Waits T"
>>> for record in records:
... if not "AU" in record:
... continue
... if search_author in record["AU"]:
... print("Author %s found: %s" % (search_author, record["SO"]))
...
希望本节让您了解Entrez和Medline接口的功能和灵活性,以及它们如何协同使用。
搜索、下载和解析Entrez核酸记录
在这里,我们将展示一个执行远程Entrez查询的简单示例。在“使用示例”一节的解析示例中,我们讨论了如何使用NCBI的Entrez网站搜索NCBI核酸数据库以获取有关杓兰亚科(我们的朋友,拖鞋兰)的信息。现在,我们将探讨如何使用Python脚本来自动执行该过程。在此示例中,我们将只展示如何连接、获取结果并解析它们,Entrez模块将完成所有工作。
首先,我们使用EGQuery找出我们将获取的结果数量,然后再实际下载它们。EGQuery将告诉我们在每个数据库中找到了多少搜索结果,但对于此示例,我们只对核酸感兴趣
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.egquery(term="Cypripedioideae")
>>> record = Entrez.read(stream)
>>> for row in record["eGQueryResult"]:
... if row["DbName"] == "nuccore":
... print(row["Count"])
...
4457
因此,我们预计将找到4457条Entrez核酸记录(这从2008年的814条记录增加;未来很可能继续增加)。如果您发现有太多命中,您可能需要重新考虑是否真的要下载所有结果,这是我们的下一步。让我们使用retmax
参数将检索到的最大记录数量限制为2008年可用的数量
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(
... db="nucleotide", term="Cypripedioideae", retmax=814, idtype="acc"
... )
>>> record = Entrez.read(stream)
>>> stream.close()
在此处,record
是一个包含搜索结果和一些辅助信息的Python字典。仅供参考,让我们看看此字典中存储了什么
>>> print(record.keys())
['Count', 'RetMax', 'IdList', 'TranslationSet', 'RetStart', 'QueryTranslation']
首先,让我们检查找到了多少结果
>>> print(record["Count"])
'4457'
您可能期望这是814,即我们要求检索的最大记录数量。但是,Count
表示该搜索可用的记录总数,而不是检索到的数量。检索到的记录存储在record['IdList']
中,其中应包含我们要求的总数
>>> len(record["IdList"])
814
让我们看看前五个结果
>>> record["IdList"][:5]
['KX265015.1', 'KX265014.1', 'KX265013.1', 'KX265012.1', 'KX265011.1']
我们可以使用efetch
下载这些记录。虽然您可以逐个下载这些记录,但为了减少对NCBI服务器的负载,最好一次获取大量记录,如下所示。但是,在这种情况下,您应该理想情况下使用“使用历史记录和WebEnv”一节中介绍的历史功能。
>>> idlist = ",".join(record["IdList"][:5])
>>> print(idlist)
KX265015.1, KX265014.1, KX265013.1, KX265012.1, KX265011.1]
>>> stream = Entrez.efetch(db="nucleotide", id=idlist, retmode="xml")
>>> records = Entrez.read(stream)
>>> len(records)
5
每个记录对应一个GenBank记录。
>>> print(records[0].keys())
['GBSeq_moltype', 'GBSeq_source', 'GBSeq_sequence',
'GBSeq_primary-accession', 'GBSeq_definition', 'GBSeq_accession-version',
'GBSeq_topology', 'GBSeq_length', 'GBSeq_feature-table',
'GBSeq_create-date', 'GBSeq_other-seqids', 'GBSeq_division',
'GBSeq_taxonomy', 'GBSeq_references', 'GBSeq_update-date',
'GBSeq_organism', 'GBSeq_locus', 'GBSeq_strandedness']
>>> print(records[0]["GBSeq_primary-accession"])
DQ110336
>>> print(records[0]["GBSeq_other-seqids"])
['gb|DQ110336.1|', 'gi|187237168']
>>> print(records[0]["GBSeq_definition"])
Cypripedium calceolus voucher Davis 03-03 A maturase (matR) gene, partial cds;
mitochondrial
>>> print(records[0]["GBSeq_organism"])
Cypripedium calceolus
您可以使用它来快速设置搜索 - 但对于大量使用,请参阅“使用历史记录和WebEnv”一节。
搜索、下载和解析GenBank记录
GenBank记录格式是一种非常流行的方法,用于保存有关序列、序列特征以及其他相关序列信息的信息。该格式是获取来自https://www.ncbi.nlm.nih.gov/的NCBI数据库信息的好方法。
在此示例中,我们将展示如何查询NCBI数据库,检索查询中的记录,然后使用Bio.SeqIO
解析它们 - 这在“从网络解析GenBank记录”一节中有所提及。为了简单起见,此示例不利用WebEnv历史功能 - 请参阅“使用历史记录和WebEnv”一节以了解这一点。
首先,我们想要进行查询并找出要检索的记录的ID。在这里,我们将快速搜索我们最喜欢的生物体之一,Opuntia(仙人掌)。我们可以进行快速搜索并获取所有对应记录的GI(GenBank标识符)。我们首先检查有多少条记录
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.egquery(term="Opuntia AND rpl16")
>>> record = Entrez.read(stream)
>>> for row in record["eGQueryResult"]:
... if row["DbName"] == "nuccore":
... print(row["Count"])
...
9
现在我们下载GenBank标识符列表
>>> stream = Entrez.esearch(db="nuccore", term="Opuntia AND rpl16")
>>> record = Entrez.read(stream)
>>> gi_list = record["IdList"]
>>> gi_list
['57240072', '57240071', '6273287', '6273291', '6273290', '6273289', '6273286',
'6273285', '6273284']
现在我们使用这些GI来下载GenBank记录 - 请注意,在较旧版本的Biopython中,您必须向Entrez提供一个用逗号分隔的GI编号列表,从Biopython 1.59开始,您可以传递一个列表,它将为您转换为相应的格式
>>> gi_str = ",".join(gi_list)
>>> stream = Entrez.efetch(db="nuccore", id=gi_str, rettype="gb", retmode="text")
如果您想要查看原始GenBank文件,您可以从此流中读取并打印出结果
>>> text = stream.read()
>>> print(text)
LOCUS AY851612 892 bp DNA linear PLN 10-APR-2007
DEFINITION Opuntia subulata rpl16 gene, intron; chloroplast.
ACCESSION AY851612
VERSION AY851612.1 GI:57240072
KEYWORDS .
SOURCE chloroplast Austrocylindropuntia subulata
ORGANISM Austrocylindropuntia subulata
Eukaryota; Viridiplantae; Streptophyta; Embryophyta; Tracheophyta;
Spermatophyta; Magnoliophyta; eudicotyledons; core eudicotyledons;
Caryophyllales; Cactaceae; Opuntioideae; Austrocylindropuntia.
REFERENCE 1 (bases 1 to 892)
AUTHORS Butterworth,C.A. and Wallace,R.S.
...
在这种情况下,我们只是获取原始记录。要以更易于Python使用的形式获取记录,我们可以使用Bio.SeqIO
将GenBank数据解析为SeqRecord
对象,包括SeqFeature
对象(请参阅“序列输入/输出”一章)。
>>> from Bio import SeqIO
>>> stream = Entrez.efetch(db="nuccore", id=gi_str, rettype="gb", retmode="text")
>>> records = SeqIO.parse(stream, "gb")
现在我们可以遍历这些记录,查看我们感兴趣的信息
>>> for record in records:
... print(f"{record.name}, length {len(record)}, with {len(record.features)} features")
...
AY851612, length 892, with 3 features
AY851611, length 881, with 3 features
AF191661, length 895, with 3 features
AF191665, length 902, with 3 features
AF191664, length 899, with 3 features
AF191663, length 899, with 3 features
AF191660, length 893, with 3 features
AF191659, length 894, with 3 features
AF191658, length 896, with 3 features
使用这些自动查询检索功能比手动操作要好得多。虽然模块应遵守 NCBI 每秒最多 3 次查询的规则,但 NCBI 还有其他建议,例如避免高峰时段。参见第 Entrez 指南 节。特别是,请注意,为简单起见,此示例不使用 WebEnv 历史记录功能。对于任何非平凡的搜索和下载工作,您应该使用它,参见第 使用历史记录和 WebEnv 节。
最后,如果您计划重复您的分析,而不是从 NCBI 下载文件并立即解析它们(如本示例所示),您应该只下载记录一次并将它们保存到您的硬盘,然后解析本地文件。
查找生物体的谱系
继续以植物为例,我们现在来查找兰科杓兰亚科的谱系。首先,我们在分类数据库中搜索 Cypripedioideae,它只产生一个 NCBI 分类标识符
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(db="Taxonomy", term="Cypripedioideae")
>>> record = Entrez.read(stream)
>>> record["IdList"]
['158330']
>>> record["IdList"][0]
'158330'
现在,我们使用 efetch
下载分类数据库中的此条目,然后解析它
>>> stream = Entrez.efetch(db="Taxonomy", id="158330", retmode="xml")
>>> records = Entrez.read(stream)
同样,此记录存储了大量信息
>>> records[0].keys()
['Lineage', 'Division', 'ParentTaxId', 'PubDate', 'LineageEx',
'CreateDate', 'TaxId', 'Rank', 'GeneticCode', 'ScientificName',
'MitoGeneticCode', 'UpdateDate']
我们可以直接从该记录中获取谱系
>>> records[0]["Lineage"]
'cellular organisms; Eukaryota; Viridiplantae; Streptophyta; Streptophytina;
Embryophyta; Tracheophyta; Euphyllophyta; Spermatophyta; Magnoliopsida;
Liliopsida; Asparagales; Orchidaceae'
记录数据包含的不仅仅是这里显示的信息 - 例如,查看 "LineageEx"
而不是 "Lineage"
,您也将获得谱系条目的 NCBI 分类标识符。
使用历史记录和 WebEnv
通常,您会希望进行一系列链接查询。最典型的,运行搜索,可能需要细化搜索,然后检索详细的搜索结果。您可以通过对 Entrez 进行一系列单独的调用来做到这一点。但是,NCBI 更希望您利用他们的历史记录支持 - 例如,将 ESearch 和 EFetch 结合起来。
历史记录支持的另一个典型用途是将 EPost 和 EFetch 结合起来。您使用 EPost 上传标识符列表,这将启动一个新的历史记录会话。然后,您通过引用会话(而不是标识符)使用 EFetch 下载记录。
使用历史记录搜索和下载序列
假设我们想搜索和下载所有Opuntia rpl16 核苷酸序列,并将它们存储在一个 FASTA 文件中。如第 搜索、下载和解析 GenBank 记录 节所示,我们可以天真地将 Bio.Entrez.esearch()
结合起来以获取登录号列表,然后调用 Bio.Entrez.efetch()
来下载它们全部。
但是,批准的方法是使用历史记录功能运行搜索。然后,我们可以通过引用搜索结果来获取结果 - NCBI 可以预测并缓存这些结果。
要做到这一点,请像往常一样调用 Bio.Entrez.esearch()
,但添加 usehistory="y"
参数,
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> stream = Entrez.esearch(
... db="nucleotide", term="Opuntia[orgn] and rpl16", usehistory="y", idtype="acc"
... )
>>> search_results = Entrez.read(stream)
>>> stream.close()
如前所述(参见第 搜索、下载和解析 Entrez 核苷酸记录 节),XML 输出包含前 retmax
个搜索结果,其中 retmax
默认值为 20
>>> acc_list = search_results["IdList"]
>>> count = int(search_results["Count"])
>>> len(acc_list)
20
>>> count
28
您还将获得两条附加信息,即 WebEnv
会话 cookie 和 QueryKey
>>> webenv = search_results["WebEnv"]
>>> query_key = search_results["QueryKey"]
将这些值存储在变量 session_cookie
和 query_key
中,我们可以将它们用作 Bio.Entrez.efetch()
的参数,而不是将 GI 号作为标识符提供。
虽然对于小型搜索,您可能可以一次性下载所有内容,但最好分批下载。您使用 retstart
和 retmax
参数指定要返回的搜索结果范围(使用基于零的计数的起始条目,以及要返回的最大结果数)。请注意,如果 Biopython 遇到瞬态故障(例如,与 NCBI 通信时出现 HTTP 500 响应),它会自动尝试几次。例如,
# This assumes you have already run a search as shown above,
# and set the variables count, webenv, query_key
batch_size = 3
output = open("orchid_rpl16.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))
stream = Entrez.efetch(
db="nucleotide",
rettype="fasta",
retmode="text",
retstart=start,
retmax=batch_size,
webenv=webenv,
query_key=query_key,
idtype="acc",
)
data = stream.read()
stream.close()
output.write(data)
output.close()
为了说明目的,此示例分批下载了三个 FASTA 记录。除非您正在下载基因组或染色体,否则您通常会选择更大的批次大小。
使用历史记录搜索和下载摘要
这是另一个历史记录示例,搜索过去一年中发表的关于Opuntia的论文,然后将它们下载到一个 MedLine 格式的文件中
from Bio import Entrez
Entrez.email = "[email protected]"
search_results = Entrez.read(
Entrez.esearch(
db="pubmed", term="Opuntia[ORGN]", reldate=365, datetype="pdat", usehistory="y"
)
)
count = int(search_results["Count"])
print("Found %i results" % count)
batch_size = 10
output = open("recent_orchid_papers.txt", "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))
stream = Entrez.efetch(
db="pubmed",
rettype="medline",
retmode="text",
retstart=start,
retmax=batch_size,
webenv=search_results["WebEnv"],
query_key=search_results["QueryKey"],
)
data = stream.read()
stream.close()
output.write(data)
output.close()
在撰写本文时,这产生了 28 个匹配项 - 但由于这是一个依赖于日期的搜索,因此这当然会有所不同。如上所述,您可以使用 Bio.Medline
解析保存的记录。
搜索引用
在第 ELink:在 NCBI Entrez 中搜索相关项目 节中,我们提到 ELink 可用于搜索给定论文的引用。不幸的是,这仅涵盖为 PubMed Central 编制索引的期刊(对 PubMed 中的所有期刊执行此操作意味着 NIH 需要做更多工作)。让我们尝试一下 Biopython PDB 解析器论文,PubMed ID 为 14630660
>>> from Bio import Entrez
>>> Entrez.email = "[email protected]" # Always tell NCBI who you are
>>> pmid = "14630660"
>>> results = Entrez.read(
... Entrez.elink(dbfrom="pubmed", db="pmc", LinkName="pubmed_pmc_refs", id=pmid)
... )
>>> pmc_ids = [link["Id"] for link in results[0]["LinkSetDb"][0]["Link"]]
>>> pmc_ids
['2744707', '2705363', '2682512', ..., '1190160']
很好 - 十一篇论文。但为什么没有找到 Biopython 应用笔记(PubMed ID 为 19304878)?好吧,正如您可能从变量名称中猜到的那样,它们实际上不是 PubMed ID,而是 PubMed Central ID。我们的应用笔记是该列表中的第三篇引用论文,PMCID 为 2682512。
那么,如果您(像我一样)更愿意获得一个 PubMed ID 列表呢?好吧,我们可以再次调用 ELink 来转换它们。这将成为一个两步过程,因此到目前为止,您应该期望使用历史记录功能来完成它(第 使用历史记录和 WebEnv 节)。
但首先,采用更直接的方法,对 ELink 进行第二次(单独的)调用
>>> results2 = Entrez.read(
... Entrez.elink(dbfrom="pmc", db="pubmed", LinkName="pmc_pubmed", id=",".join(pmc_ids))
... )
>>> pubmed_ids = [link["Id"] for link in results2[0]["LinkSetDb"][0]["Link"]]
>>> pubmed_ids
['19698094', '19450287', '19304878', ..., '15985178']
这次,您可以立即发现 Biopython 应用笔记是第三个命中项(PubMed ID 为 19304878)。
现在,让我们再次执行所有操作,但使用历史记录……待办事项。
最后,请不要忘记在 Entrez 调用中包含您自己的电子邮件地址。