生物信息学与算法RNA-seqrice related analysis

一文学会批量下载SRA数据

2019-01-10  本文已影响18人  WooWoods

因业务需要,得从SRA下载数据,项目号是SRP059928,打开一看,这个项目下一共有62个文件,不算多,也不算少。



麻烦的地方在于,当前页面每条item下的accession number是用不上的,你得点进去,在另一个页面找到它的SRR number,这个number才能用于sra-toolkit下载。



62个item,每个点一次鼠标,选中SRR number,复制一下,还得去命令行敲一条命令,有可能还会忘了上一条点的是哪个,得回去检查一下。。。想想都很烦啊,得,写个脚本搞一搞吧。

这就是个小爬虫嘛,先来分析一下需求。我们现在有一个项目号SRP059928,用这个项目号去NCBI SRA 搜索,会返回一个页面,它的URL是https://www.ncbi.nlm.nih.gov/sra/?term=SRP059928,仔细看,这个就是我们的初始URL。搜索结果一共有4页,每一页都有很多item,每条item都是一个链接,我们的目标是找出所有item的链接,顺着链接获取新的页面,从新的页面得到SRR number并记录下来。当我们获取了所有的SRR number,爬虫的任务就算完成了。之后的下载任务,只需要拿着这些SRR number,写个循环就很容易搞定。
需求搞清楚了,接下来分析页面,目的是从网页源代码中发现一定的规律,从而将我们需要的东西提取出来。只要它有自己的特征,不同于其他的结构,我们就能有办法对付它,跟做实验一个道理。方法有很多,可以用BeautifulSoup,也可以用正则表达式re,但是我喜欢用xpath。

用chrome浏览器按ctl+shift+I打开调试器,很容易就发现,所有item的结构都是一样的,<a>标签中就包含我们要的链接。


node_list = html.xpath("//div[@class='rslt']/p[@class='title']/a/@href")

这行代码的意思是提取所有'class'属性值为'rslt'的<div>标签下的'class'属性值为'title'的<p>标签下的<a>标签的href值,有点拗口,对照着HTML结构看应该很容易明白:


接下来要从每个item的页面提取SRR number,同样的,打开调试工具,可以看到,只有这个<a>标签是在一个<table>里面,利用这个特征就可以把SRR number提出来了。


OK,技术分析到此结束。只需要把每个页面都这么爬一遍就搞定了。翻页很easy的,不信你们看,当我点击next按钮,页面会跳到下一页,同时URL会变成https://www.ncbi.nlm.nih.gov/sra/?term=SRP059928/2这样类似的形式。。。

这就过分了啊,作为一个学术性的网站反爬虫反的这么认真,估计也是被爬虫整的烦了。
那么是时候祭出selenium了,简单说下,这个工具就是模拟浏览器点击的操作,以实现反反爬虫。因为是在Linux服务器上,没有桌面环境,所以使用selenium时需要先用Xvfb启动一个虚拟化的桌面。

    def browse_page(self):
        # 启动虚拟桌面
        display = Display(visible=0, size=[800, 600])
        display.start()
        driver = webdriver.Chrome()
        driver.get(self.startURL)
        elem = driver.find_element_by_xpath('//input[@title="Search SRA"]')
        elem.clear()
        try:
            print(f'正在搜索{self.accession_num}')
            elem.send_keys(self.accession_num)
            elem.send_keys(Keys.RETURN)
        except Exception:
            raise('SRA检索失败,请检查项目号后再次运行。')

        has_next = True
        while has_next:
            try:
                # 将页面源代码提供给parse_page进行解析
                page_content = driver.page_source
                self.parse_page(page_content)
                # 点击<下一页>按钮进行翻页
                options = driver.find_elements_by_xpath("//a[@title='Next page of results']")
                options[0].click()
            except IndexError:
                has_next = False
        driver.close()
        display.stop()

完整代码有些长,就不贴了。已上传GitHub(https://github.com/WooWoods/biofino-exercises),有需要的自取。

为了加快下载速度,这里使用的多线程,因为这种下载任务比较适合用多线程。如果你不知道什么是多线程,打个比方,有个活儿,1个人需要干10天,如果10个人同时干,就只需要1天。不恰当,不严谨,但是可以这样理解吧。
因为某些“你懂的”原因,我们下载外网资源的速度非常难以忍受,所以我放弃了sra-toolkit的fastq-dump,而使用aspera下载。aspera真的是非常强大,什么原理我不懂,似乎不是通过http或ftp协议,“你懂的”拿他没办法。所以大家如果用这段代码的话需要先配置自己的aspera环境,或者改用fastq-dump,或者ftp,改一句代码就可以。

看一下效果

其实还可以打包成exe文件,作为独立程序直接可以在Windows下使用的,不需要配置环境,但是我比较懒,所以就这样吧,拜拜。


上一篇 下一篇

猜你喜欢

热点阅读