其實之前有寫過一篇帖子了 舊帖地址(知乎)
在之前使用教務系統的程序中,偶然一次發現登上教務系統后再退出來的后的登錄網址竟然不需要驗證碼,想著之前有寫過教務系統的爬蟲模擬登錄,沒驗證碼的豈不是更好干(之前那次折騰了好久hhh,后面還是用selenium實作的成績爬取,相比直接爬取,selenium的性能還是比不上畢竟selenium本來就是用來搞自動化的hhh),然后今天閑著就重寫了相同的功能并實作了成績的爬取,
簡單寫一下思路:
- 百度直接搜索出來的教務系統網址是需要驗證碼的,登錄上去之后,再退出來就得到不需要驗證碼的登錄網址
-
點開我們可以發現是需要驗證碼的

-
登錄上去之后再退出,下圖箭頭所指:

-
退出之后,是不是神奇的發現驗證碼不見了(見下圖)哈哈哈,這就是我們要的,

-
- 正式開始我們的分析
- 要分析,肯定是得要看網頁源代碼滴(滑鼠右擊查看網頁源代碼),當然還有F12提供的開發者除錯工具


2.讓我們來看看網頁源代碼- 我們直接找到表單位置,可以注意到當點擊登陸時會觸發函式
submitForm1()==> 好嘞,這不好辦嗎?接下來就讓我們來順騰摸瓜

- 我們復制函式的名稱,并直接ctrl+F查找到函式的位置

- 仔細看看函式,不難發現函式取得到了表單中我們輸入的賬號密碼后都呼叫了
encodeInp()函式,然后組成了一個用變數encoded保存的字串,

3.輸入一個錯誤的賬號密碼,點擊登錄看看開發者除錯工具里面network的情況 - 我們可以注意到紅框中的那個post請求

- 點開后,我們可以看到
cookie,也不難發現encoded字樣,于是我們可以猜測提交的表單中就只有這一個資料,且是登錄驗證的唯一一個資料(比之前那個貼簡單太多了,自己流下了心酸的淚水)

- 接著分析,關掉瀏覽器,重新打開這個不要驗證碼的網址(重新獲得服務端分配的一個cookie),輸入跟剛剛錯誤的賬號密碼再看看那個
encoded有沒有變化,因為根據自己上次的經驗encoded是根據每次分配的cookie不同而變化的.....然后我們發現是沒有變化的!!!是沒有變化的!!!是沒有變化的!!!(重要的事情說三遍,這還不好辦嘛???)

- 我們直接找到表單位置,可以注意到當點擊登陸時會觸發函式
- 繼續順騰摸瓜(戰術性滑稽臉)
- 上面說到點擊網頁上的登錄按鈕時會觸發函式
submitForm1(),然后在這個函式中又會呼叫對賬號密碼進行加工(其實是加密hhh)的encodeInp()函式,我們來找到encodeInp()函式的位置,相同的操作CTRL+F,結果發現函式不在這兒,

- 既然函式不在該頁面的源代碼中,肯定是引進來的js檔案,我們在html的頭部去找引入的檔案,結果發現只引入了一個js檔案,那么我們可以肯定
encodeInp()函式就在該檔案中了,

- 在點開的
conwork.js檔案中搜素encodeInp()函式,找到了!!!

- 上面說到點擊網頁上的登錄按鈕時會觸發函式
- 仔細看看
conwork.js檔案- 看了好一會兒后,發現自己根本看不懂,想著反正是呼叫的這個檔案中的函式,那不如自己去改改代碼呼叫
encodeInp()函式,看能不能呼叫成功,輸出跟除錯工具中一樣的encoded,如果是一樣的我們目的就達到了,加密的程序就是在submitForm1()中呼叫encodeInp()函式,且跟cookie沒關系,也就是說每個人的賬號密碼最后經過加密出來的字串每次都是固定的,

- 這里我就用了自己的賬號密碼,結果可以發現是一樣的,

- 看了好一會兒后,發現自己根本看不懂,想著反正是呼叫的這個檔案中的函式,那不如自己去改改代碼呼叫
- 要分析,肯定是得要看網頁源代碼滴(滑鼠右擊查看網頁源代碼),當然還有F12提供的開發者除錯工具
- 接下來我們就可以寫python代碼了
- 我們先把
conwork.js檔案的代碼和經過更改的且python的execjs庫能呼叫的submitForm1()函式放在一個同一個js檔案里面(這里我把函式名稱換了一下,換成了encode)

- 寫代碼的思路我就不說了,代碼貼在下面了,不過這次我倒是驚奇的發現不加header都能直接登陸,
- 我們先把
import requests
import execjs
from bs4 import BeautifulSoup
class Login:
def __init__(self):
self.url = 'http://jiaowu2.hufe.edu.cn/jsxsd/'
header = {
"Content-Type": "text/html;charset=utf-8",
"Vary": "Accept-Encoding"
}
self.session = requests.session()
self.session.get(self.url,headers=header)
self.username = '****'#賬號
self.password = '****'#密碼
self.GetEncoded()
self.login()
def GetEncoded(self):#該函式獲取加密后的字串
with open(r'conwork.js', encoding='utf-8') as f:
js = execjs.compile(f.read())
self.encoded = js.call('encode', self.username,self.password)
f.close()
return self.encoded
def login(self):
postData = https://www.cnblogs.com/daweiguo/p/{'encoded': self.encoded.strip() # 賬號密碼加密后的東西
}
return self.session.post('http://jiaowu2.hufe.edu.cn/jsxsd/xk/LoginToXk',data=https://www.cnblogs.com/daweiguo/p/postData)
def GetScore(self):#爬取全部課程成績
response = self.session.get('http://jiaowu2.hufe.edu.cn/jsxsd/kscj/cjcx_list')
grade_html = response.text
soup = BeautifulSoup(grade_html, 'html.parser')
tr_lable = soup.find_all("tr")[1:]
all_rows = [] # 該串列存放每一個課程的詳細資訊,
all_rows.append([i.text for i in soup.find_all("th")])
for tr in tr_lable:
tds = tr.find_all('td')
row = []
for td in tds:
row.append(td.text)
all_rows.append(row)
return all_rows
test = Login()
test.login()
print(test.GetScore())#列印爬取的成績
最后,代碼肯定有很多寫的不夠好的地方,望大家多多包含,嘿嘿嘿~
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251413.html
標籤:Python
上一篇:python的變數快取機制
