NCBI批量下载基因组

说明

  • 使用Python 中的 ftplib从NCBI下载基因组。
  • 关于基因组的一些知识请参考之前的文章

待改进

  • 目前只能处理文件夹里面不包含文件夹的情况,如果还有文件夹,只会提醒。
  • 目前如果有多个版本的注释,默认下载的是第一个版本
  • 目前目的文件夹已经写在里面了E://,应该下载到当前路径。
  • 以上不足不影响下到最核心的序列文件。

前题

  1. 安装了 Python3
  2. 文件夹:
    1. *.txt 文件夹存放 GenBank accession No,一行一条,第一行不要为空行。
    2. 将以下内容粘贴到另外一个 txt 文件中,并修改后缀为 py

运行

双击 .py 文件。


#!/usr/bin/python
#author: W.-S. Zheng
#date 20180429
# -*- coding: UTF-8 -*-
#usage: download genomes from ncbi database

import glob
from ftplib import FTP
import os
import sys

# ------------------- 类和函数定义 -----------------------
class MyPathes:
    '''定义类储存当前路径,当前路径下的文件名,当前路径下的文件夹名'''

    def __init__(self, cur_path, ftp):
        self.cur = cur_path #当前路径
        self.ftp = ftp # 连接的FTP
        self.folders = [] # 解析出当前路径下的文件夹
        self.files = [] # 解析出当前路径下的文件
        self.nextPathes = [] # 生成下一步的路径
        self.links = [] # 解析出当前路径下的超链接

        self.content = self.getContet() # 初始化的时候从服务器上获得路径下的内容
        self.sort() # 对获得的内容分类:文件夹,文件,超链接
        self.createPathes() # 生成下一步的路径,也就是如何去包含的文件夹

    def getContet(self):
        dir_content = []
        self.ftp.cwd(self.cur)
        self.ftp.retrlines('LIST', callback = dir_content.append)
        return dir_content

    def sort(self):
        for line in self.content:
            if line.startswith('d'):
                self.folders.append(line.split(" ")[-1])
            elif line.startswith('l'):
                self.links.append(line.split(" ")[-1])
            else:
                self.files.append(line.split(" ")[-1])

    def oneDes(self):
        return(len(self.folders) == 1)


    def createPathes(self):
        for folder in self.folders:
            self.nextPathes.append(self.cur + '/' + folder)
        return(self.nextPathes)

# -------------------------函数 -----------------------------
# 转换accession no. 为路径
def acc2path(acc):
    root = '/genomes/all/GCA/'
    acc = acc.split('_')[1]
    acc = acc.split('.')[0]
    path = root + acc[0:3] + '/' + acc[3:6] + '/' + acc[6:9]
    return path

# 连接FTP
def con():
    ftp = FTP()
    ftp.connect("ftp.ncbi.nlm.nih.gov", 21)
    ftp.login()#连接的用户名,密码
    return(ftp)

# 下载文件
def downloadFile(filename):
    try:
        ftp.retrbinary("RETR " + filename, open(filename, 'wb').write)
    except FileExistsError:
        pass

# 下载文件夹
def downloadFolder(dir_folder):
    try:
        os.mkdir(dir_folder)
    except FileExistsError:
        print('File existed')
    os.chdir(dir_folder)

#----------------------------定义完成----------------------

# 获得GenBank No.
# 存在同文件夹中,唯一的txt文件中
file = glob.glob('*.txt')
print(file)
accessions = open(file[0], 'r').readlines()
print(accessions)


# 逐个基因组下载,适用于文件夹中不包括其他文件夹
for acc in accessions:
    os.chdir('E://')

    # 将No解析为路径
    root = acc2path(acc)
    print(root)


    # 连接FTP
    ftp = con()

    # 解析当前路径的内容
    x1 = MyPathes(root, ftp)

    # 进入要下载的文件夹
    # 如果不只一个文件夹,说明有不同注释的版本,提醒
    if not x1.oneDes():
        print("More than one version available!")

    else:
        # 连接FTP
        ftp = con() 

        # 建立本地文件夹
        downloadFolder(x1.folders[0])
        
        # 进入下一级ftp目录,这里包含实际的序列和注释文件
        x2 = MyPathes(x1.nextPathes[0], ftp)

        # 开始下载
        print('start!')
        prog = len(x2.files)
        for file in x2.files:
            downloadFile(file)
            sys.stdout.write("%i=" % (prog))
            sys.stdout.flush()
            prog = prog-1

       # 判断是不是还有包含的文件夹需要下载 
       if not x2.nextPathes: 
            print('Done')
        else:
            print('Must go deeper')

posted @ 2018-05-02 21:26  Xeonilian  阅读(2906)  评论(0编辑  收藏  举报