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