zoukankan      html  css  js  c++  java
  • Python3实现自动查询成绩(主要使用的包有Tesseract-OCR、PIL、execjs、pytesseract、BeautifulSoup)

    前提:本文仅作为技术训练,不可利用技术做非法的事。


    某考试的成绩查询页面如下:查询成绩需要的数据有准考证号或者身份证、考生姓名、验证码。现在使用python来实现自动查询指定人员的考试成绩(不知道准考证号的前提下)。主要使用的包有Tesseract-OCR、PIL、execjs、pytesseract、BeautifulSoup

    查询页面:

     

    入围名单:

     包的功能介绍:

    • execjs:由于查询成绩参数加密后发送给服务器,这里使用调用原网站的加密函数加密查询字符串。
    • BeautifulSoup:建立爬取的网页的文档树。
    • PIL:中的Image函数读取下载下来的验证码图片,实例化后传给Tesseract-OCR识别。
    • Tesseract-OCR:读取图片验证码,识别图片中的数字(主要其中有图片的训练集)。
    • pytesseract:tesseract_cmd来初始化Tesseract-OCR,然后使用image_to_data()方法识别图片中的数字,该方法接受Image实例化后的图片对象为参数。

    第一步:安装环境

     主要介绍Tesseract-OCR安装,其他包可通过pip+包名自行安装。

    安装完成后将Tesseract-OCR添加进path环境变量;然后新建环境变量TESSDATA_PREFIX:安装目录Tesseract-OCR essdata。然后重启计算机。

    cmd输入tesseract显示如下则安装成功:


    第二步:登陆网站收集信息

     使用正确的账号信息登陆,收集header、cookies及其他信息(例如本次登陆就使用到加密的js)。

    • 加密js信息:(根据发送的查询字符串是否需要加密来决定是否添加
    JSCode = r'''
    /*
    *(1).加密:
    *  第一步:strEncode(data,firstKey,secondKey,thirdKey);
    *(2).解密:
    *  第一步:strDecode(data,firstKey,secondKey,thirdKey);
    */
    /*
    * encrypt the string to string made up of hex
    * return the encrypted string
    */
    
    中间内容略
    
    /*end*/
    
    '''
    • header相关信息
    header = {
            'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Connection': 'keep-alive',
            'Cookie': 'JSESSIONID=E9A7EF615C2A7FC0D99711C8697D158B',
            'Host': '***.***.***.***',
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
        }
    •  在python中可以使用如下方式调用js中的代码:
    #装载
    CTX = execjs.compile(JSCode)
    
    #调用
    CTX.call('函数名', '实参')

    第三步:模拟登陆(考号+姓名+验证码)

    为了将准考证号中隐藏的数字找出来,我们需要不断遍历。直到考号姓名对应。

    这里的验证码在访问成绩页面时就产生了,所以需要所以使用requests.get(url1, headers=header)来将验证码下载到本地,然后识别出来,接着在模拟查询按钮动作 requests.get(url2, headers=header)

    ,将所有信息塞入查询字符串进行查询,由于是遍历查询,一旦循环产生的考号与已知的姓名匹配,就会返回结果,查询结束。

    • 模拟登陆,并返回查询结果req2.text
    def get_content(number='201902300365', name='张三'):#填入一个正确的默认信息
        number = CTX.call('strEncode', number) #调用js加密数字,以下类同
        name = CTX.call('strEncode', name)
        url1 = 'http://***.***.***.***/2019****/register/image.jsp'
        header = null #
        while True:
            try:
                req1 = requests.get(url1, headers=header)
                img = req1.content
                with open('./yanzhengma.png', 'wb') as f:
                    f.write(img)
                im = Image.open(r'D:PycharmProjectsuntitled1yanzhengma.png')
                pytesseract.pytesseract.tesseract_cmd = r'C:Program Files (x86)Tesseract-OCR	esseract.exe'
                num = pytesseract.image_to_data(im) #识别验证码中的数字
                input_yznumber = num[-4:] #将结果的最后四位数字取出,即验证码
    
                yznumber = CTX.call('strEncode', input_yznumber)
                url2 = 'http://***.***.***.***/2019****/printInfo.do?activity=cjddy&number=' + number + '&name=' + name + '&yznumber=' + yznumber
                req2 = requests.get(url2, headers=header)
                req2.encoding = 'utf-8'
                break
            except socket.timeout as e:
                print('3:', e)
                time.sleep(random.choice(range(8, 15)))
            except socket.error as e:
                print('4:', e)
                time.sleep(random.choice(range(20, 60)))
            except http.client.BadStatusLine as e:
                print('5:', e)
                time.sleep(random.choice(range(30, 80)))
            except http.client.IncompleteRead as e:
                print('6:', e)
                time.sleep(random.choice(range(5, 15)))
        return req2.text
    • 使用BeautifulSoup遍历文档树:

     遍历文档树后查询指定dom(本例是div)下的内容:

    def get_data(xml_data):
        bs = BeautifulSoup(xml_data, "html.parser")
        scores = bs.find_all('div', string=re.compile('2019')) #考号的前几位
        return scores
    • 启动程序,遍历查询
    if __name__ == "__main__":
        for kc in range(3000, 4601): #考场号 范围可从0-9999 根据考号规则改变
            for zwh in range(0, 1000): #最大座位号是999
                if len(str(zwh)) == 1:
                    number = '20190'+str(kc)+'00'+str(zwh)
                elif len(str(zwh)) == 2:
                    number = '20190'+str(kc) + '0'+str(zwh)
                else:
                    number = '20190'+str(kc) + str(zwh)
                print("number = ", number)
                zhunkaohao = get_data(get_content(number='20191' + str(zwh)+'173', name='焦作'))
                if zwh % 50 == 0:
                    t_zhunkaohao=get_data(get_content(number='201902300365', name='张三')) #每50次返回一个正确结果,来确保查询正确性
                    print("***************"+str(t_zuoweihao))
                if zhunkaohao != []:
                    print(zhunkaohao)
                    break #查询成功 跳出循环

    由于涉密,这里就不附上源码了。

    需要引入以下包:

    # coding: utf-8
    import socket
    from bs4 import BeautifulSoup
    import requests, random, time, http
    import execjs
    import re
    import pytesseract
    from PIL import Image

    参考:

    基于tesseract-OCR进行中文识别

    加密js

  • 相关阅读:
    [解决]WLAN设置静态IP后不能上网(Internet)
    风险类型(已知,已知未知,未知未知)
    申请PDU流程(自我学习类型PDU)
    SharePoint 2010中如何迁移(拷贝)工作流(How to migrate/copy workflow)
    如何让域用户登录SharePoint记住密码
    PMBOK成本预算组成图解
    SharePoint 2010在FireFox浏览器中的功能限制
    如何在SharePoint中配置Visio Graphics Service
    [转]地理编码服务 GeoCode Service
    SharePoint 2010工作流介绍
  • 原文地址:https://www.cnblogs.com/hoaprox/p/11050228.html
Copyright © 2011-2022 走看看