【背景】

每当成绩刚出的时候,大批考生急切知晓自己的成绩,相继涌入教育部开放的成绩查询接口。这样带来的后果就相当于在一瞬间给接口进行了一次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('姓名', '证件号码')

【总结】

一次投机取巧的爬虫实战,温习了爬虫相关知识。

在本次实战中发现验证码是可以通过深度学习训练进行识别的。(相对简单),但时间有限没有深究。日后勉励吧。

作者 WellLee

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注