高手請一笑而過。
實體實驗課别人已經做過3、4個了,自己一個還沒做呢。不是咱不想做,而是咱不想起那麼早,并且僅有的一次起得早,但是哈工大的伺服器竟然超負荷,不停重新整理還是不行,不禁感慨這才是真正的“萬馬争過獨木橋“啊!伺服器不給力啊……
好了,廢話少說。其實,我的想法很簡單。寫一個三重循環,不停地送出,直到所有的資料都accepted。其中最關鍵的是送出最後一個頁面,因為送出使用者名和密碼後不需要再通路其他的頁面,是以不需要用到cookis。
這個隻是Python最簡單的應用。核心代碼隻有兩行:
data = urllib.urlencode(each_people)
req = urllib2.Request(url , data)
這裡用到了Python中Web程式設計中的比較重要的子產品urllib和urllib2。其實你也可以用httplib來代替,兩者本質上是一樣的,因為urllib内部的一部分就是用httplib來實作的。
現解釋一下上面的意思:each_people是一個字典,就相當于C++中的multimap、java中的hashMap,其含義是一個人的選課資訊。urllib.urlencode()函數将each_people的格式轉換一下,以便将其作為CGI請求的URL字元串的一部分。關于CGI是什麼大家可以google一下。舉個例子:
>>>import urllib
>>>each_people = {'name' : 'Tom' , 'password' : '12345' , 'class' : 'lab5'}
>>>data = urllib.urlencode(each_people)
>>>print data
結果是:name=Tom&password=12345&class=lab5
第二行看字面意思就知道其實什麼意思了。參數url表示你要送出資料的網站。
那麼怎麼檢視其傳回結果呢?很簡單:
response = urllib2.urlopen(req)
the_page = response.read()
print the_page
看到有幾個人問,就把代碼貼出來吧,有注釋:
#coding=gb2312
import urllib
import urllib2
import re
#要送出資料的網站
url = 'http://……'
#選課人的資訊
info_list = [
{'week' : '9', 'expnumber' : '實驗10' , 'weekday' : '2' , 'exp_class' : '3-4' , 'number' : '10000000' , 'password' : '12345678' } ,
{'week' : '9', 'expnumber' : '實驗10' , 'weekday' : '2' , 'exp_class' : '3-4' , 'number' : '20000000' , 'password' : 'abcdefgh' }
]
#對應的選課人的名字,可以不要,我加上這個的原因是做一個log,記住選課結果
name_list = [ '張三' , '李四']
#記錄對應的是否已經選上,可以用一個 二進制數代替
trace = [ 0 , 0]
#主程式,選課
def submit():
while True:
whether_over = 1
for i , each_people in enumerate(info_list):
if trace[i] == 0 :
whether_over = 0
for j in range(20):
data = urllib.urlencode(each_people)
req = urllib2.Request(url , data)
try:
response = urllib2.urlopen(req)
except urllib2.URLError , e:
continue
else :
the_page = response.read()
#下面這個路徑可以更改,我用的是我的路徑
#這三句是将傳回的網頁寫到檔案中,以友善以後檢索
my_file = open('/home/superior/Documents/WLlog.txt' , 'w+') ;
my_file.write(the_page) ;
my_file.close()
#将剛才的網頁讀到記憶體中
my_file = open('/home/superior/Documents/WLlog.txt' , 'r') ;
buffer = my_file.read()
my_file.close()
#下面用了正規表達式子產品中的search()方法
m = re.search('課程預約成功', buffer)
#如果找到“課程預約成功”字元串了
if m is not None:
result_file = open('/home/superior/Documents/result_log.txt' , 'a+')
#将名字記錄到result_log.txt中
result_file.write(name_list[i] + ' successful/n')
result_file.close()
#将此人從清單中劃去
trace[i] = 1
break
#所有人都選上了
if whether_over == 1:
break
#定義主函數
def main():
submit()
#調用主函數
main()
我認為這個程式效率雖然還不錯,但是我認為還可以再提升一下。主要是打開檔案,讀寫檔案,關閉檔案這幾個步驟耗時。但是goole擺弄了好久,沒找到更好地辦法。有誰找到更好地辦法,請吱一聲。
另外需要說明的是:
1.為了不失廣泛性,info_list這個清單中的資訊,是我舉例用的。具體使用的話,隻需将info_list和url修改一下
2.運作此程式需要預先裝上Python,如何安裝google一下就知道了
*************************************************************************************************************
今天(Oct 17)幫助15位同學選上了課,心裡很高興,娘的,“勝造七級浮屠”啊!
看了看log,每秒選上5個同學,感覺效率很低啊!于是又想了一下改進的辦法。
第一點:
正如前面分析的那樣,主要是打開、讀取、關閉檔案費時。我看了一下the_page和buffer的類型:相同!
print 'buffer' , type( buffer )
print 'the_page' , type( the_page )
結果:
buffer
the_page
是以,果斷的把my_file這個中間檔案給去掉。
第二點:
為每個人循環20遍,這個做法不明智。因為如果目前正在送出的人的資訊根本不可能被accepted,比如學号密碼打錯了,或者選的課程已經滿了(這是極有可能發生的),這時再為此人循環20遍,明顯的是在浪費時間,而且影響了後面人的送出。難道這就是傳說中的“占着茅坑不拉屎”?是以果斷的把最後一個循環去掉。
經過上面的兩點改進,相信效率一定會有極大的提升。
做了一個final版本,暫且貼上吧。
#coding=gb2312
import urllib
import urllib2
import re
import os
url = 'http://……'
info_list = [
{'week' : '9', 'expnumber' : '實驗10' , 'weekday' : '2' , 'exp_class' : '3-4' , 'number' : '10000000' , 'password' : '12345678' } ,
{'week' : '9', 'expnumber' : '實驗10' , 'weekday' : '2' , 'exp_class' : '3-4' , 'number' : '20000000' , 'password' : 'abcdefgh' }
]
name_list = [ '張三' , '李四' ]
trace = [ 0 , 0 ]
def submit():
while True:
whether_over = 1
for i , each_people in enumerate( info_list ):
if trace[ i ] == 0 :
whether_over = 0
data = urllib.urlencode( each_people )
req = urllib2.Request( url , data )
try:
response = urllib2.urlopen( req )
except urllib2.URLError:
continue
else :
the_page = response.read()
m = re.search( '課程預約成功', the_page )
if m is not None:
result_file = open( '/home/superior/Documents/result_log.txt' , 'a+' )
result_file.write( name_list[ i ] + ' successful ' + os.popen( 'date' ).read() + '/n' )
result_file.close()
trace[ i ] = 1
if whether_over == 1:
break
if __name__ == '__main__':
submit()