最近几天一直在搞爬虫,爬的是学校的网站,须要登陆。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")#显示中文