python爬蟲 requests庫學(xué)習(xí)之自動抓取cookies模擬登錄學(xué)校官網(wǎng)

這次講一個很重要的技巧:那就是利用代碼模擬登錄某些網(wǎng)站。

首先我們重點(diǎn)講下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的關(guān)系侧啼,cookiejar是底層庫衣赶,可以形象的把cookiejar看作保存cookie的罐子间唉,cookie里面可以保存很多cookie偏塞。session的實(shí)現(xiàn)調(diào)用了底層cookejar,可以認(rèn)為session對象能把cookie對象自動保存到cookiejar中

使用session對象十分十分方便钉答,我們首先創(chuàng)造session對象础芍,用requests.session()就可以了,然后后面的所有網(wǎng)絡(luò)請求全部用session的get数尿,post函數(shù)等仑性,而不用requests對象的get,post函數(shù)右蹦,這樣session對象能自動保存訪問過的網(wǎng)頁設(shè)置的cookie

理論上我們使用session是不需要知道cookiejar是什么東西的诊杆,因?yàn)樵O(shè)計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('登陸頁面網(wǎng)址', timeout=10, data={'登陸的表單數(shù)據(jù)何陆,字典格式'})
# 用以及保存了cookie的opener對象去訪問別的網(wǎng)頁
response = cookie_opener.open('需要登陸后才能訪問的網(wǎng)頁')

我們再次感受到requests庫的簡便與強(qiáng)大晨汹。。我們這次爬取還是用session

我們在使用爬蟲的時候經(jīng)常會遇到某些必須要求我們登陸才能獲取到信息的情況贷盲,比如淘寶商品信息的爬取淘这。
這時候我們一般有兩種方式,第一種是手動設(shè)置cookies巩剖,具體見上一篇文章铝穷;
這篇文章里我們介紹下另外一種方法:代碼實(shí)現(xiàn)自動抓取cookies然后模擬登陸,這樣做有一個好處佳魔,只要你輸入正確的賬號密碼曙聂,就可以直接獲取到你想要獲取的信息。

廢話不多說鞠鲜,我們直接開始宁脊,然后這次我們選擇的目標(biāo)網(wǎng)站是我的母校的教務(wù)處網(wǎng)站,我準(zhǔn)備從中查詢到成績和課表信息:

我們首先要人工登陸镊尺,注意在登陸之前(就是輸入賬號密碼的那個網(wǎng)頁)打開開發(fā)者工具:
image.png

我們把這個preserve log 勾選上朦佩,這個的意思是保存歷史信息,就是說跳轉(zhuǎn)到新的url后原來界面的network里面的元素還在而不會刷新掉庐氮。

然后我們正確輸入賬號密碼后完成登陸语稠,之后我們在首頁利用開發(fā)者工具分析下網(wǎng)絡(luò)結(jié)構(gòu):
image.png

找到all選項下的一個是POST請求的元素(一般在前面),把詳細(xì)信息拉到最下面會有一個form表單弄砍,這是post請求的參數(shù):
image.png

其中username和password就是你剛剛輸入的賬號和密碼仙畦,下面還有些參數(shù),有的需要有的不需要音婶。

這些是為了安全性創(chuàng)造的一些參數(shù)慨畸,尤其是lt參數(shù),其實(shí)就是一個隨機(jī)數(shù)衣式,每次刷新都不一樣寸士,但是lt參數(shù)你錯一個字母都無法成功登陸檐什,execution參數(shù)是你登陸了幾次的意思,如果你賬號密碼輸入錯誤他就會增加弱卡,比如從e1s1變成了e2s2可能乃正,然后你一直錯,它一直加婶博,最后可能在錯誤的次數(shù)達(dá)到一定程度后就給你上驗(yàn)證碼了瓮具,所以我們最好一次就成功登陸。

