uniport学习笔记
UniProt 作为全球最权威的蛋白质数据库,其强大的查询系统能帮助研究者快速定位目标数据。本文基于官方文档,来记录一个零基础Python环境下学习uniport的学习方法。本文假设读者是一名未经过系统计算机教育的生物类工作者,只会假设读者会Python的一些基本特性和常用方法。
前言
Uniport的API是一种Result类API,这类API的特点是利用URL进行数据与信息的专递,返回信息通常为json或者XML等信息。uniport的API也继承了这个特点。在Uniport的API中我们尽量只对json类信息进行操作,因此接下来只会讲解json类信息的特点和如何使用及访问。
以下的所有代码中都默认有库
import json
import os
import requests
from requests.adapters import HTTPAdapter, Retry
import re
import pandas as pd
一、必要前置信息
1.何为json
json是一类极其简单的结构化数据,其大多为数据对,即键:值。与Python中的字典类似,可以简单理解一种多重嵌套的字典。
举一个例子:
https://rest.uniprot.org/uniprotkb/P09230/publications
在使用库json后,我们就可以将其看作一种类似于字典的容器数据进行处理。即可以通过[]来访问
import json
# 读取 JSON 文件
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
# 假设 data.json 内容如下:
# {
# "name": "Alice",
# "age": 30,
# "hobbies": ["reading", "coding"],
# "address": {
# "city": "Beijing",
# "street": "Main Street"
# }
# }
# 读取某一项
print(data["name"]) # 输出: Alice
print(data["hobbies"][0]) # 输出: reading
print(data["address"]["city"]) # 输出: Beijing
2.如何在Python中实现对网站的访问
在Python中,我们常使用requests来实现对网址的访问。通常的request的方法相当冗长且难以理解,本文仅会描述到在Uniport中够用。
retries = Retry(total=5, backoff_factor=0.25, status_forcelist=[500, 502, 503, 504])
session = requests.Session()
session.mount("https://", HTTPAdapter(max_retries=retries))
def get_url(url):
response = session.get(url)
response.raise_for_status()
return response
这段其实是官方给出的访问方法,但其中其实有些功能是冗余的,但官方既然这么写了就先这么用吧)在访问时都可以使用get_url()方法来进行访问,其结果都会是点击之后返回的页面。
这里简单讲解一下可能的返回码是什么意思。
200:访问成功(基本不会看到)
500+(500,502,……):通常是服务器卡了,或者网不好导致的,重试即可。
其余的错误码基本都意味着你的代码,或者URL有问题,试着检查错误。
二、API基本
基本URL结构为
https://rest.uniprot.org/<数据库名字>/<操作方法>
数据库通常为uniportKB和citations。uniportKB可以实现对大多数内容的查询,而citations则可以下载相关论文信息。具体论文内容需要根据其中的PubMed ID下载。
PudMed也是常搭配Uniport使用的平台,后续笔者也会更新我们使用Uniport时所需要的PubMed内容。
在Uniport或者说所有Result类API中,最重要的方法之一就是通过找到你想要的资源地址,然后将其URL的开头换为API的URL开头。
比如我想要获得某个蛋白质的论文信息。
我们先找到那个蛋白质的网页,点开论文页面。
然后,我们将www换成rest(即将url头部换为api的)
剩下的内容就变成蛋白质信息的json内容了,其余信息也有类似的情况。
三、查询语法
1.原理
先举一个例子
https://rest.uniprot.org/uniprotkb/search?query=human&fields=accession,xref_proteomes
https://rest.uniprot.org/uniprotkb/search?query=human
https://rest.uniprot.org/uniprotkb/search?query=human&fields=accession
这一段内容是查询人类作为搜索词,并获取accession,xref_proteomes这两个信息的API的例子。读者可以自行点击查看会返回怎样的信息。
查询的基础URL为
https://rest.uniprot.org/uniprotkb/search?query=<搜索的内容>&fields=<想要请求的内容>&<其他有效参数>
搜索的内容允许使用布尔运算来将数个关键词连接。
fields允许的有效字段非常之多,具体查看有效字段.
官方的有效字段json有些抽象,id=可选字段_所属参数。
所以在事实上,只有id以field为结尾的才可以放入field参数当中。
其他有效参数有includeIso,sort,size,includeIsoform.
2.实战
让我们来看一下实际中我们可以使用怎样的代码来做到这个功能。
def download_data(url, mode='1'):
""" 下载蛋白质列表数据 """
proteins = []
for batch in get_batch(url):
for line in batch.text.splitlines()[1:]:
proteins.append(line.split('\t')[0]) # 提取蛋白质ID(假设第一列为ID)
return proteins
def search_proteins(search_query,fields='accession,id',format='tsv',size=500):
url=("https://rest.uniprot.org/uniprotkb/search?"
"query={search_query}&"
"fields={fields}&format={format}&size={size}")
url = url.format(search_query=search_query, fields=fields, format=format, size=size)
proteins = download_data(url)
return proteins
这段代码实现了搜索特定蛋白质url的构建,实际上这两段代码是可以合并的,但鉴于未来可能会需要别的url来下载所以分离,读者可根据实际需求来写代码。
这里会返回所有符合需求蛋白的id,id是用来后续操作必要的数据。
四、获取蛋白质的基本信息
1.原理
参考笔者之前提到的方法,我们想要获取的基本信息在哪个页面?
https://www.uniprot.org/uniprotkb/P09230/entry
我们将这个转为api应有的题头
https://rest.uniprot.org/uniprotkb/P09230/entry
我们发现这个页面并没有我们想要的信息,这个时候我们必须要有一种思维,这种思维就是设计者的思维,就是你如果是设计这个网站API的人,你会将这个蛋白质的基本信息放到哪里?
很容易想到https://rest.uniprot.org/uniprotkb/P09230
在事实上也是如此。具体内容不再展示了,读者可以自行查阅这个链接包含了这个蛋白质怎样的信息。不要忘记使用ctrl+F快速查找你想要的信息。
2.实战
def fetch_uniprot_data(protein_id: str, folder_path: str) -> bool:
""" 获取并保存UniProt完整JSON数据 """
url = f"https://rest.uniprot.org/uniprotkb/{protein_id}"
filepath = os.path.join(folder_path, f"{protein_id}.json")
try:
if os.path.exists(filepath):
return True
response = session.get(url)
response.raise_for_status()
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(response.json(), f, indent=2)
return True
except Exception as e:
print(f"下载 {protein_id} UniProt数据失败: {str(e)}")
return False
如果你只想要某个信息,那需要对json进行访问即可。
五、获取相关论文
这个需要提前获取你要获取的蛋白质的id,因此常常和搜索同时使用。
1.原理
基础url为
https://rest.uniprot.org/uniprotkb/{protein_id}/publications
这个会获得某个蛋白质的全部出版物,举一个例子
https://rest.uniprot.org/uniprotkb/P09230/publications
这里最重要的数据为id,持有这个数据就可以从pubMed中下载论文原文
2.实战
def save_publications(proteins, max_proteins=1000):
""" 直接保存每个蛋白质的原始出版物数据 """
base_url = "https://rest.uniprot.org/uniprotkb/{protein_id}/publications"
base_dir = "Uniprot_data"
# 创建根目录,这段代码在后续解释。
create_folder(base_dir)
report = []
for idx, protein in enumerate(proteins):
if idx >= max_proteins:
break
protein_dir = os.path.join(base_dir, protein)
output_file = os.path.join(protein_dir, "publications.json")
try:
# 跳过已处理过的蛋白质
if os.path.exists(output_file):
print(f"[{idx+1}/{len(proteins)}] {protein} 数据已存在,跳过")
report.append({"Protein": protein, "Status": "已存在"})
continue
# 创建蛋白质专属目录
create_folder(protein_dir)
# 获取论文数据
url = base_url.format(protein_id=protein)
response = session.get(url)
response.raise_for_status()
data = response.json()
# 保存原始JSON数据
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2)
print(f"[{idx+1}/{len(proteins)}] {protein} 数据已保存")
report.append({"Protein": protein, "Status": "成功"})
except Exception as e:
print(f"[{idx+1}/{len(proteins)}] {protein} 处理失败: {str(e)}")
report.append({"Protein": protein, "Status": f"失败: {str(e)}"})
这段代码实现了从Uniport下载蛋白质的论文信息并将其保存在一个以蛋白质名字命名的文件夹中,这里使用了一个文件夹创建的函数。如下。
def create_folder(folder_path: str) -> None:
""" 创建多级目录 """
if not os.path.exists(folder_path):
os.makedirs(folder_path)
print(f"目录 '{folder_path}' 已创建")
else:
print(f"目录 '{folder_path}' 已存在")
六、杂项
许多我们常用的信息并不在上述的json当中,这里主要是记录一些杂项在哪里访问,未来会持续更新。
- 蛋白质的序列fasta
https://rest.uniprot.org/uniprotkb/{id}.fasta
- 蛋白质的结构
https://alphafold.ebi.ac.uk/files/AF-{id}-F1-model_v4.pdb# AlphaFold的结构