python爬虫 requests库学习之自动抓取cookies模拟登录学校官网

这次讲一个很重要的技巧:那就是利用代码模拟登录某些网站。

首先我们重点讲下session以及cookiejar:官方文档

"""A Requests session.

    Provides cookie persistence, connection-pooling, and configuration.

    Basic Usage::

      >>> import requests
      >>> s = requests.Session()
      >>> s.get('https://httpbin.org/get')
      <Response [200]>

    Or as a context manager::

      >>> with requests.Session() as s:
      >>>     s.get('https://httpbin.org/get')
      <Response [200]>
    """

大意是说session对象具有自动保存cookie等功能

cookiejar:

r"""HTTP cookie handling for web clients.

This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library.

Docstrings, comments and debug strings in this code refer to the
attributes of the HTTP cookie system as cookie-attributes, to distinguish
them clearly from Python attributes.

Class diagram (note that BSDDBCookieJar and the MSIE* classes are not
distributed with the Python standard library, but are available from
http://wwwsearch.sf.net/):

                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

"""

讲下cookiejar和session的关系,cookiejar是底层库,可以形象的把cookiejar看作保存cookie的罐子,cookie里面可以保存很多cookie。session的实现调用了底层cookejar,可以认为session对象能把cookie对象自动保存到cookiejar中

使用session对象十分十分方便,我们首先创造session对象,用requests.session()就可以了,然后后面的所有网络请求全部用session的get,post函数等,而不用requests对象的get,post函数,这样session对象能自动保存访问过的网页设置的cookie

理论上我们使用session是不需要知道cookiejar是什么东西的,因为设计requests的人早就帮我们封装好了一切。这里我还是讲下cookiejar的用法

from http import cookiejar
from urllib import request

cookie_jar = cookiejar.CookieJar()
cookie_handler = request.HTTPCookieProcessor(cookie_jar)
cookie_opener = request.build_opener(cookie_handler)
# cookiejar保存cookie
cookie_opener.open('登陆页面网址', timeout=10, data={'登陆的表单数据,字典格式'})
# 用以及保存了cookie的opener对象去访问别的网页
response = cookie_opener.open('需要登陆后才能访问的网页')

我们再次感受到requests库的简便与强大。。我们这次爬取还是用session

我们在使用爬虫的时候经常会遇到某些必须要求我们登陆才能获取到信息的情况,比如淘宝商品信息的爬取。
这时候我们一般有两种方式,第一种是手动设置cookies,具体见上一篇文章;
这篇文章里我们介绍下另外一种方法:代码实现自动抓取cookies然后模拟登陆,这样做有一个好处,只要你输入正确的账号密码,就可以直接获取到你想要获取的信息。

废话不多说,我们直接开始,然后这次我们选择的目标网站是我的母校的教务处网站,我准备从中查询到成绩和课表信息:

我们首先要人工登陆,注意在登陆之前(就是输入账号密码的那个网页)打开开发者工具:
image.png

我们把这个preserve log 勾选上,这个的意思是保存历史信息,就是说跳转到新的url后原来界面的network里面的元素还在而不会刷新掉。

然后我们正确输入账号密码后完成登陆,之后我们在首页利用开发者工具分析下网络结构:
image.png

找到all选项下的一个是POST请求的元素(一般在前面),把详细信息拉到最下面会有一个form表单,这是post请求的参数:
image.png

其中username和password就是你刚刚输入的账号和密码,下面还有些参数,有的需要有的不需要。

这些是为了安全性创造的一些参数,尤其是lt参数,其实就是一个随机数,每次刷新都不一样,但是lt参数你错一个字母都无法成功登陆,execution参数是你登陆了几次的意思,如果你账号密码输入错误他就会增加,比如从e1s1变成了e2s2可能,然后你一直错,它一直加,最后可能在错误的次数达到一定程度后就给你上验证码了,所以我们最好一次就成功登陆。

从哪里去找到这些参数呢?----->其实我也找了好久,我当时想,既然你 浏览器能够正常获得,那么肯定隐藏在某个地方,然后我就去登陆前的页面打开原网页寻找:我直接搜索lt,他还真就出现了:
image.png

所以我第一个想啊就是先让程序抓取这个登陆页面的lt后,利用这个lt再去登陆。

但是有个小问题:随着我每次刷新,lt和execution都是在动态变化的,这肯定不行(因为你抓取第一次,相当于第一次访问登陆页面,他给你第一次的lt,你再用第一次的lt去登陆的时候,,别人的lt在你登陆的过程中就变化了,生成了第二次的lt),那我们要怎么办呢? 以及它是根据什么判断我们是第几次访问到登陆页面的??

答案就是 cookies

我们在每次进入到登陆界面的网站,它会给我们设置一个cookies来判断我们是第几次访问,如果我们账号密码输入错误,它的cookes也会变化,从而导致lt变化。
也就是说,只要我们在获取到lt后,用当时获取到lt的cookies去发送登录请求,就能正常登陆:
我们先看看cookie与lt的关系:

第一次请求:
image.png

第二次请求:
image.png

从这里我们就可以看出cookie与lt的关系,可以这么简单的理解:一个cookie对应一个lt。

然后我们只要用前面请求lt的cookie去模拟登录,它的lt就不会“刷新”。

之后我们利用lt和其他参数拼接成的data字典传给post请求的data参数,生成网页导入本地,打开后是这样:
image.png

就代表你成功登陆了,可以保存登陆后的cookies。

而如果打开后是:
image.png

代表哪里出了问题,要么是data参数不正确还是啥的,这样没成功登陆是保存不了cookies的。

这样,获取了登陆后的cookies后,我们就可以用保存了cookies的session对象继续去访问里面的网站,比如成绩网站:我们进去后查看源网页,随便搜索一门课的成绩:
image.png

