RexYuan / courseNTNU

(Discontinued) NTNU course rating catalog.
The Unlicense
1 stars 0 forks source link

Real Time Scraping Problem - Search Requires Session #25

Closed RexYuan closed 8 years ago

RexYuan commented 8 years ago

為了能夠順利刮到人數相關資料,如:限修人數、授權碼人數、保留新生人數、選課人數、已分發人數、未分發人數、授權碼選課人數、交換生選課人數、不佔名額生人數,不能再以開課查詢系統搜索,必須以選課系統才能得到所有資訊,而同時這也代表即時更新人數的可能性。參考以下範例:

TIME: 2015/8/21(Fri.) 1:54 P.M. 查詢資工系本學期開課,辨識出選課系統資料來源為

http://cos2.ntnu.edu.tw/AasEnrollStudent/CourseQueryCtrl?action=showGrid&_dc=1440135269677&serialNo=&chnName=&teacher=&deptCode=SU47&formS=&class1=&generalCore=&notFull=0&courseCode=&checkWkSection10=0&checkWkSection11=0&checkWkSection12=0&checkWkSection13=0&checkWkSection14=0&checkWkSection15=0&checkWkSection16=0&checkWkSection17=0&checkWkSection18=0&checkWkSection19=0&checkWkSection110=0&checkWkSection111=0&checkWkSection112=0&checkWkSection113=0&checkWkSection114=0&checkWkSection20=0&checkWkSection21=0&checkWkSection22=0&checkWkSection23=0&checkWkSection24=0&checkWkSection25=0&checkWkSection26=0&checkWkSection27=0&checkWkSection28=0&checkWkSection29=0&checkWkSection210=0&checkWkSection211=0&checkWkSection212=0&checkWkSection213=0&checkWkSection214=0&checkWkSection30=0&checkWkSection31=0&checkWkSection32=0&checkWkSection33=0&checkWkSection34=0&checkWkSection35=0&checkWkSection36=0&checkWkSection37=0&checkWkSection38=0&checkWkSection39=0&checkWkSection310=0&checkWkSection311=0&checkWkSection312=0&checkWkSection313=0&checkWkSection314=0&checkWkSection40=0&checkWkSection41=0&checkWkSection42=0&checkWkSection43=0&checkWkSection44=0&checkWkSection45=0&checkWkSection46=0&checkWkSection47=0&checkWkSection48=0&checkWkSection49=0&checkWkSection410=0&checkWkSection411=0&checkWkSection412=0&checkWkSection413=0&checkWkSection414=0&checkWkSection50=0&checkWkSection51=0&checkWkSection52=0&checkWkSection53=0&checkWkSection54=0&checkWkSection55=0&checkWkSection56=0&checkWkSection57=0&checkWkSection58=0&checkWkSection59=0&checkWkSection510=0&checkWkSection511=0&checkWkSection512=0&checkWkSection513=0&checkWkSection514=0&checkWkSection60=0&checkWkSection61=0&checkWkSection62=0&checkWkSection63=0&checkWkSection64=0&checkWkSection65=0&checkWkSection66=0&checkWkSection67=0&checkWkSection68=0&checkWkSection69=0&checkWkSection610=0&checkWkSection611=0&checkWkSection612=0&checkWkSection613=0&checkWkSection614=0&action=showGrid&actionButton=add&page=1&start=0&limit=999999

經分析解讀後,可以看到以上皆帶來非常多有趣的暗示,包含學習選課模擬的方法,而其回傳值也非常易解讀,其中一門資訊安全的課程節錄如下:

{"acadmTerm":"1","acadmYear":"104","authorizeP":20,"chnName":"資訊安全","class1":"9","courseCode":"CSC0072","courseGroup":"","courseKind":"半","credit":"3.0","deptCode":"SU47","deptGroup":"","engTeach":"否","formS":"","insDeptCode":"SU47","limitCountH":50,"moocs":"N","optionCode":"選修","serialNo":"3283","sex_restrict":"","teacher":"陳善泰","timeInfo":"二 2-4 公館 S302,","v_chn_name":"資訊安全","v_class1":"大碩合開","v_comment":" ","v_deptChiabbr":"資工系","v_deptGroup":"","v_error":"","v_is_Full":"","v_limitCourse":"◎限大三大四 ◎限碩一碩二碩三以上修習","v_phase":"","v_priority":0,"v_release_time":"","v_reserve_count":0,"v_stage":0,"v_stfseld":30,"v_stfseld_auth":0,"v_stfseld_deal":25,"v_stfseld_exchange":0,"v_stfseld_undeal":5,"v_stfseld_unfull":0}

其中許多資料在開課系統之中就以能夠取得,不過依然能夠從中發現到我們感興趣的人數部分,甚至其他意義不明的,以下為這些變數列表和部分意義臆測:

名稱 意義
authorizeP 20 授權碼人數
limitCountH 50 限修人數
v_error
v_is_Full 額滿?
v_phase 選課階段相關?
v_priority 0 保留新生?
v_release_time 開始選課時間?
v_reserve_count 0 保留新生人數?
v_stage 0
v_stfseld 30 選課人數
v_stfseld_auth 0 授權碼選課人數
v_stfseld_deal 25 已分發人數
v_stfseld_exchange 0 交換生選課人數
v_stfseld_undeal 5 未分發人數
v_stfseld_unfull 0 不佔名額生人數

問題是 ...

不過,經嘗試後很快地發現,選課系統有某種拒絕未登入 client 直接對其作 query 的機制。如果以 Chrome 無痕式頁面嘗試,馬上發現到選課系統會回傳「錯誤訊息 不合法執行選課系統」,@jaidTw 提到這是因為其的 session 設計。必須解決該問題所有上述提到的可能才能實現。

RexYuan commented 8 years ago

考慮到 session 機制,嘗試研究識別用戶的 session id,並在 Chrome 中發現 cos2.ntnu.edu.tw 中有一個 cookie 名為 JSESSIONID,不過注意到該 cookie 的 expire 時間在 When the browsing session ends,path 在多次嘗試時不一定,也開了 HttpOnly。目前仍無法在任何地方重現直接以 browser 進行 request 的回傳,不管是利用 php curl 或是其他的程式。

jaidTw commented 8 years ago

此問題理論上可用cURL進行模擬解決,瓶頸在於伺服器有Captcha機制,目前未知是否有方法可識別或繞過

jaidTw commented 8 years ago

@RexYuan 發現,可以由無障礙輸入輔助功能獲得驗證碼的純文字形式, 分析後發現,向http://cos1.ntnu.edu.tw/AasEnrollStudent/ImageBoxFromIndexCtrl 送出請求,即可獲得包含驗證碼之JSON資料。 範例如下:

{success:true,msg:"rqku"}

師大的Captcha根本形同虛設Orz

wildskyf commented 8 years ago

太 hack 啦XDDDD

jaidTw commented 8 years ago

一路試到天亮算是成功了,先貼code去睡覺, https://gist.github.com/jaidTw/0f65496b054f35ccf12f 明天醒來再整理和補充…

jaidTw commented 8 years ago

資料已經整理至wiki,上面連結的code也已重構過。

RexYuan commented 8 years ago

觀察來自選課系統資料,並使用來自選課系統資料節錄來自開課系統節錄,可以發現,關於人數有以下幾點

選課系統顯示名稱 名稱 使否會變動 可能為開課系統資料重複 (cond.)Courses 名稱
限修人數 limitCountH :heavy_multiplication_x: limit_count_h TotalMaxSize
授權碼人數 authorizeP :heavy_multiplication_x: authorize_p AuthMaxSize
保留新生人數 v_reserve_count :heavy_multiplication_x: :heavy_multiplication_x: 無儲存
選課人數 v_stfseld :heavy_check_mark: counter_exceptAuth CourseSize
已分發人數 v_stfseld_deal :heavy_check_mark: counter 無儲存
未分發人數 v_stfseld_undeal :heavy_check_mark: authorize_using AuthUsed
授權碼選課人數 v_stfseld_auth :heavy_check_mark: :question: 無儲存
交換生選課人數 v_stfseld_exchange :heavy_check_mark: :question: 無儲存
不佔名額生人數 v_stfseld_unfull :heavy_check_mark: :question: 無儲存

目前計劃將會變動的資料(:heavy_check_mark: )在 temporal_scraper.php 更新,不會變動的資料(:heavy_multiplication_x:)在 semestral_scraper.php 更新。

RexYuan commented 8 years ago

對原先 Courses 的更新:

欄位 動作
CourseSize 遷移至 Enrolled
AuthUsed 遷移至 Unassigned
FreshReserve 至選課系統刮 v_reserve_count
Distributed 刪除

新增一個 TABLE CoursesStates:

欄位 原資料名稱 型別 意義 範例 備註
CourseStateId N/A u_INT AUTO_INCREMENT PRIMARY KEY 識別碼 1,32,6334 Courses(CourseStateId) 映射至此
Enrolled v_stfseld u_INT 選課人數 123,122,100
Assigned v_stfseld_deal u_INT 已分發人數 115,41,59
Unassigned v_stfseld_undeal u_INT 未分發人數 196,82,82
AuthAssigned v_stfseld_auth u_INT 授權碼選課人數 0 目前尚未到加退選時間,無法確定
ExAssigned v_stfseld_exchange u_INT 交換生選課人數 0 無法確定
PtAssigned v_stfseld_unfull u_INT 不佔名額生人數 0 無法確定
RexYuan commented 8 years ago

我不知道怎麼辦 所以我就最後還是給他存 Courses 了 ... 在 ad89af30ce9d72e4d78f0aa4fe9935d84665e4cc,已經有一個可以搭配新版 Schema(尚未更新至 Wiki)的 scraper 了。打算確定完成後才會更新