從哪里去找到這些參數(shù)呢凡人?----->其實(shí)我也找了好久名党,我當(dāng)時想,既然你 瀏覽器能夠正常獲得挠轴,那么肯定隱藏在某個地方传睹,然后我就去登陸前的頁面打開原網(wǎng)頁尋找:我直接搜索lt,他還真就出現(xiàn)了:
image.png

所以我第一個想啊就是先讓程序抓取這個登陸頁面的lt后忠荞,利用這個lt再去登陸蒋歌。

但是有個小問題:隨著我每次刷新帅掘,lt和execution都是在動態(tài)變化的委煤,這肯定不行(因?yàn)槟阕ト〉谝淮危喈?dāng)于第一次訪問登陸頁面修档,他給你第一次的lt碧绞,你再用第一次的lt去登陸的時候,吱窝,別人的lt在你登陸的過程中就變化了讥邻,生成了第二次的lt),那我們要怎么辦呢院峡? 以及它是根據(jù)什么判斷我們是第幾次訪問到登陸頁面的兴使??

答案就是 cookies

我們在每次進(jìn)入到登陸界面的網(wǎng)站照激,它會給我們設(shè)置一個cookies來判斷我們是第幾次訪問发魄,如果我們賬號密碼輸入錯誤,它的cookes也會變化俩垃,從而導(dǎo)致lt變化励幼。
也就是說,只要我們在獲取到lt后口柳,用當(dāng)時獲取到lt的cookies去發(fā)送登錄請求苹粟,就能正常登陸:
我們先看看cookie與lt的關(guān)系:

第一次請求:
image.png

第二次請求:
image.png

從這里我們就可以看出cookie與lt的關(guān)系,可以這么簡單的理解:一個cookie對應(yīng)一個lt跃闹。

然后我們只要用前面請求lt的cookie去模擬登錄嵌削,它的lt就不會“刷新”毛好。

之后我們利用lt和其他參數(shù)拼接成的data字典傳給post請求的data參數(shù),生成網(wǎng)頁導(dǎo)入本地苛秕,打開后是這樣:
image.png

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

而如果打開后是:
image.png

代表哪里出了問題想帅,要么是data參數(shù)不正確還是啥的场靴,這樣沒成功登陸是保存不了cookies的。

這樣港准,獲取了登陸后的cookies后旨剥,我們就可以用保存了cookies的session對象繼續(xù)去訪問里面的網(wǎng)站,比如成績網(wǎng)站:我們進(jìn)去后查看源網(wǎng)頁浅缸,隨便搜索一門課的成績:
image.png

沒有任何數(shù)據(jù)轨帜。這樣的網(wǎng)站我們已經(jīng)見過很多了,前面的搜狗百度圖片衩椒,都是這樣的蚌父,稱為瀑布流式網(wǎng)頁,Ajax動態(tài)網(wǎng)頁毛萌,我們利用開發(fā)者工具苟弛,抓取數(shù)據(jù):
image.png

在XHR項一個個找,看哪個是返回給我們的數(shù)據(jù)阁将,最后發(fā)現(xiàn)最下面的xscjx.do是成績數(shù)據(jù):
image.png

歐克膏秫,找到目標(biāo)url了,繼續(xù)爬茸鲋选:
image.png

人傻了缤削,我們不是登陸了嗎?怎么回事吹榴?

其實(shí)我在前面已經(jīng)強(qiáng)調(diào)過很多次了亭敢,正常用戶肯定是一個網(wǎng)頁一個網(wǎng)頁往里點(diǎn),而不是直接就訪問這個ajax請求图筹,所以在成績網(wǎng)頁肯定設(shè)置了cookie:
image.png

所以我們還要用session再登陸下這個成績網(wǎng)頁保存cookies:
image.png

然后再獲取數(shù)據(jù)就大功告成:
image.png

注意ajax的那個網(wǎng)頁返回的數(shù)據(jù)是json格式的帅刀。
這種最簡單搞了,直接轉(zhuǎn)成python字典婿斥,然后需要啥爬啥劝篷。
簡單處理下:
image.png