没有任何数据。这样的网站我们已经见过很多了,前面的搜狗百度图片,都是这样的,称为瀑布流式网页,Ajax动态网页,我们利用开发者工具,抓取数据:
image.png

在XHR项一个个找,看哪个是返回给我们的数据,最后发现最下面的xscjx.do是成绩数据:
image.png

欧克,找到目标url了,继续爬取:
image.png

人傻了,我们不是登陆了吗?怎么回事?

其实我在前面已经强调过很多次了,正常用户肯定是一个网页一个网页往里点,而不是直接就访问这个ajax请求,所以在成绩网页肯定设置了cookie:
image.png

所以我们还要用session再登陆下这个成绩网页保存cookies:
image.png

然后再获取数据就大功告成:
image.png

注意ajax的那个网页返回的数据是json格式的。
这种最简单搞了,直接转成python字典,然后需要啥爬啥。
简单处理下:
image.png

当然你可以导入scv表格,做GUI界面,反正数据都搞到了,做啥看兴趣了。

比如你可以设置输入账号密码:


image.png

课表的话类似吧,,以前没搞过,现在试试:

确实差不多,甚至不需要抓取课程首页设置的cookies,但是它那个请求是post的:
image.png

这个可能代表是第几学期的课表,post下就欧克了。 结果完全没问题昂:
image.png

当然数据获取到了,你怎么去使用就看你的兴趣了。

谢谢观看@**@

源代码:

# coding='utf-8'

import requests
from lxml import etree


class Spider:
    def __init__(self, url='', path=''):
        self.url = url if url else ''
        self.path = path if path else ''
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
        }

    def get_response(self, url):
        return self.session.get(url, headers=self.headers)

    # 模拟登录,保存cookie
    def post_response(self, url, data):
        return self.session.post(url, headers=self.headers, data=data)

    def get_etree(self, xml):
        return etree.HTML(xml)

    def parse_data(self, target, fmt):
        return target.xpath(fmt)

    def set_data(self, name='', psw=''):
        self.data = {
            'username': name if name else '17030140051',
            'password': psw if psw else 'ForeverLove520',
            'lt': self.lt,
            'execution': 'e1s1',
            '_eventId': 'submit',
            'rmShown': '1',
        }

    def set_lt(self, url):
        response = self.get_response(url)
        target = self.get_etree(response.content.decode('utf-8'))
        result_list = self.parse_data(target, r'//input[@name="lt"]')
        self.lt = result_list[0].get('value')

    def start(self):
        log_in_url = 'http://ids.xidian.edu.cn/authserver/login?service=http%3A%2F%2Fehall.xidian.edu.cn%2Flogin%3Fservice%3Dhttp%3A%2F%2Fehall.xidian.edu.cn%2Fnew%2Findex.html'
        self.session = requests.session()
        # 给的参数是登陆网页,作用是抓取动态lt,同时保存cookies
        self.set_lt(log_in_url)
        name = input('输入学号:')
        psw = input('输入密码:')
        self.set_data(name, psw)
        # 模拟登录
        response = self.post_response(log_in_url, self.data)
        # 这步必须要,成绩网站也给我们设置cookies了
        # 我们首先要获取成绩查询所在的网址
        # 这步真的搞哭我了....................一把辛酸泪
        '''
        # 这个可以用来搞到所有的可用的app
        all_useable_url = 'http://ehall.xidian.edu.cn/jsonp/getUserAllUsableApp?searchKey=&_=1585880169428'
        response = self.get_response(all_useable_url)
        all_apps = response.json()['data']
        for each in all_apps:
            # 查成绩:
            if each['appName'] == '成绩查询':
                score_appid = each['appId']
                break
        '''
        score_appid = '4768574631264620'
        # 只需要访问这个临时的网站我们就可以获得cookies,然后去申请成绩数据
        temp_url = 'http://ehall.xidian.edu.cn//appShow?appId={}'.format(score_appid)
        response = self.get_response(temp_url)
        # 查成绩的json url,开发者工具抓取
        self.url = 'http://ehall.xidian.edu.cn/jwapp/sys/cjcx/modules/cjcx/xscjcx.do'
        response = self.get_response(self.url)
        score_list = response.json()['datas']['xscjcx']['rows']
        print('\n\n成绩:\n')
        for each in score_list:
            print(each['KCM'], ":", each['ZCJ'])

        print('\n\n\n____________________________\n\n\n课表:\n')

        course_end_url = 'http://ehall.xidian.edu.cn/jwapp/sys/wdkb/modules/xskcb/xsllsykb.do'
        response = self.post_response(course_end_url, {'XNXQDM': '2019-2020-2'})
        course_list = response.json()['datas']['xsllsykb']['rows']
        for each in course_list:
            print(each['KCM'], ':', each['YPSJDD'])

Spider().start()

'''
from http import cookiejar
from urllib import request

cookie_jar = cookiejar.CookieJar()
cookie_handler = request.HTTPCookieProcessor(cookie_jar)
cookie_opener = request.build_opener(cookie_handler)
# cookiejar保存cookie
cookie_opener.open('https://image.baidu.com', timeout=10, data={'键':'值'})
# 用以及保存了cookie的opener对象去访问别的网页
response = cookie_opener.open('需要登陆后才能访问的网页')
'''

'''
from http import cookiejar
from urllib import request

cookie_jar = cookiejar.CookieJar()
cookie_handler = request.HTTPCookieProcessor(cookie_jar)
cookie_opener = request.build_opener(cookie_handler)
# cookiejar保存cookie
cookie_opener.open('https://image.baidu.com', timeout=10, data={'键':'值'})
# 用以及保存了cookie的opener对象去访问别的网页
response = cookie_opener.open('需要登陆后才能访问的网页')
'''

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容