目标请求一:
jscurl --path-as-is -i -s -k -X $'GET' \
-H $'Host: jiaowu.nit.edu.cn:8080' -H $'X-Requested-With: XMLHttpRequest' -H $'Accept-Language: zh-CN,zh;q=0.9' -H $'Accept: application/json, text/javascript, */*; q=0.01' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36' -H $'Referer: http://jiaowu.nit.edu.cn:8080/jsxsd/kscj/cjcx_frm' -H $'Accept-Encoding: gzip, deflate, br' -H $'Connection: keep-alive' \
-b $'bzb_jsxsd=1FF0607241F84CA8C94531B3F7D6EBC3' \
$'http://jiaowu.nit.edu.cn:8080/jsxsd/kscj/cjcx_list?pageNum=1&pageSize=20&kksj=2024-2025-1&kcxz=&kcsx=&kcmc=&xsfs=all&sfxsbcxq=1'
拿到数据
HTTP/1.1 200 Expires: Wed, 31 Dec 1969 23:59:59 GMT vary: accept-encoding Content-Encoding: gzip Content-Type: text/html;charset=utf-8 Transfer-Encoding: chunked Date: Mon, 27 Jan 2025 07:34:54 GMT Keep-Alive: timeout=10 Connection: keep-alive {"msg":"","code":0,"data":[{"cj0708id":"2BBEE76D8F3D0876E063AD5A000A774F","xnxqid":"2024-2025-1","kch":"030420143","kc_mc":"5形势与政策","ksdw":"马克思主义学院","xqmc":"2024-2025-1","xf":0.25,"zxs":8,"ksfs":"考查","kcsx":"必修","xqstr":"2024-2025-1","zcj":75,"zcjstr":"75","kz":0,"kcxzmc":"通识必修课","xs0101id":"2022102191","jx0404id":"202420251002177","jd":2.7,"ksxz":"正常考试","rownum_":1},{"cj0708id":"80579348544240B6BD0324AF2A0F6CBA","xnxqid":"2024-2025-1","kch":"040220012","kc_mc":"国家学生体质健康测试3","ksdw":"体育教 学部","xqmc":"2024-2025-1","xf":0,"zxs":1,"kcsx":"必修","xqstr":"2024-2025-1","zcj":51.3,"zcjstr":"51.3","kz":0,"kcxzmc":"通识限选课","xs0101id":"2022102191","jd":0,"ksxz":"正常考试","rownum_":2},{"cj0708id":"2B15ECE7BEA75256E063AE5A000A44CB","xnxqid":"2024-2025-1","bcxq":"2024-2025-1","kch":"050220401","kc_mc":"专门用途英语I(科技英语翻译)","ksdw":"外国语学院","xqmc":"2024-2025-1","xf":2,"zxs":32,"ksfs":"考查","kcsx":"必修","xqstr":"2024-2025-1","zcj":60,"zcjstr":"60","kz":0,"kcxzmc":"学科基础课","xs0101id":"2022102191","jx0404id":"202420251002190","jd":1,"ksxz":"重修一","rownum_":3},{"cj0708id":"2B132E76B39DD071E063AD5A000A6110","xnxqid":"2024-2025-1","bcxq":"2024-2025-1","kch":"070120007","kc_mc":"概率论与数理统计","ksdw":"理学 院","xqmc":"2024-2025-1","xf":3,"zxs":48,"ksfs":"考查","kcsx":"必修","xqstr":"2024-2025-1","zcj":55,"zcjstr":"55","kz":0,"kcxzmc":"学科基础课","xs0101id":"2022102191","jx0404id":"202420251002334","jd":0,"ksxz":" 重修一","rownum_":4},{"cj0708id":"2BDEB9BBBD9AA3D0E063AE5A000A786E","xnxqid":"2024-2025-1","bcxq":"2024-2025-1","kch":"070227011","kc_mc":"大学物理B实验","ksdw":"理学院","xqmc":"2024-2025-1","xf":0.5,"zxs":16,"ksfs":"考试","kcsx":"必修","xqstr":"2024-2025-1","zcj":0,"zcjstr":"0","kz":0,"kcxzmc":"学科基础课","xs0101id":"2022102191","jx0404id":"202420251001219","jd":0,"ksxz":"重修一","cjbs":"缺考","rownum_":5},{"cj0708id":"2B199D4A64C2FD52E063AE5A000A4E2E","xnxqid":"2024-2025-1","kch":"080907111","kc_mc":"分布式计算技术实训","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":2,"zxs":2,"ksfs":"考查","kcsx":"必修","xqstr":"2024-2025-1","zcj":80,"zcjstr":"80","kz":0,"kcxzmc":"集中实践教学环节","xs0101id":"2022102191","jx0404id":"202420251003533","jd":3,"ksxz":"正常考试","rownum_":6},{"cj0708id":"2BA2259F7C09E40AE063AD5A000AF47C","xnxqid":"2024-2025-1","kch":"080910017","kc_mc":"机器学习","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":4,"zxs":64,"ksfs":"考查","kcsx":"任选","xqstr":"2024-2025-1","zcj":78,"zcjstr":"78","kz":0,"kcxzmc":"专业选修课","xs0101id":"2022102191","jx0404id":"202420251002069","jd":3,"ksxz":"正常考试","rownum_":7},{"cj0708id":"2A52A8DD9E242792E063AD5A000A11DC","xnxqid":"2024-2025-1","kch":"080910108","kc_mc":"分布式计算技术","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":4,"zxs":64,"ksfs":"考试","kcsx":"必修","xqstr":"2024-2025-1","zcj":62,"zcjstr":"62","kz":0,"kcxzmc":"专业核心课","xs0101id":"2022102191","jx0404id":"202420251002094","jd":1,"ksxz":"正常考试","rownum_":8},{"cj0708id":"2B95E304C04F264EE063AD5A000A70D2","xnxqid":"2024-2025-1","kch":"080910109","kc_mc":"Java Web技术","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":2.5,"zxs":40,"ksfs":"考查","kcsx":"任选","xqstr":"2024-2025-1","zcj":83,"zcjstr":"83","kz":0,"kcxzmc":"专业选修课","xs0101id":"2022102191","jx0404id":"202420251002102","jd":3.3,"ksxz":"正常考试","rownum_":9},{"cj0708id":"2B96460F66F70B7AE063AE5A000AF637","xnxqid":"2024-2025-1","kch":"080910110","kc_mc":"计算机网络","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":3.5,"zxs":56,"ksfs":"考试","kcsx":"必修","xqstr":"2024-2025-1","zcj":67,"zcjstr":"67","kz":0,"kcxzmc":"学科基础课","xs0101id":"2022102191","jx0404id":"202420251002026","jd":1.5,"ksxz":"正常考 试","rownum_":10},{"cj0708id":"2BA91668C3621177E063AD5A000AFE85","xnxqid":"2024-2025-1","bcxq":"2024-2025-1","kch":"080921101","kc_mc":"劳动通论","ksdw":"马克思主义学院","xqmc":"2024-2025-1","xf":1,"zxs":16,"ksfs":"考查","kcsx":"必修","xqstr":"2024-2025-1","zcj":89,"zcjstr":"89","kz":0,"kcxzmc":"通识必修课","xs0101id":"2022102191","jx0404id":"202420251005652","jd":3.7,"ksxz":"重修一","rownum_":11},{"cj0708id":"2BE507B0DD243820E063AE5A000A6D6A","xnxqid":"2024-2025-1","kch":"080930020","kc_mc":"软件工程与项目管理","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":3.5,"zxs":56,"ksfs":"考试","kcsx":"必修","xqstr":"2024-2025-1","zcj":69,"zcjstr":"69","kz":0,"kcxzmc":"学科基础课","xs0101id":"2022102191","jx0404id":"202420251002213","jd":2,"ksxz":"正常考试","rownum_":12},{"cj0708id":"2B93036B2FECB610E063AE5A000A7B33","xnxqid":"2024-2025-1","kch":"080947003","kc_mc":"Java Web技术实训","ksdw":"信息工程学院","xqmc":"2024-2025-1","xf":1,"zxs":1,"ksfs":"考查","kcsx":"任选","xqstr":"2024-2025-1","zcj":99,"zcjstr":"99","kz":0,"kcxzmc":"专业选修课","xs0101id":"2022102191","jx0404id":"202420251003492","jd":4,"ksxz":"正常考试","rownum_":13},{"cj0708id":"2BB578E44424DD9FE063AE5A000A04E1","xnxqid":"2024-2025-1","kch":"221325315","kc_mc":"C++语言(慕课)","ksdw":"教务处(创新创业学院)","xqmc":"2024-2025-1","xf":1.5,"zxs":24,"ksfs":"考查","kcsx":"公选","xqstr":"2024-2025-1","zcj":4,"zcjstr":"4","kz":0,"kcxzmc":"专业选修课","xs0101id":"2022102191","jx0404id":"202420251007000","jd":0,"ksxz":"正常考试","rownum_":14},{"cj0708id":"2B3EB32D42596A7BE063AE5A000ABB99","xnxqid":"2024-2025-1","kch":"990103947","kc_mc":"数字创作与智能艺术","ksdw":"人文与艺术学院","xqmc":"2024-2025-1","xf":1,"zxs":32,"ksfs":"考查","kcsx":"公选","xqstr":"2024-2025-1","zcj":84,"zcjstr":"84","kz":0,"kcxzmc":"通识任选课","xs0101id":"2022102191","jx0404id":"202420251006388","jd":0,"ksxz":"正常考试","txklb1":"创新创业类","rownum_":15}],"count":15,"tjsj":"","pjxfjdts":"统计规则发生改变或未计算时,需重新统计。","isXsckpscj":0}
第一个Login有用请求
jscurl --path-as-is -i -s -k -X $'POST' \
-H $'Host: eapp2.nit.edu.cn:9443' -H $'Content-Length: 4893' -H $'Cache-Control: max-age=0' -H $'Sec-Ch-Ua: \"Not?A_Brand\";v=\"99\", \"Chromium\";v=\"130\"' -H $'Sec-Ch-Ua-Mobile: ?0' -H $'Sec-Ch-Ua-Platform: \"Windows\"' -H $'Accept-Language: zh-CN,zh;q=0.9' -H $'Origin: https://eapp2.nit.edu.cn:9443' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Upgrade-Insecure-Requests: 1' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' -H $'Sec-Fetch-Site: same-origin' -H $'Sec-Fetch-Mode: navigate' -H $'Sec-Fetch-User: ?1' -H $'Sec-Fetch-Dest: document' -H $'Referer: https://eapp2.nit.edu.cn:9443/cas/login' -H $'Priority: u=0, i' -H $'Connection: keep-alive' \
--data-binary $'username=2022102191&password=3485000346zyhQWM&execution=6c19d7b7-7b2f-46cd-9537-a6148d5f61fc_ZXlKaGJHY2lPaUpJVXpVeE1pSjkuQ1dDL3dDMnMwOTRhQWVrb1IyMDhMVkZia1dyUXQ4b29IOGdmcHJ5MXA1QThpRzJJZ0pMTjloWWI2L1pZNTJPZ0tGSlgzZVdEdkRseHJMMWd0emZnUnVVUENpVTNwOEFRbG1GSUV2THN2UVdXb3lLWml0bUphYlN5VVB6ekcxVHZ5MS8rMDFrSG9kSGtDSURqa2s1UWZKWTJocDdnbjJWUTk2TzB1ZFpld1pDMmpGYXpNd3VUQXMwNDgwUTJmaUNvSmFodGViMjFYWFhRTmVjTVVPcjZUT3Z4YmQzZW9KZ1hPWkxsdjliNC9idUVHUXpGMnJDOUVadEJNYURHNlM2a0Q3ZVM4RVhzcnZlMk94N0NxNllLci9KKzhPUlE3TTNmTW45M2JCR3RQY1RUK1NmaUVHeGJ6WE9qNlUrZURqQ3NPU3Q2cmlkZElabzlQTDN0TXc5UUZTZ0FRazFhZzlkVTZWVlpDMU1ETmtsQnZ0TmMxSjZGazRwb0h3QVhEVllvMEd0dFdvcDE4N2Rkenk1RWxwL1ZLNGFGUGU5Tzk5Vm81RkJHYnYwOGU2Q3VZaXJ5VWpMSGhiVHQvZ2xqZkVNeml1M2U4K1lsS2I3MHFoREpjRE5UU3FCMUpSUlNvUitONHdBRnN1ckxCWHBnV3ZDcVJ0MUV4UmlxaEpFUjk3dHliUFJWNXM0bzJ6YWhvcVZPVlRNSEF2S3RyN2ZMSm5UOWpEV2hjUWpxNVN1WVlsaUcrNjA1TUEyOHFSdGZpQ2RhTWRBa3YvV2xMSzdKTDdxS2JYZDdsbmJoZGZQcXAwWkFiUldCdnJremlRVUszb1pzd0tiSlVwYVRTZWJrakx1SHNyVUdNcmVCQ2xDT0ZhSFRJR3oxeCtWK2NpSzNuYnVqMlJheElzS2xxOStsRG5uMzdyeTY2enNMdGF5ZzhYaGxMNm5aa0NrbHFuenhPMncxdzBMZ0lvcCtHdFBZeEpramtpelVMM1R4YnlpSU5DRWdnSkhlRjhmdVM1eE9xNFZHNFdpM0lVK1Q0OFJidktCWnBwZXJ5Z0RZb0g5cUZvMG5TWmxHY014RFFtMjZmUkxnYmRZZHNEc3I4WGNPOWRZTXNmeTRCL200U3g3S0FQa3R6dXRJZld2c2R3TmFySWVuUENrSzduVGtvYmpVWEdZZXVmbzBKSC9DTDBMMTRwMytwRFRSMkg1eXlJU3p4cVZCWnJFUURIc2YreUw0RGc5QVdiMDh0TzBWMTVYTGtVZnk5YmxxdkUzUkh3YUJ0VkdSNFZoZWpVdStKRVR0OVp6b0ttNEE0SWVSWS9iUXFydmpBMFR5bmd5MDVDMFhhT2FiRTZuWVplTUt5VFNPT2dQNmdsS0d4SndWRFNnZU51V3V1UXptZEx6dkFyZUFVUUZxRDlXVmdTdFhES1BGbWdteTUzK1ozdlE2ci9zNGtpUmp0TnlTR3hmNUEzZHlyUytoZmNYK3BqRDlKQW8zdnh3eUR5eS9ESm9xb0lqeHJ3bmlTelZQYmU3WHlBVWlpNzN4dVZCMGp6VnhKWnJ3VTYremN5OFM0dk5TU0hwS2E0L1JQTVZWVzhPYllLdmNMRkV3Z2hlZkd6OGtyVTFnaU5QS3h6OHQ1T3k0UG16ZHlSalpHcnRHSWhkVXVNSGVRemd1NW9QWHpSR1FtdkVTdHA5c09Hend1R21zREJQR25hWlh0cG9Wc3RuRWI5czhudTQySjBJbnRhM2t5dVZVVUxQdmdrUnlqRkt0Tm9YUVo4YmtxQytTb1R5eGtDUE1USFBhTGEydElaRE9zMFZWY0dPTm9ZVHNJWi9mYU5HSmFSL21SaGd1UktjSnpWS25uWmIvZFp6dzZSdG5Jd24yYmZnZHp6cUwvSzdlZTVvRi9xMHJPcmtCRTdpMjZ4OC9SbnNSTlc3UGFsd0ZwMVFFL29ReUZWYWtvMVpDb29WbmRlU3l2Zi84TXFUWkhHVFZiSTNpcDhIMzM3eU9qR0M5eXlCVVFTaVI0Ri84MjlveUxSQ0xwRFk5Titob1pYeStBM01BUk9JOFJXbmxEQmdIRlRkZWd1MEpJTnFkVzVIbXM0M1FaaWVHV1lUUjNBZ2xXSVBvZkhFOSttelZTd1hHQVgrTDJkUHFiQW1BUXFLT2NTckkxOWJnOXN2cFR6TFRjTjJRYWpYaGh6Q1M0TjNvMCtnWXlnOVVadFRMSkhQaGlKTkN1ZWFGSGRBM0xOUVpra1RVZHhEZkVMNzk1ZUJOMjAwb2JpellpRE54VTBIV3FtaHVNdnpReE05Y1J5K0FQOGRBTHVQWnR5QlpLNWpJdnlET2xaZG9MT0lwbmlQVnhBaEFlRDdUR0NpZ0dhS3JSZnZobzJrRHZrdm81a1IrRmNsTmF3eVVsampzZ1F2UWJ5SUNML21KejIvTkw3SVJndlZyelZ4Rk5pODZBaWhYcGlzQ1hpeFlnU1p4K3Iya0pMczhDWm15eW1Sa1RaOTVpUVp2OXg5Mmtyam0va0U1QW5MVXZHZFkrVjFtUU01cytQWklnbklZajBFb2RkZlBmMWU3OFNNenYzd2UvUG5yYXJ3cjRPM1hLTkwzY1M4eERlbzRIWVFxKzNvaVUycDhZMGU0NVRRR0VhWjBzeExhZ0ZuTXVQZEptcVRCZmNFNFpGZ3VmRzRqb1UrVFNtQjNOK21BbHZiSGI3SkhVeWFYeGNpY2dJMDU0a0sva2VxRWViOCs0THcrMCtqTmNiNTVQc0M4VWh6Rk5FR2ZSVnVzOWlZb2RUV2gxQlZvb3FMU2JCYkRHRVlINmNVK3k0K2gzdFdzQmFDOWU2T2s3N2xaakZlRERoMktaTWhnU1ZuNm9HK0NQdFF6aFJ2NWZobEdwSnlHYmd0aGwyaCtUTGVoRXQ0aWZHejlRQUEzRG13aXZRTlZ5d1VEb1kyRm9ON1ZYUnlKMHNwSlFVSXdIMGIydGk2ckNBUGhIWDI1eWptc2NHUmZ3ckE0Q05DRnFEeXdFLys4bVlMZ1NBakIwYXNlRm5OR29SYjI0dk9JeUlPUFA5NDhhdFFZZGFZRFJ3TzVySGdDWGpNQWZza2hEcVFJYTJiTlBSalJOZHpESVZRVDJVVlAvbHFGMVJHT1c0RlJoM1FVV1Q3NXJadlZwTGNoZ0dPbjhWQllFVHBFU2RYeEpVazBDcnlqeDA5MXNYeWdISjZNSmdNbUdHSE0wZlNrRnJrdkhoVTBnYm02NlpMKys3T3NhSWZ6Y0RhTmVjL2V2a00rdkxGcTN3VmxyV0hXYzZZVFZ3bXNscHVrMHJ4QVJyUkFNdHRxU2ZVNGNpQS9uOVZLNlpoSWdoLzUzeSswODArUVZ5aWg1V3dVb250N0NCdDIyb2x2V0o1eG13ZTRlZVdoK2RnSVVjVU5Hd1c3TW4xUDJpb0dXVE9TZWY2NUtNR0c5MUFEUXJoVFQwTnlQR1JScW12STFETzNvSG1SVXZjMzdlc1VmWEhtRmNWMktVRlluT0tGNm4rSklneng2NGFLRnVFMWJJU3dEbGpNMFVsNnlDRFBIak9hY3JUa1RUTTdReGtKYVVGdGpzR3ZsLzM0U2QxOXVpU2RzSTcvWTRkVDhHSDlMU0Z0OUxqemNSM09LYXlVVWRXOFg4UEdRYyt6RG9aV25ONWJOdzNUdzFTT08wZ3Q4VWtaYWpFRjkrVkVGbHlsUkkzUjEwUmVORURJZ0NRaWFucFhpRzN4emhjYlVtS0ZjaWd1VjUyaThiTSszM0U5a1hKZTREWFlJLzgzb25HazZtK0pKS2FtSm1qWXI4eUFDQmQ2N3kxd0tpN2tNbnpzcENBMnE1bjFEQWNweFYvQy9qSG5SUGMwYm5BNEJuUG83NThSWnp5aWgxaFFZQno2MjcvN0R3c3FDa0lnY2VBcElGb254dmdId21rb0laL1h4RkxpSlRWenZNbDl3cXNqZEFyS0cwdzhpaU84MWE1NXdsbkVRWlJ5YnRJd0JIcDNNaGJNMnk0czY3WTlZMkVFajJ3d0tNRGFlTTdxcUlYbHpHaStJeU5aVWRHWGM4Z2w5aFk0MFc2TS8yT25PUGhMdTJPaWE5QVJWTTlXK01qNHBJd1FHNC9TMDQzeW1rUytVZVFqVTFsVEV0SHFLS2U0U1VzWUU4bHQ2TE9pK2ZpTnZyOGZRSXE1TEV3WVh1ME91OE5UWU1lWlgvdEVVRHZDb1pzNHJTYnlIaUVJOElIeTM5T3B5bnE1TnNvMG8vMDlMZXV0M1YydFRmMXFSWXdLY1VROXRSekhoNWJ1cVRSRnp2RXpUOE9YaE5CWWFNOFMwUEMrNWhoZHlmRWp5SzJqRjM5cHQ4M1VlT2ttZUdjTFNLVmJsUEJwdWpTcFdsSTdQcm1hektGUUVNdGJLQzg4WGFST0NqT3JlTUhsNExFL05VUzhkOWViNlVtbGptVFFJZytMbThYNXIxWnk0aUV2N2I0MG9QUzM4T3VxcU84UldzV0NNU2VSMUpwV1psUjIrWnd6Z0R0U3VsMG5yK1QxQW1qdGloeHd6TFlxTGUwRXhNMzdvT1hBaDdPakxFcVM0OXhqYVNsMEFISGxnZjh0aDJFRjdyVUIvNThydTVMUXBjNVQrSENkMTNHU29wYnJjQT09Llp6eU5JWW0yZGJwc1JWNE1BYUJLYmtITGxSUl9OWFlPSFRaYUhMV0c0SFhvbm9jY0ZWdFdDQVBOMThsTW1Uc2R2amJRMFZkTnFLd25sZkJUZC14N1BB&_eventId=submit' \
$'https://eapp2.nit.edu.cn:9443/cas/login'
拿到数据:
HTTP/1.1 302 Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 Strict-Transport-Security: max-age=15768000 ; includeSubDomains X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block Set-Cookie: JSESSIONID=DBDC4F15C20BCB64CF76E9DA062DF206; Path=/cas; Secure; HttpOnly Set-Cookie: TGC=eyJhbGciOiJIUzUxMiJ9.ZXlKNmFYQWlPaUpFUlVZaUxDSmhiR2NpT2lKa2FYSWlMQ0psYm1NaU9pSkJNVEk0UTBKRExVaFRNalUySW4wLi5TcTF5YWdIVDBLbDhJX1pnVFM3YTR3LnlHbGI2SEo1Qko4ckJJQ1ZpM01NMmlrZnpBWmJtSTNTZW1sUEFHVFU0aFFRcXZpbDM4ZWxJejJ4N1JwYTF3cllOOXVuVjVpWjJ0U0w3YWtJa3pHNkI5RDU1OS1DV0hPcjVKV3I5SGpyZjJrNktBdkcyd0lXSkdiLVVuVXJxSXdaaEQ2MUxkLU11X1hhNnY4WXlheFdyZy1fbVJudi0zUElBdm9sWklaaEU0TjZJUTNKakF3TTNLMkdEeFBWNE5zWEVKUG9ocG5DcE9RZXZSZmF1OXh1WW9qVFFyN0psTE94Vkx5dkZYS0xhWHlMbEliQkwzbC1yUVcwekgya252cmNNd1IwejFPLUhyX0t1b3hPUlNpWDhBLi13ZEhoVlRHSFNtOGZ5THJmbmhqTkE=.JC0yDze1lCzavogG6KZlfA0iHZGyBIgHJHi5KjWLYnFWsw48J3rElbnqq4x_HJvx2XQ8yhtGvXI0MbBRhudglA; Path=/cas/; Secure; HttpOnly Location: http://portal.nit.edu.cn/cas/login_portal?ticket=ST-1770620-bOb9Vxs5uOfZURzA3EZH5CAE13g-localhost Content-Length: 0 Date: Mon, 27 Jan 2025 07:35:04 GMT
学期不填返回全部
pyimport requests
from bs4 import BeautifulSoup
# 初始化Session
session = requests.Session()
# 用户信息
USERNAME = "" # 替换为你的用户名
PASSWORD = "" # 替换为你的密码
# CAS登录URL
CAS_LOGIN_URL = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fportal.nit.edu.cn%2Fcas%2Flogin_portal"
SCORE_URL = "http://jiaowu.nit.edu.cn:8080/jsxsd/kscj/cjcx_list"
# 请求头
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36",
"Accept-Language": "zh-CN,zh;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
}
def get_execution_value():
"""从CAS登录页面获取execution参数"""
try:
response = session.get(CAS_LOGIN_URL, headers=HEADERS)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
execution = soup.find("input", {"name": "execution"}).get("value")
return execution
except Exception as e:
print(f"获取execution失败: {e}")
return None
def cas_login(execution):
"""CAS登录"""
login_data = {
"username": USERNAME,
"password": PASSWORD,
"execution": execution,
"_eventId": "submit",
"submit": "登录",
}
try:
response = session.post(
CAS_LOGIN_URL,
data=login_data,
headers=HEADERS,
allow_redirects=False,
)
response.raise_for_status()
if response.status_code == 302:
print("CAS登录成功")
return response.headers["Location"] # 返回重定向URL
else:
print("CAS登录失败,状态码:", response.status_code)
return None
except Exception as e:
print(f"CAS登录失败: {e}")
return None
def follow_redirects(redirect_url):
"""跟随重定向链,获取必要的Cookies"""
try:
response = session.get(redirect_url, headers=HEADERS, allow_redirects=True)
response.raise_for_status()
print("重定向完成,当前Cookies:", session.cookies.get_dict())
except Exception as e:
print(f"重定向失败: {e}")
def validate_portal_token():
"""验证Portal Token"""
validate_url = "http://portal.nit.edu.cn/security_portal/validate_login"
token = session.cookies.get("PORTAL_TOKEN") # 从Cookies中获取Token
if not token:
print("未找到PORTAL_TOKEN")
return False
try:
response = session.post(
validate_url,
data={"token": token},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
response.raise_for_status()
if response.json().get("errcode") == "0":
print("Token验证成功")
return True
else:
print("Token验证失败:", response.json())
return False
except Exception as e:
print(f"Token验证失败: {e}")
return False
def sso_to_jwxt():
"""通过SSO跳转到教务系统,获取bzb_jsxsd Cookie"""
sso_url = "http://jiaowu.nit.edu.cn/sso.jsp"
try:
# 第一步:获取bzb_njw
response = session.get(sso_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
bzb_njw = session.cookies.get("bzb_njw")
if not bzb_njw:
print("未找到bzb_njw Cookie")
return False
print("bzb_njw Cookie获取成功:", bzb_njw)
print("Response Body: ", response.text)
# 第二步:跟随CAS登录URL
# cas_login_url = response.headers.get("Location")
cas_login_url = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fjiaowu.nit.edu.cn%2Fsso.jsp"
if not cas_login_url:
print("未找到CAS登录URL")
return False
response = session.get(cas_login_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
# 第三步:跟随ticket重定向
ticket_url = response.headers.get("Location")
if not ticket_url:
print("未找到ticket URL")
return False
response = session.get(ticket_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 第四步:最终跳转到教务系统
final_redirect_url = response.headers.get("Location")
if not final_redirect_url:
print("未找到最终重定向URL")
return False
response = session.get(final_redirect_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 获取bzb_jsxsd Cookie
# print("Response Cookies: ", session.cookies.get_dict())
# bzb_jsxsd = session.cookies.get("bzb_jsxsd")
# if not bzb_jsxsd:
# print("未找到bzb_jsxsd Cookie")
# return False
final_final_redirect_url = response.headers.get("Location")
if not final_final_redirect_url:
print("未找到最终最终重定向URL")
return False
response = session.get(final_final_redirect_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 获取bzb_jsxsd Cookie
# print("Response Cookies: ", session.cookies.get_dict())
bzb_jsxsd = session.cookies.get("bzb_jsxsd")
if not bzb_jsxsd:
print("未找到bzb_jsxsd Cookie")
return False
print("教务系统Cookie获取成功:", bzb_jsxsd)
return True
except Exception as e:
print(f"SSO跳转失败: {e}")
return False
def query_scores():
"""查询成绩"""
params = {
"pageNum": 1,
"pageSize": 20,
"xsfs": "all",
"kksj":"2024-2025-1",
"sfxsbcxq": 1,
}
try:
response = session.get(SCORE_URL, params=params, headers=HEADERS)
response.raise_for_status()
scores = response.json()
print("成绩查询成功:")
print(scores)
# for score in scores.get("data", []):
# print(f"课程: {score['kc_mc']}, 成绩: {score['zcj']}")
except Exception as e:
print(f"成绩查询失败: {e}")
def main():
# 1. 获取execution参数
execution = get_execution_value()
if not execution:
return
# 2. CAS登录
redirect_url = cas_login(execution)
if not redirect_url:
return
# 3. 跟随重定向链
follow_redirects(redirect_url)
# 4. 验证Portal Token
if not validate_portal_token():
return
# 5. SSO跳转到教务系统
if not sso_to_jwxt():
return
# 6. 查询成绩
query_scores()
if __name__ == "__main__":
main()
第二版
pyimport requests
from bs4 import BeautifulSoup
import json
# 初始化Session
session = requests.Session()
# 用户信息
USERNAME = "" # 替换为你的用户名
PASSWORD = "" # 替换为你的密码
# CAS登录URL
CAS_LOGIN_URL = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fportal.nit.edu.cn%2Fcas%2Flogin_portal"
SCORE_URL = "http://jiaowu.nit.edu.cn:8080/jsxsd/kscj/cjcx_list"
# 请求头
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36",
"Accept-Language": "zh-CN,zh;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
}
def get_execution_value():
"""从CAS登录页面获取execution参数"""
try:
response = session.get(CAS_LOGIN_URL, headers=HEADERS)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
execution = soup.find("input", {"name": "execution"}).get("value")
return execution
except Exception as e:
print(f"获取execution失败: {e}")
return None
def cas_login(execution):
"""CAS登录"""
login_data = {
"username": USERNAME,
"password": PASSWORD,
"execution": execution,
"_eventId": "submit",
"submit": "登录",
}
try:
response = session.post(
CAS_LOGIN_URL,
data=login_data,
headers=HEADERS,
allow_redirects=False,
)
response.raise_for_status()
if response.status_code == 302:
print("CAS登录成功")
return response.headers["Location"] # 返回重定向URL
else:
print("CAS登录失败,状态码:", response.status_code)
return None
except Exception as e:
print(f"CAS登录失败: {e}")
return None
def follow_redirects(redirect_url):
"""跟随重定向链,获取必要的Cookies"""
try:
response = session.get(redirect_url, headers=HEADERS, allow_redirects=True)
response.raise_for_status()
print("重定向完成,当前Cookies:", session.cookies.get_dict())
except Exception as e:
print(f"重定向失败: {e}")
def validate_portal_token():
"""验证Portal Token"""
validate_url = "http://portal.nit.edu.cn/security_portal/validate_login"
token = session.cookies.get("PORTAL_TOKEN") # 从Cookies中获取Token
if not token:
print("未找到PORTAL_TOKEN")
return False
try:
response = session.post(
validate_url,
data={"token": token},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
response.raise_for_status()
if response.json().get("errcode") == "0":
print("Token验证成功")
return True
else:
print("Token验证失败:", response.json())
return False
except Exception as e:
print(f"Token验证失败: {e}")
return False
def sso_to_jwxt():
"""通过SSO跳转到教务系统,获取bzb_jsxsd Cookie"""
sso_url = "http://jiaowu.nit.edu.cn/sso.jsp"
try:
# 第一步:获取bzb_njw
response = session.get(sso_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
bzb_njw = session.cookies.get("bzb_njw")
if not bzb_njw:
print("未找到bzb_njw Cookie")
return False
print("bzb_njw Cookie获取成功:", bzb_njw)
print("Response Body: ", response.text)
# 第二步:跟随CAS登录URL
# cas_login_url = response.headers.get("Location")
cas_login_url = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fjiaowu.nit.edu.cn%2Fsso.jsp"
if not cas_login_url:
print("未找到CAS登录URL")
return False
response = session.get(cas_login_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
# 第三步:跟随ticket重定向
ticket_url = response.headers.get("Location")
if not ticket_url:
print("未找到ticket URL")
return False
response = session.get(ticket_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 第四步:最终跳转到教务系统
final_redirect_url = response.headers.get("Location")
if not final_redirect_url:
print("未找到最终重定向URL")
return False
response = session.get(final_redirect_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 获取bzb_jsxsd Cookie
# print("Response Cookies: ", session.cookies.get_dict())
# bzb_jsxsd = session.cookies.get("bzb_jsxsd")
# if not bzb_jsxsd:
# print("未找到bzb_jsxsd Cookie")
# return False
final_final_redirect_url = response.headers.get("Location")
if not final_final_redirect_url:
print("未找到最终最终重定向URL")
return False
response = session.get(final_final_redirect_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 获取bzb_jsxsd Cookie
# print("Response Cookies: ", session.cookies.get_dict())
bzb_jsxsd = session.cookies.get("bzb_jsxsd")
if not bzb_jsxsd:
print("未找到bzb_jsxsd Cookie")
return False
print("教务系统Cookie获取成功:", bzb_jsxsd)
return True
except Exception as e:
print(f"SSO跳转失败: {e}")
return False
def query_scores():
"""查询成绩"""
params = {
"pageNum": 1,
"pageSize": 20,
"xsfs": "all",
"kksj":"2024-2025-1",
"sfxsbcxq": 1,
}
try:
response = session.get(SCORE_URL, params=params, headers=HEADERS)
response.raise_for_status()
scores = response.json()
print("成绩查询成功:")
print(scores)
# for score in scores.get("data", []):
# print(f"课程: {score['kc_mc']}, 成绩: {score['zcj']}")
except Exception as e:
print(f"成绩查询失败: {e}")
def query_exam_schedule():
"""查询考试安排"""
exam_schedule_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/xsks/xsksap_list"
params = {
"pageNum": 1,
"pageSize": 20,
"xnxqid": "2024-2025-1", # 学年学期ID
"xqlb": "", # 校区类别,留空表示全部
}
try:
response = session.get(exam_schedule_url, params=params, headers=HEADERS)
response.raise_for_status()
exam_schedule = response.json()
print("考试安排查询成功:")
print(exam_schedule)
# 打印考试安排信息
for exam in exam_schedule.get("data", []):
print(f"课程: {exam['kskcmc']}, 时间: {exam['kssj']}, 地点: {exam['js_mc']}, 教师: {exam['jsxm']}")
except Exception as e:
print(f"考试安排查询失败: {e}")
def query_student_info():
"""查询学生信息"""
student_info_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/framework/xsMainV_new.htmlx?t1=1"
try:
# 发送请求
response = session.get(student_info_url, headers=HEADERS)
response.raise_for_status()
# 解析 HTML
soup = BeautifulSoup(response.text, "html.parser")
# 提取学生信息
info_content = soup.find("div", class_="qz-infoContent")
if not info_content:
print("未找到学生信息")
return None
# 提取姓名和学号
name_id = info_content.find("div", class_="infoContentTitle").text.strip()
print(f"姓名和学号: {name_id}")
# 提取性别
gender_tag = info_content.find("div", class_="man-tag")
gender = gender_tag.find("span").text.strip() if gender_tag else "未知"
print(f"性别: {gender}")
# 提取生源地、学院、专业、班级
info_body = info_content.find("div", class_="infoContentBody")
if info_body:
rows = info_body.find_all("div", class_="qz-rowlan")
for row in rows:
label = row.find("div", class_="qz-detailtext").text.strip()
print(label)
except Exception as e:
print(f"学生信息查询失败: {e}")
# 第一步:获取 kbjcmsid
def get_kbjcmsid():
url = "http://jiaowu.nit.edu.cn:8080/jsxsd/framework/xsMainV_new.htmlx?t1=1"
response = session.get(url, headers=HEADERS)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# 提取 kbjcmsid
kbjcmsid_tag = soup.find('li', {'name': 'kbjcmsid'})
if kbjcmsid_tag:
kbjcmsid = kbjcmsid_tag.get('data-value')
return kbjcmsid
return None
# 第二步:获取课程表数据
# 第二步:获取课程表数据
def get_course_table(kbjcmsid, week=1):
url = f"http://jiaowu.nit.edu.cn:8080/jsxsd/framework/mainV_index_loadkb.htmlx?zc={week}&kbjcmsid={kbjcmsid}&xnxq01id=2024-2025-2&xswk=false"
response = session.get(url, headers=HEADERS)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
# 初始化每天的课程表
days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
course_table = {day: [] for day in days}
# 提取课程表数据
rows = soup.find_all('tr', class_='qz-weeklyTable-tr')
for row in rows:
cells = row.find_all('td', class_='qz-weeklyTable-td')
if len(cells) > 1: # 确保是课程行
time_slot = cells[0].get_text(strip=True) # 时间段
for i in range(1, len(cells)):
day = days[i - 1] # 获取星期几
course_items = cells[i].find_all('li', class_='courselists-item')
if course_items:
for item in course_items:
course_name = item.find('div', class_='qz-hasCourse-title').get_text(strip=True)
details = item.find_all('div', class_='qz-hasCourse-detailitem')
teacher = details[0].get_text(strip=True).replace("教师:", "")
location = details[-1].get_text(strip=True)
week_info = details[-2].get_text(strip=True)
course_info = {
"time_slot": time_slot,
"course_name": course_name,
"teacher": teacher,
"location": location,
"week_info": week_info
}
course_table[day].append(course_info)
else:
# 如果没有课程,添加“没课”
course_table[day].append({
"time_slot": time_slot,
"course_name": "没课",
"teacher": "",
"location": "",
"week_info": ""
})
return course_table
return None
def get_exmp_table():
# 发送HTTP请求
url = 'http://jiaowu.nit.edu.cn:8080/jsxsd/syjx/toXskb.do'
response = session.get(url, headers=HEADERS)
print(response.status_code)
# 检查请求是否成功
if response.status_code == 200:
# 解析HTML内容
soup = BeautifulSoup(response.content, 'html.parser')
# 查找表格
table = soup.find('table', class_='qz-weeklyTable')
# print(table)
if table:
# 解析表格内容
rows = table.find_all('tr')
table_data = []
for row in rows:
cells = row.find_all(['th', 'td'])
row_data = [cell.get_text(strip=True) for cell in cells]
table_data.append(row_data)
return table_data
else:
print("未找到表格")
return []
else:
print(f"请求失败,状态码: {response.status_code}")
return []
def format_table_data(table_data):
"""
将解析后的表格数据整理成每周每天的课程表格式。
:param table_data: 解析后的表格数据
:return: 整理后的表格内容,以JSON格式返回
"""
formatted_data = []
week_days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
periods = ['1-2节', '3-4节', '5-6节', '7-8节', '9-10节']
# 遍历每一行
i = 1
while i < len(table_data):
week = table_data[i][0]
week_data = {'周次': week}
# 每个周次有5行节次数据
for j in range(5):
# 跳过表头
row = table_data[i + j]
# 遍历每一天
for k, day in enumerate(week_days):
if k + 1 < len(row):
if j == 0 and day == '周一':
cell = row[k + 2]
else:
cell = row[k + 1]
if cell:
period = periods[j]
day_data = week_data.setdefault(day, {})
day_data[period] = cell
else:
period = periods[j]
day_data = week_data.setdefault(day, {})
day_data[period] = '没课'
formatted_data.append(week_data)
i += 5
return formatted_data
def main():
# 1. 获取execution参数
execution = get_execution_value()
if not execution:
return
# 2. CAS登录
redirect_url = cas_login(execution)
if not redirect_url:
return
# 3. 跟随重定向链
follow_redirects(redirect_url)
# 4. 验证Portal Token
if not validate_portal_token():
return
# 5. SSO跳转到教务系统
if not sso_to_jwxt():
return
# # 6. 查询成绩
# query_scores()
# # 7. 查询考试安排
# query_exam_schedule()
# # 8. 查询学生信息
# query_student_info()
# 获取 kbjcmsid
kbjcmsid = get_kbjcmsid()
if kbjcmsid:
print(f"获取到的 kbjcmsid: {kbjcmsid}")
# 获取课程表数据(默认第1周)
course_table = get_course_table(kbjcmsid, week=5)
if course_table:
for day, courses in course_table.items():
print(f"\n{day}的课程安排:")
for course in courses:
if course["course_name"] == "没课":
print(f" {course['time_slot']}: 没课")
else:
print(f" {course['time_slot']}: {course['course_name']}")
print(f" 教师: {course['teacher']}")
print(f" 地点: {course['location']}")
print(f" 周次: {course['week_info']}")
else:
print("获取课程表失败!")
else:
print("获取 kbjcmsid 失败!")
# data = get_exmp_table()
# print(data)
# if data:
# formatted_table = format_table_data(data)
# # 将结果转换为JSON格式
# json_data = json.dumps(formatted_table, ensure_ascii=False, indent=4)
# print("格式化后的课程表数据:")
# print(json_data)
# else:
# print("获取考试安排失败!")
if __name__ == "__main__":
main()
py import requests
from bs4 import BeautifulSoup
import json
# 初始化Session
session = requests.Session()
# 用户信息
USERNAME = "2022" # 替换为你的用户名
PASSWORD = "3" # 替换为你的密码
# CAS登录URL
CAS_LOGIN_URL = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fportal.nit.edu.cn%2Fcas%2Flogin_portal"
SCORE_URL = "http://jiaowu.nit.edu.cn:8080/jsxsd/kscj/cjcx_list"
# 请求头
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36",
"Accept-Language": "zh-CN,zh;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
}
def get_execution_value():
"""从CAS登录页面获取execution参数"""
try:
response = session.get(CAS_LOGIN_URL, headers=HEADERS)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
execution = soup.find("input", {"name": "execution"}).get("value")
return execution
except Exception as e:
print(f"获取execution失败: {e}")
return None
def cas_login(execution):
"""CAS登录"""
login_data = {
"username": USERNAME,
"password": PASSWORD,
"execution": execution,
"_eventId": "submit",
"submit": "登录",
}
try:
response = session.post(
CAS_LOGIN_URL,
data=login_data,
headers=HEADERS,
allow_redirects=False,
)
response.raise_for_status()
if response.status_code == 302:
print("CAS登录成功")
return response.headers["Location"] # 返回重定向URL
else:
print("CAS登录失败,状态码:", response.status_code)
return None
except Exception as e:
print(f"CAS登录失败: {e}")
return None
def follow_redirects(redirect_url):
"""跟随重定向链,获取必要的Cookies"""
try:
response = session.get(redirect_url, headers=HEADERS, allow_redirects=True)
response.raise_for_status()
print("重定向完成,当前Cookies:", session.cookies.get_dict())
except Exception as e:
print(f"重定向失败: {e}")
def validate_portal_token():
"""验证Portal Token"""
validate_url = "http://portal.nit.edu.cn/security_portal/validate_login"
token = session.cookies.get("PORTAL_TOKEN") # 从Cookies中获取Token
if not token:
print("未找到PORTAL_TOKEN")
return False
try:
response = session.post(
validate_url,
data={"token": token},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
response.raise_for_status()
if response.json().get("errcode") == "0":
print("Token验证成功")
return True
else:
print("Token验证失败:", response.json())
return False
except Exception as e:
print(f"Token验证失败: {e}")
return False
def sso_to_jwxt():
"""通过SSO跳转到教务系统,获取bzb_jsxsd Cookie"""
sso_url = "http://jiaowu.nit.edu.cn/sso.jsp"
try:
# 第一步:获取bzb_njw
response = session.get(sso_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
bzb_njw = session.cookies.get("bzb_njw")
if not bzb_njw:
print("未找到bzb_njw Cookie")
return False
print("bzb_njw Cookie获取成功:", bzb_njw)
print("Response Body: ", response.text)
# 第二步:跟随CAS登录URL
# cas_login_url = response.headers.get("Location")
cas_login_url = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fjiaowu.nit.edu.cn%2Fsso.jsp"
if not cas_login_url:
print("未找到CAS登录URL")
return False
response = session.get(cas_login_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
# 第三步:跟随ticket重定向
ticket_url = response.headers.get("Location")
if not ticket_url:
print("未找到ticket URL")
return False
response = session.get(ticket_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 第四步:最终跳转到教务系统
final_redirect_url = response.headers.get("Location")
if not final_redirect_url:
print("未找到最终重定向URL")
return False
response = session.get(final_redirect_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 获取bzb_jsxsd Cookie
# print("Response Cookies: ", session.cookies.get_dict())
# bzb_jsxsd = session.cookies.get("bzb_jsxsd")
# if not bzb_jsxsd:
# print("未找到bzb_jsxsd Cookie")
# return False
final_final_redirect_url = response.headers.get("Location")
if not final_final_redirect_url:
print("未找到最终最终重定向URL")
return False
response = session.get(final_final_redirect_url, headers=HEADERS, allow_redirects=False)
response.raise_for_status()
print("Response Headers: ", response.headers)
# 获取bzb_jsxsd Cookie
# print("Response Cookies: ", session.cookies.get_dict())
bzb_jsxsd = session.cookies.get("bzb_jsxsd")
if not bzb_jsxsd:
print("未找到bzb_jsxsd Cookie")
return False
print("教务系统Cookie获取成功:", bzb_jsxsd)
return True
except Exception as e:
print(f"SSO跳转失败: {e}")
return False
def query_scores():
"""查询成绩"""
params = {
"pageNum": 1,
"pageSize": 20,
"xsfs": "all",
"kksj": "2024-2025-1",
"sfxsbcxq": 1,
}
try:
response = session.get(SCORE_URL, params=params, headers=HEADERS)
response.raise_for_status()
scores = response.json()
return json.dumps(scores, ensure_ascii=False, indent=4) # 返回JSON格式
except Exception as e:
return json.dumps({"error": f"成绩查询失败: {e}"}, ensure_ascii=False, indent=4)
def query_exam_schedule():
"""查询考试安排"""
exam_schedule_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/xsks/xsksap_list"
params = {
"pageNum": 1,
"pageSize": 20,
"xnxqid": "2024-2025-1",
"xqlb": "",
}
try:
response = session.get(exam_schedule_url, params=params, headers=HEADERS)
response.raise_for_status()
exam_schedule = response.json()
return json.dumps(exam_schedule, ensure_ascii=False, indent=4) # 返回JSON格式
except Exception as e:
return json.dumps({"error": f"考试安排查询失败: {e}"}, ensure_ascii=False, indent=4)
def query_student_info():
"""查询学生信息"""
student_info_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/framework/xsMainV_new.htmlx?t1=1"
try:
response = session.get(student_info_url, headers=HEADERS)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
info_content = soup.find("div", class_="qz-infoContent")
if not info_content:
return json.dumps({"error": "未找到学生信息"}, ensure_ascii=False, indent=4)
name_id = info_content.find("div", class_="infoContentTitle").text.strip()
gender_tag = info_content.find("div", class_="man-tag")
gender = gender_tag.find("span").text.strip() if gender_tag else "未知"
info_body = info_content.find("div", class_="infoContentBody")
if info_body:
rows = info_body.find_all("div", class_="qz-rowlan")
details = [row.text.strip() for row in rows]
return json.dumps({
"姓名和学号": name_id,
"性别": gender,
"其他信息": details
}, ensure_ascii=False, indent=4)
except Exception as e:
return json.dumps({"error": f"学生信息查询失败: {e}"}, ensure_ascii=False, indent=4)
def get_kbjcmsid():
url = "http://jiaowu.nit.edu.cn:8080/jsxsd/framework/xsMainV_new.htmlx?t1=1"
response = session.get(url, headers=HEADERS)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
kbjcmsid_tag = soup.find('li', {'name': 'kbjcmsid'})
if kbjcmsid_tag:
kbjcmsid = kbjcmsid_tag.get('data-value')
return json.dumps({"kbjcmsid": kbjcmsid}, ensure_ascii=False, indent=4)
return json.dumps({"error": "获取 kbjcmsid 失败"}, ensure_ascii=False, indent=4)
def get_course_table(kbjcmsid, week=1):
url = f"http://jiaowu.nit.edu.cn:8080/jsxsd/framework/mainV_index_loadkb.htmlx?zc={week}&kbjcmsid={kbjcmsid}&xnxq01id=2024-2025-2&xswk=false"
response = session.get(url, headers=HEADERS)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
course_table = {day: [] for day in days}
rows = soup.find_all('tr', class_='qz-weeklyTable-tr')
for row in rows:
cells = row.find_all('td', class_='qz-weeklyTable-td')
if len(cells) > 1:
time_slot = cells[0].get_text(strip=True)
for i in range(1, len(cells)):
day = days[i - 1]
course_items = cells[i].find_all('li', class_='courselists-item')
if course_items:
for item in course_items:
course_name = item.find('div', class_='qz-hasCourse-title').get_text(strip=True)
details = item.find_all('div', class_='qz-hasCourse-detailitem')
teacher = details[0].get_text(strip=True).replace("教师:", "") if details else ""
location = details[-1].get_text(strip=True) if details else ""
week_info = details[-2].get_text(strip=True) if len(details) >= 2 else ""
course_info = {
"time_slot": time_slot,
"course_name": course_name,
"teacher": teacher,
"location": location,
"week_info": week_info
}
course_table[day].append(course_info)
else:
course_table[day].append({
"time_slot": time_slot,
"course_name": "没课",
"teacher": "",
"location": "",
"week_info": ""
})
return json.dumps(course_table, ensure_ascii=False, indent=4)
return json.dumps({"error": "获取课程表失败"}, ensure_ascii=False, indent=4)
def get_exmp_table():
"""获取实验课表"""
url = "http://jiaowu.nit.edu.cn:8080/jsxsd/syjx/toXskb.do"
try:
response = session.get(url, headers=HEADERS)
if response.status_code == 200:
soup = BeautifulSoup(response.content, 'html.parser')
table = soup.find('table', class_='qz-weeklyTable')
if table:
rows = table.find_all('tr')
table_data = []
for row in rows:
cells = row.find_all(['th', 'td'])
row_data = [cell.get_text(strip=True) for cell in cells]
table_data.append(row_data)
return json.dumps(table_data, ensure_ascii=False, indent=4)
else:
return json.dumps({"error": "未找到表格"}, ensure_ascii=False, indent=4)
else:
return json.dumps({"error": f"请求失败,状态码: {response.status_code}"}, ensure_ascii=False, indent=4)
except Exception as e:
return json.dumps({"error": f"获取实验课表失败: {e}"}, ensure_ascii=False, indent=4)
def format_exmp_table_data(table_data):
"""格式化实验课表数据"""
formatted_data = []
week_days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
periods = ['1-2节', '3-4节', '5-6节', '7-8节', '9-10节']
i = 0
while i < len(table_data):
week = table_data[i][0]
if week.startswith("周次"):
i += 1
continue
week_data = {'周次': week}
for j in range(5):
if i + j >= len(table_data):
break
row = table_data[i + j]
for k, day in enumerate(week_days):
# cell = row[k + 1] if k + 1 < len(row) else ""
if k + 1 < len(row):
if j == 0 and day == "周一":
cell = row[k + 2]
else:
cell = row[k + 1]
else:
cell = ""
period = periods[j]
week_data.setdefault(day, {})[period] = cell if cell else '没课'
formatted_data.append(week_data)
i += 5
return json.dumps(formatted_data, ensure_ascii=False, indent=4)
def main():
result = {
"status": "success",
"data": {}
}
try:
# 1. 获取execution参数
execution = get_execution_value()
if not execution:
result["status"] = "failed"
result["error"] = "获取execution失败"
return result
# 2. CAS登录
redirect_url = cas_login(execution)
if not redirect_url:
result["status"] = "failed"
result["error"] = "CAS登录失败"
return result
# 3. 跟随重定向链
follow_redirects(redirect_url)
# 4. 验证Portal Token
if not validate_portal_token():
result["status"] = "failed"
result["error"] = "Portal Token验证失败"
return result
# 5. SSO跳转到教务系统
if not sso_to_jwxt():
result["status"] = "failed"
result["error"] = "SSO跳转失败"
return result
# 6. 查询成绩
result["data"]["scores"] = query_scores()
# 7. 查询考试安排
result["data"]["exam_schedule"] = query_exam_schedule()
# 8. 查询学生信息
result["data"]["student_info"] = query_student_info()
# 9. 查询课程表
kbjcmsid = get_kbjcmsid()
result["data"]["kbjcmsid"] = kbjcmsid
kbjcmsid_data = json.loads(kbjcmsid)
if kbjcmsid_data.get("kbjcmsid"):
course_table = get_course_table(kbjcmsid_data["kbjcmsid"], week=5)
result["data"]["course_table"] = course_table
# 10. 查询实验课表
exmp_table = get_exmp_table()
result["data"]["exmp_table"] = exmp_table
# 11. 格式化实验课表
formatted_exmp_table = format_exmp_table_data(json.loads(exmp_table))
result["data"]["formatted_exmp_table"] = formatted_exmp_table
# 将结果写入result.json
with open("result.json", "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=4)
except Exception as e:
result["status"] = "failed"
result["error"] = f"发生错误: {str(e)}"
with open("result.json", "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=4)
if __name__ == "__main__":
main()
pyimport requests
from bs4 import BeautifulSoup
import json
class NITEduCrawler:
def __init__(self, username, password):
self.session = requests.Session()
self.username = username
self.password = password
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.70 Safari/537.36",
"Accept-Language": "zh-CN,zh;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-Requested-With": "XMLHttpRequest",
}
self.cas_login_url = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fportal.nit.edu.cn%2Fcas%2Flogin_portal"
self.score_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/kscj/cjcx_list"
self.portal_validate_url = "http://portal.nit.edu.cn/security_portal/validate_login"
self.sso_url = "http://jiaowu.nit.edu.cn/sso.jsp"
def login(self):
# 1. 获取execution参数
execution = self.get_execution_value()
if not execution:
return False
# 2. CAS登录
redirect_url = self.cas_login(execution)
if not redirect_url:
return False
# 3. 跟随重定向链
self.follow_redirects(redirect_url)
# 4. 验证Portal Token
if not self.validate_portal_token():
return False
# 5. SSO跳转到教务系统
if not self.sso_to_jwxt():
return False
return True
def get_execution_value(self):
"""从CAS登录页面获取execution参数"""
try:
response = self.session.get(self.cas_login_url, headers=self.headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
execution = soup.find("input", {"name": "execution"}).get("value")
return execution
except Exception as e:
print(f"获取execution失败: {e}")
return None
def cas_login(self, execution):
"""CAS登录"""
login_data = {
"username": self.username,
"password": self.password,
"execution": execution,
"_eventId": "submit",
"submit": "登录",
}
try:
response = self.session.post(
self.cas_login_url,
data=login_data,
headers=self.headers,
allow_redirects=False,
)
response.raise_for_status()
if response.status_code == 302:
print("CAS登录成功")
return response.headers["Location"] # 返回重定向URL
else:
print("CAS登录失败,状态码:", response.status_code)
return None
except Exception as e:
print(f"CAS登录失败: {e}")
return None
def follow_redirects(self, redirect_url):
"""跟随重定向链,获取必要的Cookies"""
try:
response = self.session.get(redirect_url, headers=self.headers, allow_redirects=True)
response.raise_for_status()
print("重定向完成,当前Cookies:", self.session.cookies.get_dict())
except Exception as e:
print(f"重定向失败: {e}")
def validate_portal_token(self):
"""验证Portal Token"""
token = self.session.cookies.get("PORTAL_TOKEN")
if not token:
print("未找到PORTAL_TOKEN")
return False
try:
response = self.session.post(
self.portal_validate_url,
data={"token": token},
headers={"Content-Type": "application/x-www-form-urlencoded"},
)
response.raise_for_status()
if response.json().get("errcode") == "0":
print("Token验证成功")
return True
else:
print("Token验证失败:", response.json())
return False
except Exception as e:
print(f"Token验证失败: {e}")
return False
def sso_to_jwxt(self):
"""通过SSO跳转到教务系统,获取bzb_jsxsd Cookie"""
try:
# 第一步:获取bzb_njw
response = self.session.get(self.sso_url, headers=self.headers, allow_redirects=False)
response.raise_for_status()
bzb_njw = self.session.cookies.get("bzb_njw")
if not bzb_njw:
print("未找到bzb_njw Cookie")
return False
print("bzb_njw Cookie获取成功:", bzb_njw)
# 第二步:跟随CAS登录URL
cas_login_url = "https://eapp2.nit.edu.cn:9443/cas/login?service=http%3A%2F%2Fjiaowu.nit.edu.cn%2Fsso.jsp"
response = self.session.get(cas_login_url, headers=self.headers, allow_redirects=False)
response.raise_for_status()
# 第三步:跟随ticket重定向
ticket_url = response.headers.get("Location")
if not ticket_url:
print("未找到ticket URL")
return False
response = self.session.get(ticket_url, headers=self.headers, allow_redirects=False)
response.raise_for_status()
# 第四步:最终跳转到教务系统
final_redirect_url = response.headers.get("Location")
if not final_redirect_url:
print("未找到最终重定向URL")
return False
response = self.session.get(final_redirect_url, headers=self.headers, allow_redirects=False)
response.raise_for_status()
# 第五步:获取bzb_jsxsd Cookie
final_final_redirect_url = response.headers.get("Location")
if not final_final_redirect_url:
print("未找到最终最终重定向URL")
return False
response = self.session.get(final_final_redirect_url, headers=self.headers, allow_redirects=False)
response.raise_for_status()
bzb_jsxsd = self.session.cookies.get("bzb_jsxsd")
if not bzb_jsxsd:
print("未找到bzb_jsxsd Cookie")
return False
print("教务系统Cookie获取成功:", bzb_jsxsd)
return True
except Exception as e:
print(f"SSO跳转失败: {e}")
return False
def query_scores(self):
"""查询成绩"""
params = {
"pageNum": 1,
"pageSize": 20,
"xsfs": "all",
"kksj": "2024-2025-1",
"sfxsbcxq": 1,
}
try:
response = self.session.get(self.score_url, params=params, headers=self.headers)
response.raise_for_status()
return response.json()
except Exception as e:
raise Exception(f"成绩查询失败: {e}")
def query_exam_schedule(self):
"""查询考试安排"""
exam_schedule_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/xsks/xsksap_list"
params = {
"pageNum": 1,
"pageSize": 20,
"xnxqid": "2024-2025-1",
"xqlb": "",
}
try:
response = self.session.get(exam_schedule_url, params=params, headers=self.headers)
response.raise_for_status()
return response.json()
except Exception as e:
raise Exception(f"考试安排查询失败: {e}")
def query_student_info(self):
"""查询学生信息"""
student_info_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/framework/xsMainV_new.htmlx?t1=1"
try:
response = self.session.get(student_info_url, headers=self.headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
info_content = soup.find("div", class_="qz-infoContent")
if not info_content:
raise Exception("未找到学生信息")
name_id = info_content.find("div", class_="infoContentTitle").text.strip()
gender_tag = info_content.find("div", class_="man-tag")
gender = gender_tag.find("span").text.strip() if gender_tag else "未知"
info_body = info_content.find("div", class_="infoContentBody")
if info_body:
rows = info_body.find_all("div", class_="qz-rowlan")
details = [row.text.strip() for row in rows]
return {
"姓名和学号": name_id,
"性别": gender,
"其他信息": details
}
except Exception as e:
raise Exception(f"学生信息查询失败: {e}")
def get_course_table(self, week=1):
kj_url = "http://jiaowu.nit.edu.cn:8080/jsxsd/framework/xsMainV_new.htmlx?t1=1"
response = self.session.get(kj_url, headers=self.headers)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
kbjcmsid_tag = soup.find('li', {'name': 'kbjcmsid'})
if kbjcmsid_tag:
kbjcmsid = kbjcmsid_tag.get('data-value')
"""查询课程表"""
url = f"http://jiaowu.nit.edu.cn:8080/jsxsd/framework/mainV_index_loadkb.htmlx?zc={week}&kbjcmsid={kbjcmsid}&xnxq01id=2024-2025-2&xswk=false"
try:
response = self.session.get(url, headers=self.headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
course_table = {day: [] for day in days}
rows = soup.find_all('tr', class_='qz-weeklyTable-tr')
for row in rows:
cells = row.find_all('td', class_='qz-weeklyTable-td')
if len(cells) > 1:
time_slot = cells[0].get_text(strip=True)
for i in range(1, len(cells)):
day = days[i - 1]
course_items = cells[i].find_all('li', class_='courselists-item')
if course_items:
for item in course_items:
course_name = item.find('div', class_='qz-hasCourse-title').get_text(strip=True)
details = item.find_all('div', class_='qz-hasCourse-detailitem')
teacher = details[0].get_text(strip=True).replace("教师:", "") if details else ""
location = details[-1].get_text(strip=True) if details else ""
week_info = details[-2].get_text(strip=True) if len(details) >= 2 else ""
course_info = {
"time_slot": time_slot,
"course_name": course_name,
"teacher": teacher,
"location": location,
"week_info": week_info
}
course_table[day].append(course_info)
else:
course_table[day].append({
"time_slot": time_slot,
"course_name": "没课",
"teacher": "",
"location": "",
"week_info": ""
})
return course_table
except Exception as e:
raise Exception(f"获取课程表失败: {str(e)}")
def get_exmp_table(self):
"""获取实验课表"""
url = "http://jiaowu.nit.edu.cn:8080/jsxsd/syjx/toXskb.do"
try:
response = self.session.get(url, headers=self.headers)
if response.status_code == 200:
soup = BeautifulSoup(response.content, 'html.parser')
table = soup.find('table', class_='qz-weeklyTable')
if table:
rows = table.find_all('tr')
table_data = []
for row in rows:
cells = row.find_all(['th', 'td'])
row_data = [cell.get_text(strip=True) for cell in cells]
table_data.append(row_data)
table_data = self.format_exmp_table_data(table_data)
return json.dumps(table_data, ensure_ascii=False, indent=4)
else:
return json.dumps({"error": "未找到表格"}, ensure_ascii=False, indent=4)
else:
return json.dumps({"error": f"请求失败,状态码: {response.status_code}"}, ensure_ascii=False, indent=4)
except Exception as e:
return json.dumps({"error": f"获取实验课表失败: {e}"}, ensure_ascii=False, indent=4)
def format_exmp_table_data(self,table_data):
"""格式化实验课表数据"""
formatted_data = []
week_days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
periods = ['1-2节', '3-4节', '5-6节', '7-8节', '9-10节']
i = 0
while i < len(table_data):
week = table_data[i][0]
if week.startswith("周次"):
i += 1
continue
week_data = {'周次': week}
for j in range(5):
if i + j >= len(table_data):
break
row = table_data[i + j]
for k, day in enumerate(week_days):
# cell = row[k + 1] if k + 1 < len(row) else ""
if k + 1 < len(row):
if j == 0 and day == "周一":
cell = row[k + 2]
else:
cell = row[k + 1]
else:
cell = ""
period = periods[j]
week_data.setdefault(day, {})[period] = cell if cell else '没课'
formatted_data.append(week_data)
i += 5
return json.dumps(formatted_data, ensure_ascii=False, indent=4)
if __name__ == "__main__":
USERNAME = "2022102191" # 替换为你的用户名
PASSWORD = "3485000346zyhQWM" # 替换为你的密码
crawler = NITEduCrawler(USERNAME, PASSWORD)
if crawler.login():
# 登录成功后可以调用其他方法查询数据
try:
scores = crawler.query_scores()
print("成绩查询结果:", scores)
exam_schedule = crawler.query_exam_schedule()
print("考试安排查询结果:", exam_schedule)
student_info = crawler.query_student_info()
print("学生信息查询结果:", student_info)
# 查询课程表
course_table = crawler.get_course_table()
print("课程表查询结果:", course_table)
# 查询实验课表
exmp_table = crawler.get_exmp_table()
print("实验课表查询结果:", exmp_table)
# 将结果写入文件
with open("result.json", "w", encoding="utf-8") as f:
json.dump({
"scores": scores,
"exam_schedule": exam_schedule,
"student_info": student_info,
"course_table": course_table,
"exmp_table": exmp_table
}, f, ensure_ascii=False, indent=4)
except Exception as e:
print("查询数据时发生错误:", e)
else:
print("登录失败")
本文作者:yowayimono
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!