教務處考試系統(tǒng)自動答題

學校要求登錄教務處網(wǎng)站做一個測試題蔑歌,我做了看了看,30分鐘300道題掀鹅,240分幾個散休,題量不少,題還不好做乐尊。研究了一下發(fā)現(xiàn)原來在網(wǎng)站上就有題庫的戚丸,但是一道題只有6s 的時間作答,邊查邊做肯定是時間不夠的扔嵌。靈光一閃限府,人生苦短猴鲫,我用Python,寫個自動答題的機器人吧谣殊。


思路:

  • 爬取題庫并存儲到數(shù)據(jù)庫
  • 模擬登錄教務系統(tǒng)
  • 進入答題頁面拂共,遍歷題目,匹配數(shù)據(jù)庫中記錄姻几,給出答案
  • 提交數(shù)據(jù)

用到的工具:

  • Python
  • requests
  • BeautifulSoup
  • mongodb

實現(xiàn)過程:

  • 模擬登錄

以前研究過學校教務系統(tǒng)的登錄宜狐,現(xiàn)在終于在正事上排上用場了。學校教務系統(tǒng)的登錄還算簡單蛇捌,沒有驗證碼抚恒,唯一一點兒小障礙是登錄表單會有幾個隱藏字段,有個字段會動態(tài)改變络拌,解決就是先GET一下登錄網(wǎng)址俭驮,獲取這幾個字段的值,再隨表單進行POST春贸。代碼:

import requests
from bs4 import BeautifulSoup
import os

headers = {
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate, sdch',
    'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4'
}

session = requests.session()

# 先GET一下登錄頁面獲得隱藏字段
resp = session.get("http://ids.qfnu.edu.cn/authserver/login?service=http%3A%2F%2F202.194.188.19%2Fcaslogin.jsp", headers=headers)
bsObj = BeautifulSoup(resp.text, "html.parser")     
lt = bsObj.find('input', {'name':'lt'})['value']
execution = bsObj.find('input', {'name':'execution'})['value']

params = {
    'username': os.environ.get('STU_ID'),   # 環(huán)境變量獲取的學號
    'password': os.environ.get('STU_PWD'), # 環(huán)境變量獲取的密碼
    'lt': lt,
    'execution': execution,
    '_eventId': 'submit',
    'rmShown': '1'
}

# post 數(shù)據(jù)登錄成功
resp = session.post("http://ids.qfnu.edu.cn/authserver/login?service=http%3A%2F%2F202.194.188.19%2Fcaslogin.jsp", data=params, headers=headers)

  • 題庫爬取

用了Python的requests庫進行頁面的爬取混萝,勵志小哥寫的這個庫的確好用,特別是運用 requests.session()之后萍恕,處理好登錄之后逸嘀,再也不用管那些煩人的cookie 啥的了,用了BeautifulSoup來進行頁面解析允粤,用起來也是很順手崭倘。開始有亂碼,一看網(wǎng)頁編碼是gb2312的类垫,稍微設置一下也OK了司光。
內(nèi)容有了,當然要存儲起來了悉患,不然每次答題都有爬題庫多麻煩残家,何況是些千年不變的東西。開始用的是MySQL购撼,然而編碼問題讓人頭疼跪削,設置編碼為gb2312谴仙,存儲的時候說有內(nèi)容 gb2312 又解析不了迂求,于是程序就掛了。搞了很長時間也沒搞定晃跺,還把我的 Sequel Pro 給搞掛了揩局,f***!
靜下心來一想,題庫只要寫數(shù)據(jù)庫寫一遍就OK了掀虎,但是答題的時候會頻繁地查詢數(shù)據(jù)庫凌盯,用nosql數(shù)據(jù)庫多好付枫。題目做鍵,答案做值就行了驰怎〔玻看過redis,但畢竟是內(nèi)存型數(shù)據(jù)庫县忌,雖然快掂榔,但是還要做持久化,直接用mongodb吧症杏,還沒看過装获,剛好學習了,邊學邊用厉颤。
爬取并存儲題庫部分的代碼:

tikubhs = [8692, 10988, 10989, 10990, 10991, 10992, 10993, 10994, 10995]  # 每一類題庫的編號
pages = [153, 77, 13, 18, 22, 27, 10, 39, 12]  # 每一個題庫的題目頁數(shù)

from pymongo import MongoClient
client = MongoClient()
db = client.shitiDB    # 數(shù)據(jù)庫名 shitiDB

