平時常常須要到學校的信息門戶去查看課表及其餘信息,因而想作一個爬蟲 ,能夠自動替我登陸而且獲得這些信息,因而今天動手寫了一個爬蟲:html
首先登陸學校的信息門戶:http://cas.whu.edu.cn/authserver/login?service=http://my.whu.edu.cnpython
而後這裏我隨便輸入帳號名和密碼,來看看登陸時瀏覽器都作了些什麼。這裏我使用的是FireFix瀏覽器以及HttpFox插件,若是用Chrome的話,谷歌下也有很棒的插件,IE的話推薦HTTPWatch。web
從HttpFox中咱們能夠分析得出大概流程,首先就是瀏覽器根據Name獲取到html中表單中的input內容,而後經過post提交到一個服務器地址,而後服務器判斷用戶名密碼是否正確,進而作出相應的響應。接下來咱們就須要知道瀏覽器是把什麼數據提交到了哪裏,咱們點擊httpfox中的第一個步驟:瀏覽器
能夠看到瀏覽器把數據仍是提交到了當前頁面,而且攜帶有Cookie,咱們再看看postdata裏都有什麼服務器
能夠看到postdata中不只有用戶名密碼,還有一些其餘數據,到這裏咱們能夠用Python寫一個爬蟲,只提交用戶名密碼,而後你會發現服務器仍是給你返回一個登陸頁面,這時候咱們就須要考慮lt dllt這些postdata了,但是這些是什麼呢?我查閱了一些資料,lt能夠理解成每一個須要登陸的用戶都有一個流水號。只有有了webflow發放的有效的流水號,用戶才能夠說明是已經進入了webflow流程。不然,沒有流水號的狀況下,webflow會認爲用戶尚未進入webflow流程,從而會從新進入一次webflow流程,從而會從新出現登陸界面。cookie
那麼如何得到這個lt數據呢。咱們回到http://cas.whu.edu.cn/authserver/login?service=http://my.whu.edu.cn,按F12,session
咱們很容易能找到用戶名和密碼的兩個input,咱們在查找input標籤:app
發如今form最下面有這幾個隱藏域,如今咱們已經拿到了流水號,但是還有一個問題:就是我首先發送一個get,而後我拿到這個隱藏域全部value,而後我須要在發送一次post方式,這時候,咱們先前得到的lt值已經再也不是如今的lt值了,因此這個時候咱們就要用requests的session方法來保持cookie不變了,session方法可讓同一個實例發出的全部請求保持相同的cookie。函數
接下來任務就好作了:post
#encode=utf8 ''' Created on 2016年10月15日 @author: WangHui @note: View things from WuHanUniversity ''' import requests from http.cookiejar import CookieJar from bs4 import BeautifulSoup class WHUHelper(object): __loginuri='http://cas.whu.edu.cn/authserver/login?service=http://my.whu.edu.cn' __logindo='http://yjs.whu.edu.cn' #初始化構造函數,帳戶和密碼 def __init__(self,name='',password=''): #帳戶名 if not isinstance(name,str): raise TypeError('請輸入字符串') else: self.name=name if isinstance(password,int): self.password=str(password) elif isinstance(password, str): self.password=password else: raise TypeError('請輸入字符串') #返回一個登錄成功後的Response def __getResponseAfterLogin(self): #模擬一個瀏覽器頭 header={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0'} #保持Cookie不變,而後再次訪問這個頁面 s=requests.Session() #CookieJar能夠幫咱們自動處理Cookie s.cookies=CookieJar() #獲得一個Response對象,可是此時尚未登陸 r=s.get(self.__loginuri,headers=header) #獲得postdata應該有的lt #這裏使用BeautifulSoup對象來解析XML dic={} lt=BeautifulSoup(r.text,'html.parser') for line in lt.form.findAll('input'): if(line.attrs['name']!=None): dic[line.attrs['name']]=line.attrs['value'] params={ 'username':self.name, 'password':self.password, 'dllt':'userNamePasswordLogin', 'lt':dic['lt'], 'execution':dic['execution'], '_eventId':dic['_eventId'], 'rmShown':dic['rmShown']} #使用構建好的PostData從新登陸,以更新Cookie r=s.post(self.__loginuri, data=params,headers=header) #返回登陸後的response return s #獲得研究生信息門戶指定分類下的HTML def __getHtmlOfPerson(self): s=self.__getResponseAfterLogin() personUri='http://yjs.whu.edu.cn/ssfw/index.do#' r=s.get(personUri) return r.text #獲得研究生我的信息 def getPersonInfor(self): s=self.__getResponseAfterLogin() bs=BeautifulSoup(self.__getHtmlOfPerson(),'html.parser') dic={} #獲得基本信息get方式的訪問URL網站 jbxxUri=self.__logindo+bs.find('a',{'text':'基本信息'}).attrs['url'] r=s.get(jbxxUri) bs=BeautifulSoup(r.text,'html.parser') dic['學號']=bs.find('input',{'name':'jbxx.xh'}).attrs['value'] dic['姓名']=bs.find('input',{'name':'jbxx.xm'}).attrs['value'] return dic #獲得我的課表 def getClassInfo(self): #初始化課表 classInfo=[] classTitle=['星期一','星期二','星期三','星期四','星期五','星期六','星期日'] for i in range(13): singleclass=[] for j in range(7): singleclass.append('') classInfo.append(singleclass) #首先獲得登錄後的request s=self.__getResponseAfterLogin() bs=BeautifulSoup(self.__getHtmlOfPerson(),'html.parser') jbxxkb=self.__logindo+bs.find('a',{'text':'個人課表'}).attrs['url'] r=s.get(jbxxkb) bs=BeautifulSoup(r.text,'html.parser') #獲得天天十三節課 trs=bs.find('table',{'class':'table_con'}).findAll('tr',{'class':'t_con'}) for i in range(len(trs)): tds=trs[i].findAll('td') #表示星期幾 j=0 for td in tds: #首先去掉table的行標題和列標題 #根據規律可知,凡是帶有標題的都含有b標籤 if td.find('b')!=None: continue #beautifulsoup會把 解析爲\a0,因此這裏須要先轉碼,而後在編碼 classInfo[i][j]=str(td.get_text()).encode('gbk','ignore').decode('gbk') j=j+1 classInfo.insert(0, classTitle) return classInfo
固然這個類並不完善,我只是想要看到個人課表,若是須要查看其餘信息,可使那個requests再次發送請求,而後用BeautifulSoup4解析便可。
這裏咱們能夠測試一下:
參考文章:
https://my.oschina.net/u/1177799/blog/491645
http://beautifulsoup.readthedocs.io/zh_CN/latest/
http://m.blog.csdn.net/article/details?id=51628649
http://docs.python-requests.org/en/latest/user/advanced/#session-objects