前提:本文僅做爲技術訓練,不可利用技術作非法的事。html
某考試的成績查詢頁面以下:查詢成績須要的數據有准考證號或者身份證、考生姓名、驗證碼。如今使用python來實現自動查詢指定人員的考試成績(不知道准考證號的前提下)。主要使用的包有Tesseract-OCR、PIL、execjs、pytesseract、BeautifulSouppython
查詢頁面:web
入圍名單:服務器
包的功能介紹:cookie
主要介紹Tesseract-OCR安裝,其餘包可經過pip+包名自行安裝。dom
安裝完成後將Tesseract-OCR添加進path環境變量;而後新建環境變量TESSDATA_PREFIX:安裝目錄\Tesseract-OCR\tessdata。而後重啓計算機。socket
cmd輸入tesseract顯示以下則安裝成功:jsp
使用正確的帳號信息登錄,收集header、cookies及其餘信息(例如本次登錄就使用到加密的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 = { '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' }
#裝載 CTX = execjs.compile(JSCode) #調用 CTX.call('函數名', '實參')
爲了將准考證號中隱藏的數字找出來,咱們須要不斷遍歷。直到考號跟姓名對應。post
這裏的驗證碼在訪問成績頁面時就產生了,因此須要因此使用requests.get(url1, headers=header)來將驗證碼下載到本地,而後識別出來,接着在模擬查詢按鈕動做 requests.get(url2, headers=header)
,將全部信息塞入查詢字符串進行查詢,因爲是遍歷查詢,一旦循環產生的考號與已知的姓名匹配,就會返回結果,查詢結束。
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
遍歷文檔樹後查詢指定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
參考: