今晚運用剛學的post請求的知識,爬取了學校系統中的課程表,雖然很easy,但對於我來說還是件很有成就感的事~
首先這是我們學校的教務系統的全校課程表界面,可以看到,如果要獲取所有的課程表的話,基本就是選取每個學年學期的每個開課單位,並進行查詢,將查詢結果的每一頁內容爬取下來,最終整合到一起,就ok了。其他的選項,如上課周次、星期、課程性質等等,不用選擇,默認就是全部。
而對於各個學年學期,各個開課單位,以及各個頁碼,則就是一個循環的事兒。下面就着手核心部分。
通過F12在瀏覽器控制台中的分析,很容易發現含有要尋找信息的條目。
發現請求方式為POST。(由於我以前練習的都是GET請求,所以當我發現不同學院課程表的url竟然都是相同時,才發覺是POST方式233)
而且是Request Payload 形式的POST請求,而不是Form Data了,但正常處理。(哼,還以為什么呢,第一次見到嚇了本小白一跳,於是學習了這篇文章:python爬蟲如何POST request payload形式的請求。
請求部分代碼如下,其中對payloadData的處理上面的鏈接中給了好幾種方式,都可以。params就是上圖的Query String Parameters,復制即可。不過headers我最初挑了好幾個,卻總是相應無內容,一氣之下(哼!)把request headers全部copy過來,大成功!
payloadData = {"nj":"","zc":"","jcList":[],"jczy003id":"","kkdwid":"100700","jczy013id":"2020-2021-1","jczy004id":"","jczy010id":"","kcname":"","jsname":"","skls_name":"","jczy002id":"","xqList":[],"jczy008id":"","pkgl002id":"c1343bd90000WH","kclbcode":"","sctype":"zgrmdx","sfcxjxdgcode":"1","page":{"pageIndex":3,"pageSize":10,"orderBy":"[{ \"field\": \"kcbh\", \"sortType\": \"asc\"},{ \"field\": \"id\", \"sortType\": \"asc\"}]","conditions":"QZDATASOFTJddJJVIJY29uZGl0aW9uR3JvdXAlMjIlM0ElNUIlN0IlMjJsaW5rJTIyJTNBJTIyYW5kJTIyJTJDJTIyY29uZGl0aW9uJTIyJTNBJTVCJTVEJTdEyTTECTTE"}}
r = requests.post(url, data=json.dumps(payloadData), headers=headers,params=params)
r.json()
下面是返回的結果
{'errorCode': 'success', 'errorMessage': 'success', 'errorMessageParam': [], 'data': {'rowCount': 116, 'items': [{'xsfl1': ' 36(1-17)', 'skdx_name': '2019工商管理-法學實驗班1班,2019新聞學-法學實驗班1班,2018新聞學-法學實驗班1班,2019級法學本科一班,2019級法學本科三班,2019級法學本科二班', 'xsfl2': None, 'pklb_name': '法學院排課', 'xsfl3': None, 'xsfl4': None, 'bkxt004id': 'c1343d070000Xj', 'xsfl5': None, 'tk_name': '否', 'xsfl6': None, 'jhxs': 36, 'ktmc_name': '國際法02班',
下面略
}
對此進行處理就ok了。那么怎么切換到不同的學院、不同的學期的課程表呢?這里再看一下request payload的數據,下面是經過格式化顯示了的。可以發現,里面的參數寫的很清楚,只需要根據情況稍稍改動就可以了。
{nj: "", zc: "", jcList: [], jczy003id: "", kkdwid: "100700", jczy013id: "2020-2021-1", jczy004id: "",…} jcList: [] jczy002id: "" ###這些空的引號表示沒選,即默認全部 jczy003id: "" jczy004id: "" jczy008id: "" jczy010id: "" jczy013id: "2020-2021-1" ###這是時間信息,意為2020-2021學年秋季學期(用1表示),春季學期則用2表示。 jsname: "" kclbcode: "" kcname: "" kkdwid: "100700" ###即開課單位id,因此只需要獲得所有學院的id,就可以進行for循環了 nj: "" page: {pageIndex: 2, pageSize: 30,…} conditions: "QZDATASOFTJddJJVIJY29uZGl0aW9uR3JvdXAlMjIlM0ElNUIlN0IlMjJsaW5rJTIyJTNBJTIyYW5kJTIyJTJDJTIyY29uZGl0aW9uJTIyJTNBJTVCJTVEJTdEyTTECTTE" orderBy: "[{ "field": "kcbh", "sortType": "asc"},{ "field": "id", "sortType": "asc"}]" pageIndex: 2 ###這里是頁碼,下一條是每頁顯示條數(這個沒法改成比如300這樣的大數字,因為在頁面的選項卡里有最大50這個限制) pageSize: 30 pkgl002id: "c1343bd90000WH" #這些參數發現都是固定不變的,不用管它們 sctype: "zgrmdx" sfcxjxdgcode: "1" skls_name: "" xqList: [] zc: ""
至於開課學院的id信息,可以從另一個url很方便地獲取到(真的很工整呢,愛了!)其實這里包含了所有的id信息,包括學期id。
這樣就萬事具備了!嗯,連東風都齊全了。不過后面我就沒再寫,有了思路框架,內容則水到渠成,什么時候想寫再說吧哈哈。
不過剛才過了一段時間再次查詢,出現了錯誤提示,說Token過期,不過這對爬取全校課程表應該沒什么影響,因為有效期還是很長的,應該有二十分鍾左右,對獲取全部信息來說完全足夠了。
這篇文章的原理其實非常簡單吶,不過寫得像日記一樣2333,感覺還是很有趣的!
以及一些有關的學習鏈接:
Python學習筆記:requests請求傳遞Query String Parameters參數及提交From Data數據。