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\tessdata。然后重啟計算機。

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:\PycharmProjects\untitled1\yanzhengma.png')
            pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract.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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM