1.任务背景

       现已提供数据文件,其中两个字段是ftp链接,每一条数据有两个链接,链接对应开放服务器的文件列表,该项任务主要把文件列表中指定的压缩包文件下载下来。

数据如图所示:

python爬虫 | 爬取开放服务器的文件

在浏览器中打开对应的某个ftp链接,如下图所示,目标是将其中红框中的压缩包下载下来,一个ftp下载一个,一条数据对应下载两个压缩包:

python爬虫 | 爬取开放服务器的文件

2.数据预处理

        由于python爬虫的requests库请求的url都是以http/https打头,所有首先做的操作是将每个ftp链接前缀转换为http/https,代码如下:

def changePre(data):  #更换url前缀为https
    hurlsGen=[]       #存放所有转换完成的Gen FTP链接
    hurlsRef=[]       #存放所有转换完成的Ref FTP链接
    i=0
    while i<len(data):  #循环遍历所有数据进行转换
        data=data.astype(str)
        furlGen = data['GenBank FTP'][i].strip()[3:]
        furlRef = data['RefSeq FTP'][i].strip()[3:]
        hurlGen = 'https' + furlGen+'/'
        hurlRef = 'https' + furlRef+'/'
        hurlsGen.append(hurlGen)
        hurlsRef.append(hurlRef)
        i+=1
    return hurlsGen,hurlsRef

3.得到每条转换后的url对应的HTML代码

def getHTMLText(url, code="utf-8"):   #得到转换后的每条url对应的HTML代码
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = code
        return r.text
    except:
        return ""

4.分析网页源码

python爬虫 | 爬取开放服务器的文件

如上图所示,可以发现代码非常简单,所有文件链接都在a标签中。

5.解析HTML代码,提取指定下载文件的文件名。

def parseHTMLText(html):   #解析网页源码,提取指定下载文件的文件名
    doc=pq(html)           #用pyquery提取a标签
    a=doc('a')              
    filename='RNG'         #默认文件名为RNG
    for item in a.items():    #遍历所有提取的a标签,根据href属性值,找到指定的下载文件的文件名
        if 'protein.gpff.gz' in item.attr('href'): 
            filename=item.attr('href')
            print(filename)
    return filename

6.提取待下载的文件,并写在本地文件夹中

def writeFile(basicUrl,filename,filepath,count): 
        filepath1='{0}/{1}'.format(filepath,str(count)+'_'+filename)#本地写入路径
        if not os.path.exists(filepath1):
            with open(filepath1,'wb') as f:
                file=requests.get(basicUrl+filename) #指定文件的下载链接
                if file.status_code==200:            #可能有的链接不含指定文件 此时会生成一个空文件,文件名为:序号_RNG
                    f.write(file.content)

7.全部代码:

#-*- coding:utf-8 -*-
import requests
import os
from pyquery import PyQuery as pq
import pandas as pd
from multiprocessing import Pool


def getHTMLText(url, code="utf-8"):   #得到转换后的每条url对应的HTML代码
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = code
        return r.text
    except:
        return ""

def parseHTMLText(html):   #解析网页源码,提取指定下载文件的文件名
    doc=pq(html)           #用pyquery提取a标签
    a=doc('a')              
    filename='RNG'         #默认文件名为RNG
    for item in a.items():    #遍历所有提取的a标签,根据href属性值,找到指定的下载文件的文件名
        if 'protein.gpff.gz' in item.attr('href'): 
            filename=item.attr('href')
            print(filename)
    return filename


def writeFile(basicUrl,filename,filepath,count): 
        filepath1='{0}/{1}'.format(filepath,str(count)+'_'+filename)#本地写入路径
        if not os.path.exists(filepath1):
            with open(filepath1,'wb') as f:
                file=requests.get(basicUrl+filename) #指定文件的下载链接
                if file.status_code==200:            #可能有的链接不含指定文件 此时会生成一个空文件,文件名为:序号_RNG
                    f.write(file.content)
               


def changePre(data):  #更换url前缀为https
    hurlsGen=[]       #存放所有转换完成的Gen FTP链接
    hurlsRef=[]       #存放所有转换完成的Ref FTP链接
    i=0
    while i<len(data):  #循环遍历所有数据进行转换
        data=data.astype(str)
        furlGen = data['GenBank FTP'][i].strip()[3:]
        furlRef = data['RefSeq FTP'][i].strip()[3:]
        hurlGen = 'https' + furlGen+'/'
        hurlRef = 'https' + furlRef+'/'
        hurlsGen.append(hurlGen)
        hurlsRef.append(hurlRef)
        i+=1
    return hurlsGen,hurlsRef

def Write(urls,title):
    count=1
    for url in urls:
        if not os.path.exists(title):
            os.mkdir(title)
        html = getHTMLText(url)
        #print(html)
        filename = parseHTMLText(html)
        filepath = title
        writeFile(url, filename, filepath,count)
        count+=1


hurlsGen=[]
hurlsReq=[]
def main():
    data=pd.read_csv('prokaryotes.csv')
    #data=data.head()
    hurlsGen,hurlsReq=changePre(data)
    #hurlsGen=["https://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/000/504/085/GCA_000504085.1_ASM50408v1"]
    Write(hurlsGen,'Gen')    
    Write(hurlsReq,'Req')

if __name__=='__main__':
    main()

















8.问题:

        数据文件总共有1w多条数据,对应2w多条链接,发现利用上述方式下载文件的速度很慢。不知道是网络原因,还是代码本身有问题...费解...

相关文章:

  • 2021-09-07
  • 2021-07-02
  • 2022-02-04
  • 2021-07-15
  • 2022-12-23
  • 2021-06-16
  • 2021-10-13
  • 2021-08-09
猜你喜欢
  • 2021-10-09
  • 2022-12-23
  • 2021-10-09
  • 2022-12-23
  • 2021-11-26
  • 2022-12-23
  • 2021-12-19
相关资源
相似解决方案