本文針對複雜數據網站進行數據爬取測試,本文使用的爬蟲工具是psotman,通過postman來模擬和嘗試生成post連接,以找出爬蟲URL的準確形式,最後將代碼整合後形成完整的批量化數據爬取代碼。
1.爬取ctd藥物數據網站上的drug數據:
ctd數很多生物研究常常使用的大型數據庫之一,但是要想每次粘貼進去4000個藥物名稱進行批量查詢和下載,往往會導致數據庫的反應時間過長,文件過大中途與服務器斷開連接,同時如果想要爬取的藥物數目達到幾萬條,則手動的輸出和點擊查詢會顯得笨拙和重複無聊!本文針對複雜的數據庫網頁進行爬取,實現自動化批量查詢和文件寫入。
2.詳細流程
2.1.使用Chrome瀏覽器,輸入網址:http://ctdbase.org/tools/batchQuery.go, 然後輸入要查詢的藥物名稱列表:此處僅給出10個供學習參考!
drug_list=
[polyethylene glycol
acetate
acetylcholine
sodium chloride
anthranilic acid
quinacrine
betaine
calcium
CO(2
citric acid],往ctd的網站中輸入drug_list的信息。
2.2.先打開Chrom瀏覽器>點擊Download>其餘見下圖:
雙擊“batchQuery.go?q”打開頁面,可以找到網頁中點擊Download後的post表單信息:
Form Data完整的表單數據
注:畫了綠色方框的地方是要在postman中提交的參數字段及其對應值。
2.3.在postman中,模仿Form Data部分構造表單數據向網頁提交post請求,看是否能夠返回正確的response頁面,如果可以則表單數據提交正確!之後我們就可以找到批量訪問數據的URL的特點,並編寫Python自動化程序實現對數據進行批量查詢和下載並保存成文本文件的操作。
進入postman頁面,粘貼入主要的URL domain部分,然後選擇“POST”,並在Params中依次填寫2.2節中最後綠色框中的內容字段及其對應值,然後點擊send就可以查看post提交的結果是否正確。測試成功後,就可以將整個URL的規律找到,實現一個批量自動化的數據爬取程序!
注:對於一些新版網頁來說,找到要爬取的字段的規律,可以直接右鍵>網頁源代碼>通過ctrl+F來查找指定的字段及其對應的標籤,最後通過beautifulsoup4來實現網頁標籤的快速select操作。
3.代碼
# -*- coding: utf-8 -*-
#使用postman傳遞參數後發現正確返回了結果
"""
http://ctdbase.org/tools/batchQuery.go?inputType=chem&inputTerms=
polyethylene
glycol
acetate
acetylcholine
sodium chloride
anthranilic acid
quinacrine
betaine
calcium
CO(2
citric acid
chloride
&queryFileColumn=1&report=cgixns&actionTypes=ANY&format=tsv&action=Download
"""
import requests
import random
import time
import pandas as pd
#4個數據的選項按鈕對應的Id的標籤名稱
inputType='chem'
#要爬取的藥物的名稱
drug_name=pd.read_csv('E:/drug_name112.csv')
drug_name.columns=['ChemicalID', 'drugName']
drug_name=sorted(drug_name['drugName'])
#讀取可用的IP地址
Valid_IPP=pd.read_csv('E:/valid_IP.csv')
valid_IP11=[]
for i in range(len(Valid_IPP)):
zhou=Valid_IPP.loc[i,:].tolist()
valid_IP11.append(zhou)
#批量數據的爬取
def scrapy_ctd_web(drug_name,valid_IP11):
for i in range(0,len(drug_name)-120,120): #1200
#for i in range(0,120,120):
index1=i
index2=i+120
#print(index1,index2)
drugname='' #拼接第二個參數的文本
count=0
outpath='E:/scrapy_web_ctd/'+str(int(index2/120))+'.txt'
for line in drug_name[index1:index2]:
count+=1
if count==120:
drugname+=line
break
drugname+=line
drugname+='\n'
print(drugname)
#拼接構造post的URL鄰接地址
new_url='http://ctdbase.org/tools/batchQuery.go?inputType='+inputType+'&inputTerms='+drugname+'&queryFileColumn=1&report=cgixns&actionTypes=ANY&format=tsv&action=Download'
header={"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Encoding": "gb2312, utf-8",
"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0",
"Connection": "keep-alive",
"referer":"http://ctdbase.org/tools/batchQuery.go"}
with open(outpath,'w+') as fp:
try:
IP_item = random.choice(valid_IP11)
proxies={IP_item[0].lower():IP_item[1]}
res=requests.get(new_url,proxies=proxies, headers=header,timeout=12) #封裝了瀏覽器頭部,同時使用IP池技術做一定程度的反爬蟲,timeout設置長一些可以容錯:請求時間較長的數據可以爬取下來。
res.encoding='utf-8' #設置頁面的編碼方式
fp.write(res.text)
print('第{}---{},已經爬取成功!!!'.format(index1,index2))
print('可用IP爲: ',IP_item[0].lower(),':',IP_item[1])
#print(res.text)
except:
k=0
while len(res.text)==0:
IP_item = random.choice(valid_IP11)
proxies={IP_item[0].lower():IP_item[1]}
res=requests.get(new_url,proxies=proxies, headers=header,timeout=12) #封裝了瀏覽器頭部,同時使用IP池技術做一定程度的反爬蟲,timeout設置長一些可以容錯:請求時間較長的數據可以爬取下來。
k+=1
time.sleep(5)
if k==10:
print('已經找尋了10次IP地址!!!')
break
if k!=10:
res.encoding='utf-8' #設置頁面的編碼方式
fp.write(res.text)
print('第{}---{},已經爬取成功!!!'.format(index1,index2))
print('可用IP爲: ',IP_item[0].lower(),':',IP_item[1])
else:
continue
print('===========================================')
print('我爬完了!!!')
if __name__ == '__main__':
scrapy_ctd_web(drug_name,valid_IP11)