zoukankan      html  css  js  c++  java
  • 登录网站爬虫(保持Cookie不变)

    平时经常需要到学校的信息门户去查看课表及其他信息,于是想做一个爬虫 ,可以自动替我登录并且得到这些信息,于是今天动手写了一个爬虫:

    首先登录学校的信息门户:http://cas.whu.edu.cn/authserver/login?service=http://my.whu.edu.cn

    然后这里我随便输入账号名和密码,来看看登录时浏览器都做了些什么。这里我使用的是FireFix浏览器以及HttpFox插件,如果用Chrome的话,谷歌下也有很棒的插件,IE的话推荐HTTPWatch。

    从HttpFox中我们可以分析得出大概流程,首先就是浏览器根据Name获取到html中表单中的input内容,然后通过post提交到一个服务器地址,然后服务器判断用户名密码是否正确,进而做出相应的响应。接下来我们就需要知道浏览器是把什么数据提交到了哪里,我们点击httpfox中的第一个步骤:

    可以看到浏览器把数据还是提交到了当前页面,并且携带有Cookie,我们再看看postdata里都有什么

     

    可以看到postdata中不仅有用户名密码,还有一些其他数据,到这里我们可以用Python写一个爬虫,只提交用户名密码,然后你会发现服务器还是给你返回一个登录页面,这时候我们就需要考虑lt dllt这些postdata了,可是这些是什么呢?我查阅了一些资料,lt可以理解成每个需要登录的用户都有一个流水号。只有有了webflow发放的有效的流水号,用户才可以说明是已经进入了webflow流程。否则,没有流水号的情况下,webflow会认为用户还没有进入webflow流程,从而会重新进入一次webflow流程,从而会重新出现登录界面。

    那么如何获得这个lt数据呢。我们回到http://cas.whu.edu.cn/authserver/login?service=http://my.whu.edu.cn,按F12,

    我们很容易能找到用户名和密码的两个input,我们在查找input标签:

    发现在form最下面有这几个隐藏域,现在我们已经拿到了流水号,可是还有一个问题:就是我首先发送一个get,然后我拿到这个隐藏域所有value,然后我需要在发送一次post方式,这时候,我们先前获得的lt值已经不再是现在的lt值了,所以这个时候我们就要用requests的session方法来保持cookie不变了,session方法可以让同一个实例发出的所有请求保持相同的cookie。

    接下来任务就好做了:

    #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

  • 相关阅读:
    E-Eating Together(POJ 3670)
    F-Dining Cows(POJ 3671)
    I-MooFest(POJ 1990)
    A-Apple Catching(POJ 2385)
    H-The Cow Lineup(POJ 1989)
    LOOPS(HDU 3853)
    Card Collector(HDU 4336)
    Help Me Escape (ZOJ 3640)
    Collecting Bugs(POJ 2096)
    c#大圣之路笔记——c# 从DataGrid中导出数据 Session
  • 原文地址:https://www.cnblogs.com/wzxwhd/p/5966563.html
Copyright © 2011-2022 走看看