选课助手是如何炼成的

我们学校的教务系统采用了强智科技的数字化校园平台
选课助手是如何炼成的
文章图片


可能是因为发现和非ie浏览器有兼容问题,所以在创建XMLHttpRequest时加了一个条件(如下的 1==2 ),限制了非ie浏览器的正常运行:

if(window.XMLHttpRequest && 1==2 ) { http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { http_request.overrideMimeType("text/xml"); } }

这在现在流通的win8.1+ie11上问题并不大,只是破灭了许多试图用手机浏览器抢课的孩童的美好心愿,很残忍

第二个比较大的问题是服务器并发性能差,如果是12点整开始选课,11点50就有点难以刷出登陆页了;开始选课之后,大多数人几分钟都是在等待课表被刷出来的状态,而且往往刷出来的是 “请与管理员联系” 在这种寸时寸金的时候,晚一秒钟,心仪的课就没了(比如只有30个名额的乒乓球),这个时候下行的流量率是非常大的:

GET /kdjw/xkglAction.do?method=toXk&xnxq=2014-2015-1&zzdxklbname=1&type=1&xkkssj=2014-09-01%2012:00&xkjzsj=2014-09-15%2000:00&tktime=1410266865000 HTTP/1.1


算了,懒得打码。从上面可以看出服务器使用了struts。 关键是学校蛋疼的把一个80多行的表格分为了两页:
选课助手是如何炼成的
文章图片

第一页显示50行,这样的处理,直接导致了下行更加拥堵,另一页还时常刷不出来,所以很多人都随便在第一页选了一门课就提交了。


而我的选课助手在这里做的改进就是只下载一次表格,然后把两张表的数据都显示出来,以后不再需要下行流量,只要服务器的session没有删除,什么时候都可以提交课表
选课助手是如何炼成的
文章图片



总的来说,我做的选课助手在速度上的优势在:
1、登录过一次后记住账号密码,只需要输入验证码(验证码识别模块因为识别率低,暂时没有加入,否则可能会更快些),这个在ie浏览器上是没有的。
2、减少了很多不必要的下载流量,比如网页、js文件、图片等等,整个下行只有登录页和课表页,三次服务器请求,大概500KB不到的流量。
3、减少了流程步骤。在ie流量器选课需要4-5次点击,而且在并发高的时候很容易中断,以至于无法进行下一次点击。


【选课助手是如何炼成的】当然还有更强大的策略选项,比如在不知道课表的情况下可以选包含某字符串的课程,或者发送多个请求知道请求被服务器响应为止等等。


最后说说在编码中得到的一些经验与收获,可能可以给看到这篇博文的人一个帮助。
1、强智平台在登录过程中需要向http://kdjw.hnust.cn/kdjw/Logon.do?method=logonBySSO 发送一个空白的post,才算正常的登录上了
选课助手是如何炼成的
文章图片


而正因为之前说的js屏蔽了非ie浏览器初始化XMLHttpRequest,导致非ie浏览器无法发送这个post,所以即使能请求出课表,也没有名为选中的链接。
2、因为请求到的网页字符串都是以utf8保存的,导致在转换到char *的时候输出乱码,这个时候需要转换编码,而网上找的转换函数都不太靠谱。这有个很好的函数,贴出来:

int ConvUtf8ToAnsi(CString& strSource, CString& strChAnsi) { if (strSource.GetLength() <= 0) return 0; CString strWChUnicode; strSource.TrimLeft(); strSource.TrimRight(); strChAnsi.Empty(); int iLenByWChNeed = MultiByteToWideChar(CP_UTF8, 0, strSource.GetBuffer(0), strSource.GetLength(), //MultiByteToWideChar NULL, 0); int iLenByWchDone = MultiByteToWideChar(CP_UTF8, 0, strSource.GetBuffer(0), strSource.GetLength(), (LPWSTR)strWChUnicode.GetBuffer(iLenByWChNeed * 2), iLenByWChNeed); //MultiByteToWideCharstrWChUnicode.ReleaseBuffer(iLenByWchDone * 2); int iLenByChNeed= WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)strWChUnicode.GetBuffer(0), iLenByWchDone, NULL, 0, NULL, NULL); int iLenByChDone= WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)strWChUnicode.GetBuffer(0), iLenByWchDone, strChAnsi.GetBuffer(iLenByChNeed), iLenByChNeed, NULL, NULL); strChAnsi.ReleaseBuffer(iLenByChDone); if (iLenByWChNeed != iLenByWchDone || iLenByChNeed != iLenByChDone) return 1; return 0; }


3、至于用到的libcurl、htmlcxx等等开源的库相关的知识,我会另外做一个贴记录下来,可能会对以后的人有帮助。

最后再描述一下整个思路:
先访问登陆页,保存cookie,这个cookie就是身份验证。然后带cookie把账号密码验证码post到登录servlet,判断一下返回的页面是不是登录成功,随后post空白正文到logonBySSO,这个时候再get选课单下来,用htmlcxx分析,把必要的字符串保存到文本中,随后弹出显示表格的对话框,解析文本并显示出来,其中选课的链接就保存到宽度为0的列中,方便解析。之后等待用户操作,当双击某行时,get此行课的选课链接,把返回的正文弹出啦,等待用户下一步操作,循环。


    推荐阅读