登陆网站爬虫(保持Cookie不变)

平时常常须要到学校的信息门户去查看课表及其余信息,因而想作一个爬虫 ,能够自动替我登陆而且获得这些信息,因而今天动手写了一个爬虫: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

相关文章
相关标签/搜索