用python模擬網頁數據提交

jopen 8年前發布 | 16K 次閱讀 Python Python開發

背景

做實驗的時候,需要將獨立測試集的數據與別人server跑出來的結果進行比較,比如下面這個: http://bioinfo.ggc.org/bindn/ 。但是這個server一次性只能提交一個fasta文件,也就是說,我有很多數據的話,就要分多次提交。如果是人工的去操作,會比較耗時,而且工作量特別大,因此這里就需要模擬網頁的數據提交。這就是本文的主要內容,

思路

下面先來理清下思路。我的目的是通過自己構造post數據來實現數據提交。

當模擬在網頁上提交數據時,首先要弄清楚整個數據處理流程,比如發送了什么樣的數據,給誰發的等。那么如果我要在網頁上提交數據的話,肯定是要傳遞參數的,所以我們要知道如何查找這些參數,這是最重要的一點。其次,模擬數據提交,必須要知道提交前的網頁和提交后的網頁,這樣才能將提交后顯示結果網頁保存下來。最后就是數據處理了,使用正則表達式將需要的數據抽取出來。

實踐

參數分析

關于參數,可以從數據包中分析出來,我是使用google自帶的抓包工具分析的,使用ctrl+shift+I快捷鍵,點擊進入Network列,如下圖:

可以看到,當前什么都沒有,下面我將參數填寫完整

當我將數據設置好之后,點擊Submit Query按鈕后,結果如下圖所示:

多了一個bindn.pl文件,我們來看看這個文件的內容,看看headers部分:

和圖二進行比較,你會看到是相互對應。也就是說,這就是我們需要提交的參數:

postData = {'seq' : oneseq,  #oneseq是一個字符串,后面作為一個參數傳遞進來
        'qtype' : 'rna',  
        'vtype' : 'sp',
        'val' : '80',
        'submit' : 'Submit Query' 
        }

而點擊發送后的請求URL和HTML頭內容,如下圖:

所以現在我們可以得到以下這些數據(postData在上面已經分析出來了):

hosturl = 'http://bioinfo.ggc.org/bindn/' 
posturl = 'http://bioinfo.ggc.org/cgi-bin/bindn/bindn.pl' #可以從數據包中分析出,處理post請求的url  
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36',  
           'Referer' : 'http://bioinfo.ggc.org/bindn/'}

Python模擬

分析結束后,我們要構造自己的HTTP數據包,并發送給指定url。我們通過urllib2等幾個模塊提供的API來實現request請求的發送和相應的接收。最后需要編寫一個函數,將自己需要的內容抽取出來。完整代碼和講解如下如下:

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 01 09:34:50 2016

@author: liudiwei
"""

import os 
import urllib  
import urllib2  
import cookielib  
import re

#首先定義一個模擬數據提交的函數,傳入剛剛分析出來的四個參數即可
def scratchData(hosturl, posturl, postData, headers):
    #設置一個cookie處理器,它負責從服務器下載cookie到本地,并且在發送請求時帶上本地的cookie  
    cj = cookielib.LWPCookieJar()  
    cookie_support = urllib2.HTTPCookieProcessor(cj)  
    opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler)  
    urllib2.install_opener(opener) 
    #打開登錄主頁面(他的目的是從頁面下載cookie,這樣我們在再送post數據時就有cookie了,否則發送不成功)
    urllib2.urlopen(hosturl)  
    #需要給Post數據編碼  
    postDataEncode = urllib.urlencode(postData)  
    #通過urllib2提供的request方法來向指定Url發送我們構造的數據,并完成數據發送過程  
    request = urllib2.Request(posturl, postDataEncode, headers)  
    print request  
    response = urllib2.urlopen(request)  
    resultText = response.read()  
    return resultText 

#將一次提交寫到一個函數里面,每次只需傳入一個序列即可,因為其它的參數不變
def BindN(oneseq, outdir):
    #當前頁面,即提交數據頁面
    hosturl = 'http://bioinfo.ggc.org/bindn/' 
    #post數據接收和處理的頁面(我們要向這個頁面發送我們構造的Post數據)  
    posturl = 'http://bioinfo.ggc.org/cgi-bin/bindn/bindn.pl' #可以從數據包中分析出,處理post請求的url  
     #構造header,一般header至少要包含一下兩項。這兩項是從抓到的包里分析得出的。  
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36',  
               'Referer' : 'http://bioinfo.ggc.org/bindn/'}   
    #構造Post數據,他也是從抓大的包里分析得出的。
    postData = {'seq' : oneseq,  
            'qtype' : 'rna',  
            'vtype' : 'sp',
            'val' : '80',
            'submit' : 'Submit Query' 
            } 
    result = scratchData(hosturl, posturl, postData, headers)
    print "+++++", oneseq 
    chainname = oneseq[1:5] + oneseq[6:7]
    outfilename = str(chainname) + '.html'
    fw_result = open(outdir + '/' + outfilename, 'w')
    fw_result.write(result)
    fw_result.close()
    return result, str(chainname)


#使用正則表達式提取數據
def extractBindN(htmlfmt, outfile):
    fw_result = open(outfile, 'w')
    inputdata = htmlfmt.split('\n')
    for i in range(len(inputdata)):
        onedata = inputdata[i].strip()
        if not onedata:
            continue
        if '<' in onedata or '*' in onedata:
            continue
        regText = onedata.split('\t')[0].strip()
        if re.match(r'^\d+$', regText) and True or False:
            fw_result.write(onedata + '\n')
    fw_result.close()

#main方法
if __name__=="__main__":
    oneseq = ">2XD0_A\nMKFYTISSKYIEYLKEFDDKV*NSEDPTYQNPKAFIGIVLEIQGHKYLAPLTSPK\
    KWHNNVKESSLSCFKLHENGVPENQLGLINLKFMIPIIEAEVSLLDLGNMPNTPYKRMLYKQLQFIRANSDKIA\
    SKSDTLRNLVLQGKMQGTCNFSLLEEKYRDFGK"
    outdir = "/home/liudiwei/result" #輸出路徑
    if not os.path.exists(outdir):
        os.mkdir(outdir)
    print outdir
    result, chainname = BindN(oneseq, outdir)
    outfile = outdir + "/" + chainname + ".data" #最終輸出的文件名
    extractBindN(result, outfile)

來自: http://www.csuldw.com/2016/01/01/2016-01-01-extracte-data-from-web-server-in-python/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!