【python】爬取帶CAS教務處信息

起因

一切的一切都要從一個安卓程序說起,我心血來潮想要做一個“易用”的移動端教務處,設計好了實體類,界面等等,突然發現!我沒法直接在安卓裏爬取出教務處的數據。內心一萬隻草泥馬狂奔而過。
看到對於安卓,我實在沒實力在java層面爬取出數據,於是我開始轉戰python,誰知道這才一個大坑的開始。

知識

1、CAS

CAS是Central Authentication Service的縮寫,中央認證服務,一種獨立開放指令協議。

在最開始,我以爲無非就是去教務處,模擬個header,post一下我的賬號和密碼就好了。但誰曾想!學校已經不是當年那個天真的她,在校外想要進入學校內網,都要先過cas中央認證一遍,這就給我造成了很多的坑,她在認證的時候不停的重定向。cookie的內容甚至不是下一個request說需要的。
我會告訴你!在其中一個request的history中,找出了一段cookie和另一個cookie拼接起來進行下一個訪問才成功了嗎?!!

CAS實現單點登錄 好文
https://blog.csdn.net/heyeqingquan/article/details/89885286

過程

1、cas認證+瘋狂重定向
圖片加載失敗,cas頁面
/cas/login.js裏看到了他的加密算法,是MD5 不得不說,這有點點不行啊,現在彩虹表分分鐘幹爆你。
在這裏插入圖片描述
fiddler一頓查,發現了cas頁面post所需要的所有內容,其中的lt藏在頁面中,直接提前出來就好。
然後就是加密 ,發送post請求。但這裏cas有兩次重定向。要用第二次重定向的cookie(history) 那裏面才能拿到webvpn-key,webvpn-name,這樣post才能被接受進入智強的假頁面。。。

2、智強假頁面

爲什麼說是智強的假頁面呢…因爲發現智強原本的賬號密碼登錄已經被棄用了,是根據cas的中央認證得到的cookie直接可以進去。但是他廢棄還不廢棄完,棄掉了一半,如果直接用cas的webvpn-key,webvpn-name走重定向的鏈接,會少一個cookie,你先要模擬智強本身的登錄獲取到辣個可愛的cookie塞進你的僞裝cookie內,再訪問重定向的鏈接。不然他就會給你倒回cas中央認證去,這都是什麼坑,真的神奇。

實際上這纔算進入教務處的頁面,真正的數據還一點沒找到呢!(哭)

代碼如下,已經對大學去敏感化了(其實沒啥用hhhh),但就這樣吧,算是提醒自己。

import requests
from bs4 import BeautifulSoup
import hashlib
import time


# 獲取請求參數中的lt
def getLT():
    lt_url = 'https://jwcnew.webvpn.xxxx.edu.cn/xxxxdx_jsxsd/'
    resp1 = requests.get(lt_url, verify=False)
    soup1 = BeautifulSoup(resp1.text, 'lxml').find_all('input')
    for s in soup1:
        if s.attrs['name'] == 'lt':
            print("############################")
            print("lt" + s.attrs['value'])
            print("############################")
            return s.attrs['value']


# 對密碼進行MD5加密
def md5(pd_str):
    m = hashlib.md5(password.encode("utf-8"))
    return m.hexdigest()


# 獲取登錄教務處ticket
def getTicket(html_text):
    soup = BeautifulSoup(html_text, 'lxml').find('a')
    # print(soup.attrs['href'])
    return soup.attrs['href']


url = 'https://cas.webvpn.xxxx.edu.cn/cas/login'
payload = {'encodedService': 'https%3A%2F%2Fwebvpn.xxxx.edu.cn%2fusers%2fauth%2fcas%2fcallback%3furl',
           'service': 'https://webvpn.xxxx.edu.cn/users/auth/cas/callback?url',
           'serviceName': 'null',
           'loginErrCnt': '0',
           'username': '',
           'password': '',
           'lt': ''}

username = '201xxxxx17'
password = 'xxxxxxxxxx'

payload['username'] = username
payload['password'] = md5(password)
payload['lt'] = getLT()
print("Let me sleep for 2 seconds,zzzzZZZ")
time.sleep(2)
print("Was a nice sleep, now let me continue...")

# 獲取登陸ticket
ticket_response = requests.post(url, data=payload, verify=False)
url_ticket = getTicket(ticket_response.text)

# 獲取選課頁面的cookie,後面的選課請求都會在header中設置cookie,沒有cookie將無法登陸選課頁面和選課操作
# 學校的cas會重定向兩次 要用第二次重定向的cookie 那裏面纔有vpn-key
nextreq = requests.get(url_ticket, verify=False)
cookie_need = str(nextreq.history[1].headers.get('Set-Cookie'))
print(cookie_need)

# 進入智強教務處界面
cas_select_class_url = "https://jwcnew.webvpn.xxx.edu.cn/xxxxdx_jsxsd/"
headers = {'Cookie': cookie_need}
jwc_html = requests.get(cas_select_class_url, headers=headers, verify=False)
print("####進入智強教務處界面#######")
print(jwc_html.text.find('title'))
print("############################")

# 遍歷重組出新的cookie
be_re_cookies1 = jwc_html.cookies.items()
be_re_cookies = nextreq.history[1].cookies.items()

re_cookie = ''
for name, value in be_re_cookies:
    if name == "_astraeus_session":
        continue
    else:
        re_cookie += '{0}={1};'.format(name, value)
for name, value in be_re_cookies1:
    re_cookie += '{0}={1};'.format(name, value)
print("########重組後cookie########")
print(re_cookie)
print("############################")
# 登錄智強教務處 吐槽一波 竟然沒加密 不過想着有cas 的確無所謂了吧
# 需要 cookie有 UM_distinctid _webvpn_key webvpn_username JSESSIONID 四個
newheader = {'Cookie': re_cookie}
PostData = {'USERNAME': username, 'PASSWORD': password}
Login_post = requests.post("https://jwcnew.webvpn.xxxx.edu.cn/xxxxdx_jsxsd/xk/LoginToXk", data=PostData,
                           headers=newheader, verify=False)
time.sleep(1)
login_get = requests.get('https://jwcnew.webvpn.xxxx.edu.cn/xxxxdx_jsxsd/framework/xsMain.jsp', headers=newheader,
                         verify=False)
# print(Login_post.text)
print(login_get.text)
# 成功進入教務處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章