【背景】
每当成绩刚出的时候,大批考生急切知晓自己的成绩,相继涌入教育部开放的成绩查询接口。这样带来的后果就相当于在一瞬间给接口进行了一次DDOS攻击。就导致服务器存在一定程度上的崩溃,本着服务大众的原则。本文开发一种便捷的查询脚本。帮助考生快速完成成绩查询工作
【源码运行环境】
Python 3.7
【分析】
在平常的web使用过程中,我们知道在加载一个web页面时,需要进行如下操作:下载 img(图片文件)、下载js脚本、下载css样式以及html渲染,除了html渲染是在本地浏览器上进行的,其余操作都需要从web服务器上抓取。
而在一台没有使用均衡负载,网络带宽有限的服务器上完成上述提及的文件下载,需要一定的资源。如果web访问流量小,单机是可以满足查询的需求的。但是,如果放眼于广大考生,积少成多,这样服务器的压力就会大大提升,从而对部分的考生造成崩溃的现象。
引用生活中排队的例子。我们去银行办理业务,倘若银行不实施取号排队的政策,在业务窗口有限的情况下,假若办理业务的客户一多(这几个小窗口远不能满足),大家伙都挤在这几个窗口,你说一句我说一句,在窗口的业务员东处理一点西处理一点,就导致了影响了整体办理业务的效率。
在上述所谈中,我们就本次web需求进行分析:
我们把web查询接口当做是银行办理业务的窗口。
在业务中,我们需要填表,到指定窗口办理,到银行后台(客户经理)进行确认,反馈结果
在实际查询中,我们会遇到如下情况:
1、一切正常。(效率极高)
2、能加载出html页面,但是没有验证码。(没填表,排到业务办理窗口,业务窗口也很懵逼)
3、能加载出html页面,有验证码,提交请求后页面无反应(表填了,业务窗口也接了表了,但是客户经理太忙了,确认不过来了)
4、能加载出html页面,有验证码,提交请求后页面告知验证码错误(表填了,业务窗口也接了表了,客户经理发现过了一会觉得这份表过期了,让你重填)
5、能加载出html页面,有验证码,提交请求后页面告知个人信息错误 (表填了,业务窗口也接了表了,客户经理发现过了一会觉得这份表有错误,让你重填)
等等
从上述递进的例子中,我们知道。假若银行(web)没有采取制衡政策,那么我们要想正确办理业务,就必须按部就班地进行业务的办理。这样我们办理业务的结果就能掌控在自己的手中。效率也会提高。
也就是说,因为web服务调度的因素,可能同时给不同的人不同的结果,但是我们如果目标很明确,我在没有填表前一定要填好表,填好表格之后交到业务大厅,之后再由业务大厅交由客户经理进行审核。等待结果。
在我们这样做了一系列事情,我们就确保了,不会产生上述2、5两种情况。
回到最开始的分析,我们知道要渲染一个html页面还需要从web服务器拿图片,拿js,css样式。就好比我们去银行,本来只需要办理业务,但是银行窗口却给了你一份关于金融产品的推销。而在拥挤的业务处理过程,这样的操作是可以拒绝的。
【原理】
在更专业地对该web系统进行分析过后。
我们总结出要办理查询业务需要进行下述操作:
1、拿验证码(填表)
2、构造查询数据(POST,GET)(填表)
3、发送post数据(提交到业务办理窗口)
4、等待结果(等待客户经理审核)
【源码实现】
我们利用python进行模拟,给出源码如下:
# -*- coding:utf-8 -*- """ 包导入处理 本次实验共需要如下几个包 urllib 提供http请求API cookiejar 提供cookie支持 """ from urllib.request import Request import urllib.request import urllib.parse from http.cookiejar import CookieJar """ 三个全局变量 URL:成绩查询主网站接口 POSTURL: 查询接口 YZMURL: 验证码获取接口 """ URL = 'https://ntcecf6.neea.edu.cn/' POSTURL = URL+ 'selectScore.do' YZMURL = URL + 'getYZM' """ 方法名:query 作用:查询逻辑主函数 参数:name->名字 zjhm->证件号码 Author: WellLee 最后一次修改时间:2018年12月12日 12:39:45 """ def query(name, zjhm): cj = CookieJar() browser = urllib.request.HTTPCookieProcessor(cj) browser = urllib.request.build_opener(browser) #前期准备工作,先构造HTTP运行容器 html = browser.open(YZMURL) #抓取验证码 while html.code != 200: #不扫出验证码就继续构造请求 html = browser.open(YZMURL) picture = html.read() # 保存验证码 with open('./captcha.png', 'wb') as f: f.write(picture) captcha = input("请输入验证码") # 请求用户输入验证码 querydata = { "method": 'getMyScore', "name": name, "zjhm": zjhm, "yzm": captcha, } querydata= urllib.parse.urlencode(querydata).encode('utf-8') #构造post数据 request = Request(POSTURL, querydata) response = browser.open(request) #构造post请求 while response.code != 200: #不得到结果就继续发起请求,直到有结果为止 response = browser.open(request) html = response.read().decode('utf-8') print(html) # 将结果输出 if __name__ == '__main__': #主函数 query('姓名', '证件号码')
【总结】
一次投机取巧的爬虫实战,温习了爬虫相关知识。
在本次实战中发现验证码是可以通过深度学习训练进行识别的。(相对简单),但时间有限没有深究。日后勉励吧。