python爬蟲 | 爬取開放伺服器的檔案
阿新 • • 發佈:2018-12-13
1.任務背景
現已提供資料檔案,其中兩個欄位是ftp連結,每一條資料有兩個連結,連結對應開放伺服器的檔案列表,該項任務主要把檔案列表中指定的壓縮包檔案下載下來。
資料如圖所示:
在瀏覽器中開啟對應的某個ftp連結,如下圖所示,目標是將其中紅框中的壓縮包下載下來,一個ftp下載一個,一條資料對應下載兩個壓縮包:
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.分析網頁原始碼
如上圖所示,可以發現程式碼非常簡單,所有檔案連結都在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多條連結,發現利用上述方式下載檔案的速度很慢。不知道是網路原因,還是程式碼本身有問題...費解...