最近幾天一直在搞爬蟲,爬的是學校的網站,須要登陸。html
大致分爲三步:前端
1. 抓包python
先將打開網頁中的的整個流程,用抓包工具進行抓包,分析各個包中的內容,尤爲重視以POST方式發出去的包,post出的數據/headers/cookies。可以使用Foxfire瀏覽器的一個插件HTTPFox,對包的獲取及內容進行解析。json
2. 模擬登錄瀏覽器
本次對於學校網站的爬去在於模擬登錄,這裏使用的是python中的request模塊。cookie
關於request的模塊可到http://docs.python-requests.org/zh_CN/latest/user/advanced.html#advanced網絡
下面來講此次爬蟲模擬登錄的幾個關鍵步驟:session
建立一個Session對象:app
s=requests.session()
而後,將第一步中post須要獲得的數據獲取到。Post的數據可能不單單是須要輸入的帳號密碼,還有須要在網頁上隱藏的數據。好比此次爬蟲須要輸入的:jsp
postdata={ "username":username, "password":password, "lt":lt, 'dllt':'userNamePasswordLogin', 'execution':execution, '_eventId':'submit', 'rmShown':'1' }
3. 將數據和headers一併傳遞的網絡中:
r2=s.post(self.url,headers=self.headers,data=postdata)
4. 而後就能夠進入登錄後界面了。能夠隨心所欲了,有沒有小激動。
但不要高興的太早,學校成績界面HTML中使用了動態頁面,動態頁面的HTML中是不具備所須要爬去的信息的。拿着該怎麼辦呢,好在天無絕人之路,如今有兩種方法能夠解決:一種是導入動態解析的模塊,進行解析;一種是直接經過分析所抓的包,分析最終頁面的url。網上有不少解決辦法,對於熟悉前端的猿們,這點應該不難。看來學校的界面也不是想爬就能爬的,不經歷風雨怎能見彩虹。
r3=s.get("http://yjs.njupt.edu.cn/epstar/app/template.jsp?mainobj=YJSXT/PYGL/CJGLST/V_PYGL_CJGL_KSCJHZB&tfile=KSCJHZB_CJCX_CD/KSCJHZB_XSCX_CD_BD&filter=V_PYGL_CJGL_KSCJHZB:WID=%275m3b6a22-nlcp49-ia4istlb-1-ia6fcwu4-t7h%27",headers=self.headers)
最終經過get方法將網頁頁面整個down了下來。
5.解析頁面,對於頁面的解析,有不少方式:正則/beautifulsoup等等
6.將所寫的過程封裝成方法進而造成類。
這是最終代碼:
#coding:utf-8 '''爬去教務網站成績及我的姓名學號''' import re import requests import sys import json reload(sys) sys.setdefaultencoding('utf8') #模擬瀏覽器登陸學校教務網 class JiaoWuXiTongHtml(object): def __init__(self): self.url = "http://ids6.njupt.edu.cn/authserver/login?service=http://my.njupt.edu.cn/login.do" self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0'} #模擬登錄並下載頁面 def downloadHtml(self,username,password): s=requests.session() r=s.get(self.url,headers=self.headers) ltlist=re.findall(r'<input type="hidden" name="lt" value="(LT-.*?-cas)"/', r.text, re.S) executionlist = re.findall(r'<input type="hidden" name="execution" value="(e\ds\d)".* ',r.text,re.S) lt = ltlist[0] execution = executionlist[0] #提交數據 postdata={ "username":username, "password":password, "lt":lt, 'dllt':'userNamePasswordLogin', 'execution':execution, '_eventId':'submit', 'rmShown':'1' } r2=s.post(self.url,headers=self.headers,data=postdata) #提交數據進入登錄界面 # print "*"*100 #分隔符 r3=s.get("http://yjs.njupt.edu.cn/epstar/app/template.jsp?mainobj=YJSXT/PYGL/CJGLST/V_PYGL_CJGL_KSCJHZB&tfile=KSCJHZB_CJCX_CD/KSCJHZB_XSCX_CD_BD&filter=V_PYGL_CJGL_KSCJHZB:WID=%275m3b6a22-nlcp49-ia4istlb-1-ia6fcwu4-t7h%27",headers=self.headers) return r3.content #解析爬取得html def parseHtml(self,html): patt1=r'<font id=cj >(.*?)</font>' patt2=r'<font id=kcmc >(.*?)</font>' patt3 = r'''<font id="XM" style='width:210px' value=.*>(.*?)</font>''' patt4 = r'''<font id="XH" style='width:210px' value=.*>(.*?)</font>''' regx1=re.compile(patt1) regx2=re.compile(patt2) regx3=re.compile(patt3) regx4=re.compile(patt4) content1s=re.findall(regx1,html) content2s=re.findall(regx2,html) # name=re.findall(regx3,html)[0]+'name'#由於字典無序,做爲姓名學號的特殊標識 # xuhao=re.findall(regx4,html)[0] list1=[] list2=[] #處理匹配的字符串,統一編碼 for i in content2s: i = i.decode('utf8').rstrip(r' ') list2.append(i) for i in content1s: i = i.decode('utf8') list1.append(i) d = dict(zip(list1,list2))#將數據存在該字典裏 # d[name]=xuhao#將姓名/學號添加到字典 return d #主函數類 class SpiderMain(object): def __init__(self): self.html = JiaoWuXiTongHtml() def craw(self,name,password): htmlpage = self.html.downloadHtml(name,password) print htmlpage data = self.html.parseHtml(htmlpage) return data if __name__ == '__main__': print '\nwelcome to use craw data:' name = raw_input('input username:') password = raw_input('input password:') a = SpiderMain() d = a.craw(name,password) # file1 = open('name.txt','wb+') # file1.write(str(d)) # file1.close() print json.dumps(d).decode("unicode-escape")#顯示中文