【4月20日】使用requests登陸教務處網站並查詢課表
最近上課總是記不住是哪個教室,感覺每次都要人工登陸教務處網站去查教室很麻煩。正好在學習爬蟲,於是想直接寫個爬蟲去幫我查課表資訊豈不美哉?
說幹就幹。使用requests,個人感覺比較好用的第三方庫,基於py3;解析用beautifulsoup。開啟Chorme,登陸南理工的教務處網站並跟蹤登陸過程的網路行為。
可以看見,需要輸入的資訊有三樣。使用者名稱和密碼好辦,主要是驗證碼的及時識別。擬採取的策略為:下載驗證碼檔案到本地,然後再人工輸入。點選登陸,繼續跟蹤網路行為,發現在此輸入的資料(連同其他一些附帶資料)被post到了http://gsmis.njust.edu.cn/中。
進一步檢視這個post的FormData就可以找到這三個資料了,分別為UserName,PassWord以及ValidateCode。
找到了這裡已經解決了驗證碼走那條路(post)以及要到哪裡去(http://gsmis.njust.edu.cn/)的問題,接下來要解決從哪裡來的問題。在HTML上檢查驗證碼的元素,可以發現其src為Public/ValidateCode.aspx?image=一串無關緊要的數字。也就是說要在http://gsmis.njust.edu.cn/Public/ValidateCode.aspx?image=中拿到驗證碼檔案。這樣一來,驗證碼的來龍去脈就可以釐清了,從src中獲取驗證碼連結並下載到本地,再通過post將驗證碼及其他必要資訊傳送http://gsmis.njust.edu.cn/。
登陸之後,用相似的方式分析一下課表查詢時資料以及網路行為,就可以自動課表了(雖然課是真的少,但是事情是真的多啊~~~)。另外,我發現這個方法也很麻煩,還不如直接上網查呢。
下面,直接上程式碼:
# -*- coding: utf-8 -*- """ @author: Tree """ import requests from bs4 import BeautifulSoup # 登入地址,以及查詢課表的地址 LoginUrl = "http://gsmis.njust.edu.cn/UserLogin.aspx?exit=1" class_url = "http://gsmis.njust.edu.cn/Gstudent/Course/StuCourseWeekQuery.aspx" session = requests.session() # 登入主函式 def login(): headerdic = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36', 'Host': 'gsmis.njust.edu.cn', 'Referer': 'http://gsmis.njust.edu.cn/', 'Accept': '*/*', 'Connection': 'Keep-Alive', } postdic = { 'UserName': "學號", 'PassWord': "密碼", 'drpLoginType': '1', '__ASYNCPOST': 'true', 'ScriptManager1': 'UpdatePanel2|btLogin', '__EVENTTARGET': 'btLogin', '__VIEWSTATE': '/wEPDwULLTE5OTkyNTM4MzEPZBYCAgMPZBYGAg0PZBYCZg9kFgICAQ8PFgIeCEltYWdlVXJsBSp+L1B1YmxpYy9WYWxpZGF0ZUNvZGUuYXNweD9pbWFnZT02ODA3OTUyOTFkZAIRD2QWAmYPZBYCAgEPEGRkFgFmZAIVD2QWAmYPZBYCAgEPDxYCHgtOYXZpZ2F0ZVVybAUtfi9QdWJsaWMvRW1haWxHZXRQYXNzd2QuYXNweD9FSUQ9VHVyOHZadXVYa3M9ZGQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFDVZhbGlkYXRlSW1hZ2W5HJlvYqz666q9lGAspojpOWb4sA==', '__EVENTVALIDATION': '/wEdAAoKNGMKLh/WwBcPaLKBGC94R1LBKX1P1xh290RQyTesRQa+ROBMEf7egV772v+RsRJUvPovksJgUuQnp+WD/+4LQKymBEaZgVw9rfDiAaM1opWKhJheoUmouOqQCzlwTSNWlQTw3DcvmMLY3PAqFoA+uFSTy5ozCEG4XBxL/Ykep0cgC/Irwlr9d8VObb8MnYO0GRqRfbdgDIW2dtIsr6rbUIwej/LsqVAg3gLMpVY6UeARlz0=', '__EVENTARGUMENT': '', '__LASTFOCUS': '' } login_header = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Host': 'gsmis.njust.edu.cn', 'Referer': 'http://gsmis.njust.edu.cn/UserLogin.aspx?exit=1', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3067.6 Safari/537.36' } # 執行getCheckCode,將驗證碼資訊存入postdic中 img_url = "http://gsmis.njust.edu.cn/Public/ValidateCode.aspx?image=" postdic = getCheckCode(img_url, postdic, headerdic) # 獲取本週課表,使用get構造帶有引數的訪問 eid = {'EID': 'j747VIAgTbv89k5pIqOcwJMucc!p3AXikfLcF!otxmBkw0iDLfKWdA=='} session.post("http://gsmis.njust.edu.cn/", data=postdic, headers=login_header) sclass = session.get(class_url, params=eid, headers=headerdic) soup = BeautifulSoup(sclass.text, "lxml") print("這周要上的課:") for i in range(len(soup.select('td[rowspan="4"]'))): print(soup.select('td[rowspan="4"]')[i].get_text()) for i in range(len(soup.select('td[rowspan="2"]'))): print(soup.select('td[rowspan="2"]')[i].get_text()) # 獲取驗證碼並將其在本地儲存 def getCheckCode(url, postdic, headerdic): r = session.get(url, headers=headerdic) with open('captcha.jpg', 'wb') as f: f.write(r.content) f.close() captcha = input("please input the captcha\n>") postdic["ValidateCode"] = captcha return postdic if __name__ == '__main__': login()