一個新手用python爬武漢理工大學教務系統
學了一點python感覺想寫點東西練練手,python想到的第一個事情就是爬蟲,複雜的網站不會爬一直想找簡單又有趣的網站爬玩玩,最後想到學校的教務系統挺不錯的就…搶課的時候(邪惡)。。。。。廢話不多說直接開始
首先就是登陸教務系統,開啟教務系統,開啟開發者模式,用自己的賬號密碼登陸觀察後臺提交的資料。
找到login檔案點開看,會發現url和提交的表單資訊。。。嘿嘿直接copy過來就可以 關鍵技術,點開其他的會發現後面訪問的頁面都要攜帶登陸的cookie,百度了一下方法,有可以直接複製手動登陸後返回的cookie的但是每次登陸都會返回不同的cookie,每次都要手動登陸一下複製cookie過去,還不如手動登陸算程式的優勢就沒有了。後面找到了一個好的方法建立opener自動攜帶cookie開啟其他頁面。美滋滋。。。。。 方法如下:
# 建立cookie物件儲存cookie
cookie = cookiejar.CookieJar()
# 建立一個cookie處理器
headler = urllib.request.HTTPCookieProcessor(cookie)
# 用處理器建立opener,之後opener就攜帶cookie訪問啦
opener = urllib.request.build_opener(headler)
果真有如此神奇的方法。。。。。 然後還是習慣性的建立一下header來偽裝瀏覽器發出的請求
header = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.\
84 Safari/537.36'
}
再建立一下登陸要提交的資料表單,直接copy上圖過來就歐了。。。。。
data = {
'systemId':'',
'xmlmsg':'',
'userName': userName,
'password': password,
'type' : 'xs'
}
post_data = urllib.parse.urlencode(data).encode('utf-8')#要編碼
然後直接用這些資料建立請求。。。。。完事
#登陸請求的url直接copy上圖裡面的
login_url = 'http://sso.jwc.whut.edu.cn/Certification/login.do'
request_data = urllib.request.Request(login_url, headers=header, data=post_data)
response = opener.open(request_data)
返回一個response資料體,之後解析出來找要找的連線 解析模組很多用自帶的HTMLParse也行,不過python當然要用強大的第三方模組啦,beautifulsoup廣受好評,用起來是真的方便,好評不是刷的,本來想在這裡練習一下正則表示式的不過這個模組真的好用的我都忍不住用了練習正則表示式的心都沒了。。。。。 直接上程式碼
html =BeautifulSoup(response, 'html.parser')
用BeautifulSoup裡的函式尋找成績查詢,選課等連線 這裡以成績查詢為例子 開啟相應體找應該是在圖示的a標籤裡,不確認可以點那個連結看看 直接調函式查詢取出連結
mark_url = html.find(title="成績、績點查詢")['href']
然後發現這個url返回的響應體不是要找的成績單。。。。再點開成績查詢看看。。。找到響應體就是要找的成績單。。。。。。看一下相應的地址和提交的資料,發現地址後面那堆詭異的字元點一次變一次,應該是某次相響應服務返回過來的詭異驗證碼,翻翻前面沒有成績那個響應體果然是那裡 當然是用程式碼把它取出來啦
mark_url = html.find(title="成績、績點查詢")['href']
req = urllib.request.Request(mark_url, headers=header)
resp1 = opener.open(req)
html2 = BeautifulSoup(resp1, 'html.parser')
snkey = html2.find('a', target="navTab",text="成績查詢")['href']
可是怎麼也找不到後面那堆點一次變就變得數字,而且那堆數字在哪頁都有選課什麼得都帶那堆一直變化得數字,重新整理也在變,想想會不會是代表訪問次數的,最後驗證都不是,想過和時間變化的,然後算了一下每隔相同的時間數字的變化量一樣,所以應該是和時間有關係的,但是怎麼也找不到相對應的關係,後來發現好像不用提交那個資料也可以訪問,所以就沒有再找那堆數的規律。 點成績那會發現顯示不完所有的成績,所以還要提交一個顯示頁面數的資料 直接copy到程式
data2 = {
'pageNum': '1',
'numPerPage': '200',
'xh': 'userName',
'snkey': snkey
}
post_data2 = urllib.parse.urlencode(data2).encode('utf-8')
url2 = 'http://202.114.90.180/Score/' + snkey
req2 = urllib.request.Request(url2, headers=header, data=post_data2)
resp2 = opener.open(req2)
響應體就是要找的成績單,最後還是用BeautifulSoup解析出來分離出每一科成績打印出來完事。。。。。。。。成績查詢完畢
html3 = BeautifulSoup(resp2, 'html.parser')
for i in range(len(html3.thead.tr.find_all('th'))):
mat = "{:12}"
print(mat.format(html3.thead.tr.find_all('th')[i].string), end='')
print("\n")
for j in range(len(html3.tbody.find_all('tr', target="sid_cj_id"))):
for k in range(len(html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td'))):
if html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td')[k].string == None:
html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td')[k].string =''
mat = "{:12}"
print(mat.format(html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td')[k].string), end='')
print("\n")
總結果 選課的話和前面一樣找到連線和關鍵引數就可以了 在選課的時候提交的有一個數據來源是要用到後端js傳來的,資料沒看到js也就不怎麼會了,,,,,,,,, addid這個資料是JS傳過來的,其他的都可以在前面找得到,解析出來用就可以。 感覺學校教務處的網是故意簡單設計讓新手練手的吧。。。哈哈。。。。 完整程式碼 密碼錯誤就執行錯誤,沒空寫驗證正確性了
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup
from http import cookiejar
def login(header):
userName = input('輸入學號回車')
password = input('輸入密碼回車')
data = {
'systemId': '',
'xmlmsg': '',
'userName': userName,
'password': password,
'type': 'xs'
}
post_data = urllib.parse.urlencode(data).encode('utf-8')
login_url = 'http://sso.jwc.whut.edu.cn/Certification/login.do'
request_data = urllib.request.Request(login_url, headers=header, data=post_data)
cookie = cookiejar.CookieJar()
headler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(headler)
response = opener.open(request_data)
html =BeautifulSoup(response, 'html.parser')
return opener, html
def get_mark(opener,html,header):
mark_url = html.find(title="成績、績點查詢")['href']
req = urllib.request.Request(mark_url, headers=header)
resp1 = opener.open(req)
html2 = BeautifulSoup(resp1, 'html.parser')
snkey = html2.find('a', target="navTab",text="成績查詢")['href']
data2 = {
'pageNum': '1',
'numPerPage': '200',
'xh': '0121604970404',
'snkey': snkey
}
post_data2 = urllib.parse.urlencode(data2).encode('utf-8')
url2 = 'http://202.114.90.180/Score/' + snkey
req2 = urllib.request.Request(url2, headers=header, data=post_data2)
resp2 = opener.open(req2)
html3 = BeautifulSoup(resp2, 'html.parser')
for i in range(len(html3.thead.tr.find_all('th'))):
mat = "{:12}"
print(mat.format(html3.thead.tr.find_all('th')[i].string), end='')
print("\n")
for j in range(len(html3.tbody.find_all('tr', target="sid_cj_id"))):
for k in range(len(html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td'))):
if html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td')[k].string == None:
html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td')[k].string =''
mat = "{:12}"
print(mat.format(html3.tbody.find_all('tr', target="sid_cj_id")[j].find_all('td')[k].string), end='')
print("\n")
def select_course(opener, html, header):
course_url = html.find(title="學生選課及選課結果查詢、教師查詢選課名單及回覆學生、學院回覆學生諮詢")['href']
req3 = urllib.request.Request(course_url, headers=header)
resp3 = opener.open(req3)
html2 = BeautifulSoup(resp3, 'html.parser')
gxkxk = html2.find(href="gxkxk.do?xnxq=2018-2019-1")['href']
gxkxk_url = 'http://202.114.90.180/Course/' + gxkxk
req4 = urllib.request.Request(gxkxk_url, headers=header)
resp1 = opener.open(req4)
print(resp1.read().decode('utf-8'))
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.\
84 Safari/537.36'
}
opener, html = login(header)
get_mark(opener, html, header)
#select_course(opener, html, header)
結束