當(dāng)然你可以導(dǎo)入scv表格,做GUI界面民宿,反正數(shù)據(jù)都搞到了娇妓,做啥看興趣了。

比如你可以設(shè)置輸入賬號密碼:


image.png

課表的話類似吧活鹰,哈恰,以前沒搞過只估,現(xiàn)在試試:

確實(shí)差不多,甚至不需要抓取課程首頁設(shè)置的cookies着绷,但是它那個請求是post的:
image.png

這個可能代表是第幾學(xué)期的課表蛔钙,post下就歐克了。 結(jié)果完全沒問題昂:
image.png

當(dāng)然數(shù)據(jù)獲取到了荠医,你怎么去使用就看你的興趣了吁脱。

謝謝觀看@**@

源代碼:

# 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()
        # 給的參數(shù)是登陸網(wǎng)頁,作用是抓取動態(tài)lt,同時保存cookies
        self.set_lt(log_in_url)
        name = input('輸入學(xué)號:')
        psw = input('輸入密碼:')
        self.set_data(name, psw)
        # 模擬登錄
        response = self.post_response(log_in_url, self.data)
        # 這步必須要,成績網(wǎng)站也給我們設(shè)置cookies了
        # 我們首先要獲取成績查詢所在的網(wǎng)址
        # 這步真的搞哭我了....................一把辛酸淚
        '''
        # 這個可以用來搞到所有的可用的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'
        # 只需要訪問這個臨時的網(wǎng)站我們就可以獲得cookies,然后去申請成績數(shù)據(jù)
        temp_url = 'http://ehall.xidian.edu.cn//appShow?appId={}'.format(score_appid)
        response = self.get_response(temp_url)
        # 查成績的json url,開發(fā)者工具抓取
        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對象去訪問別的網(wǎng)頁
response = cookie_opener.open('需要登陸后才能訪問的網(wǎng)頁')
'''

'''
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對象去訪問別的網(wǎng)頁
response = cookie_opener.open('需要登陸后才能訪問的網(wǎng)頁')
'''

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彬向,一起剝皮案震驚了整個濱河市兼贡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娃胆,老刑警劉巖遍希,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異里烦,居然都是意外死亡凿蒜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門胁黑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來废封,“玉大人,你說我怎么就攤上這事别厘∈觯” “怎么了拥诡?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵触趴,是天一觀的道長。 經(jīng)常有香客問我渴肉,道長冗懦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任仇祭,我火速辦了婚禮披蕉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乌奇。我一直安慰自己没讲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布礁苗。 她就那樣靜靜地躺著爬凑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪试伙。 梳的紋絲不亂的頭發(fā)上嘁信,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天于样,我揣著相機(jī)與錄音,去河邊找鬼潘靖。 笑死穿剖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卦溢。 我是一名探鬼主播糊余,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼单寂!你這毒婦竟也來了啄刹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤凄贩,失蹤者是張志新(化名)和其女友劉穎誓军,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疲扎,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昵时,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了椒丧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壹甥。...
    茶點(diǎn)故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖壶熏,靈堂內(nèi)的尸體忽然破棺而出句柠,到底是詐尸還是另有隱情,我是刑警寧澤棒假,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布溯职,位于F島的核電站,受9級特大地震影響帽哑,放射性物質(zhì)發(fā)生泄漏谜酒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一妻枕、第九天 我趴在偏房一處隱蔽的房頂上張望僻族。 院中可真熱鬧,春花似錦屡谐、人聲如沸述么。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽度秘。三九已至,卻和暖如春亭珍,著一層夾襖步出監(jiān)牢的瞬間敷钾,已是汗流浹背枝哄。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阻荒,地道東北人挠锥。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像侨赡,于是被迫代替她去往敵國和親蓖租。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容