shiti_table = db.shitis    # 表名 shitis

for tikubh, page_range in zip(tikubhs, pages):
    for page in range(1, page_range+1):
        url = "http://aqjy.qfnu.edu.cn/redir.php?catalog_id=6&cmd=learning&tikubh="+str(tikubh)+"&page="+str(page)
        resp = session.get(url)
        resp.encoding = 'gb2312'
        bsObj = BeautifulSoup(resp.text, "html.parser")
        shitis = bsObj.find_all('div', class_='shiti')
        daans = bsObj.find_all('span', style='color:#666666')
        values = []
        for timu_str, daan_str in zip(shitis, daans):
            shitibh = int(timu_str.h3.text[0:5])
            timu = timu_str.h3.text[6:]
            daan = daan_str.text[daan_str.text.find('標準答案')+5:].strip(' )')
            d = {'shitibh':shitibh, 'tikubh':tikubh, 'timu':timu, 'daan':daan}
            values.append(d)
        new_result = shiti_table.insert_many(values)

  • 模擬作答

這一部分是最關鍵的部分穴豫,再這上面的耗時比較多,大部分時間都在研究他的數(shù)據(jù)的提交流程逼友。
題目是分頁的精肃,且選擇頁面或點擊上下頁的時候,地址欄的地址是不變的帜乞,說明分頁是通過js實現(xiàn)的肋杖,而不是直接用的鏈接:


研究得知,上下頁和頁面選擇都是通過post數(shù)據(jù)標志到本頁面實現(xiàn)的

搞懂了這些數(shù)據(jù)的意義和他們之間的關系挖函,用代碼模擬出來就OK了状植,當作到最后一頁完成的時候,把tijiao標志也設為1怨喘,POST到原URL就完成了作答津畸,這部分代碼就不貼了,文末有GitHub鏈接必怜。

  • 可能的改進

    • 寫好之后許多同學找我給答題肉拓,看看如果多的話用flask搭成個web服務。高效還不用擔心我泄露你們的密碼了梳庆。
    • 爬題庫的時候想的是爬答案的文本暖途,爬成了ABCD的選項,多虧選項和答案文本的對應關系沒變膏执,但也造成個別問題答案會有錯誤驻售,致使我給答題的同學分數(shù)基本都在297-299之間(滿分300分),少有300分的同學更米。本來想改來著欺栗,轉念一想都滿分也不太好,有點誤差也好,可能這部分不會改了迟几,感興趣的可以自己改改看消请。

ps: 本校的可以直接搭好拿來用就可以了,其他同學如有類似需求类腮,這個系統(tǒng)是某公司開發(fā)的臊泰,好多學校都在用,folk一份改改應該也沒問題蚜枢。 戳到github吧因宇,歡迎 star、folk祟偷。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末察滑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子修肠,更是在濱河造成了極大的恐慌贺辰,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嵌施,死亡現(xiàn)場離奇詭異饲化,居然都是意外死亡,警方通過查閱死者的電腦和手機吗伤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門吃靠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人足淆,你說我怎么就攤上這事巢块。” “怎么了巧号?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵族奢,是天一觀的道長。 經(jīng)常有香客問我丹鸿,道長越走,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任靠欢,我火速辦了婚禮廊敌,結果婚禮上,老公的妹妹穿的比我還像新娘门怪。我一直安慰自己骡澈,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布薪缆。 她就那樣靜靜地躺著秧廉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拣帽。 梳的紋絲不亂的頭發(fā)上疼电,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音减拭,去河邊找鬼蔽豺。 笑死,一個胖子當著我的面吹牛拧粪,可吹牛的內(nèi)容都是我干的修陡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼可霎,長吁一口氣:“原來是場噩夢啊……” “哼魄鸦!你這毒婦竟也來了?” 一聲冷哼從身側響起癣朗,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤拾因,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后旷余,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绢记,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年正卧,在試婚紗的時候發(fā)現(xiàn)自己被綠了蠢熄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡炉旷,死狀恐怖签孔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窘行,我是刑警寧澤骏啰,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站抽高,受9級特大地震影響判耕,放射性物質發(fā)生泄漏。R本人自食惡果不足惜翘骂,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一壁熄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碳竟,春花似錦草丧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春懂拾,著一層夾襖步出監(jiān)牢的瞬間煤禽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工岖赋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留檬果,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓唐断,卻偏偏與公主長得像选脊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子脸甘,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容