分享

使用python自动进行华医网考试

 wenxuefeng360 2022-07-21 发布于四川
背景说明

在github上发现一个古老的华医网考试脚本(https://github.com/lhzzzzzz/autoexamofhuayi),是python2写的。它实现了华医网自动登录、自动获取考试编号cwid、自动考试。现在把它翻新一下。

脚本功能

基于已知的考试编号cwid,进行华医网自动考试。

需要用到的工具(开发环境)

1、Google Chrome;

2、Fiddler:用于抓包;

3、PyCharm

思路分析

一、答题流程分析

已有现在的Javascript脚本(《华医网自动答题脚本》),根据华医网的答题代码,进行自动答题。但这个代码使用的是试错了,反复提交需要消耗时间,不适合批量操作。

根据GitHub现有脚本(https://github.com/lhzzzzzz/autoexamofhuayi),发现华医网是直接把原答案放在试题的网页中

图片

所以其实在答题界面,用chrome的F12进行Inspect,也能找到正确答案。

图片


name="gvQuestion$ctl03$result" 对应的 value即正确答案的value

通过Fiddler抓包可以看到,考试主要包括三个动作:

1、GET 考试试题

2、POST 考试试题+答案

3、GET 考试结果

而其中

POST答案提交的data包括以下几部分:

1、__EVENTTARGET 等是 ASP.Net 相关验证参数:可以从考试界面的网页中用正则表达式提取;其中留空的字段可以不提交

2、Hidden1、Hidden2、Hidden3:表示最前面的课程评价星级,可以不提交;

3、gvQuestion$ctl03$question_id、gvQuestion$ctl03$result、gvQuestion$ctl03$rbl :表示题号、正确选项、考生选项(这里当然是直接提交正确选项的value)

图片

二、模拟登录华医网

根据旧的py脚本,以前的华医网登录不需要验证码,现在有了图片验证码,登录变得麻烦了。还是改成手动复制Fiddler抓到的cookie吧

参考:https://github.com/ZhaoKangming/Generate_CME_data_report/blob/master/get_cme_course_info.py

https://github.com/ZhaoKangming/HuaYi

三、Session会话保持

华医网登录之后使用Session进行对话,获取考卷、提交考试、获取成绩都会刷新cookie,而且只有最新的cookie能进行下次对话。

所以这里需要用requests.session()保持会话,而且起始的cookie必须是最新的一个cookie

使用流程(代码实现)
# 原代码地址:https://github.com/lhzzzzzz/autoexamofhuayi
import requestsimport re
# 设置Fiddler代理proxies = { "http": "http://127.0.0.1:8888", "https": "http://127.0.0.1:8888",}session = requests.session()# 打开 cookie.txt,复制最新一次对话的cookieswith open("cookie.txt", "r") as file: cookie = file.read()headers = { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Connection': 'keep-alive', 'Host': 'cme3.', 'Content-Type': 'application/x-www-form-urlencoded', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}headers['Cookie'] = cookiesession.headers = headersdef post_exam(cwid): url = 'http://cme3./pages/exam.aspx?cwid='+cwid exam_content = session.get(url,proxies=proxies) print(exam_content.text) #选项name pattern4 = re.compile(r'<input id="gvQuestion_rb.*?type="radio" name="(gvQuest.*?)".*?</label>') match4 = re.findall(pattern4, exam_content.text) match4_temp=[] for item in match4: # 去重 if not item in match4_temp: match4_temp.append(item) match4 = match4_temp # 隐藏答案 pattern5 = re.compile(r'<input type="hidden" name="(gvQuestion.*?)" id="gvQuestion.*?value="(.*?)" />') match5 = re.findall(pattern5, exam_content.text)
pattern6 = re.compile(r'id="__VIEWSTATE" value=".*?/>') match6 = re.findall(pattern6, exam_content.text) pattern7 = re.compile(r'__EVENTVALIDATION" value=.*?/>') match7 = re.findall(pattern7, exam_content.text)
exam_result = { '__VIEWSTATE':match6[0].split('"')[3], '__VIEWSTATEGENERATOR':'265B8D93', '__EVENTVALIDATION':match7[0].split('"')[2], 'btn_submit.x':'0', # 系统用于检查用户有没有选择 'btn_submit.y': '20' } for ia in range(int(len(match5) / 2)): print(ia) exam_result[match4[ia]] = match5[ia*2][1] #rbl exam_result[match5[ia*2][0]] = match5[ia*2][1] exam_result[match5[ia*2+1][0]] = match5[ia*2+1][1] headers['Referer'] = url session.headers = headers # 提交考试 r = session.post(url, data=exam_result,proxies=proxies) # print(r.text) # 获取考试结果 result = session.get('http://cme3./pages/exam_result.aspx?cwid=' + cwid,proxies=proxies) print(result.text)
cwids =[] # 考试id列表for cwid in cwids: print(cwid) post_exam(cwid)
运行结果

如果全部考完,可以在网页中看到可以申请证书。

MORE

华医网很多bug的,如没有完成考试也可以直接申请证书,在考试结果页面,浏览器状态输入代码就可以。

javascript: window.location.href = 'apply_certificate.aspx?cid=73058c85-868c-484c-b95d-a82dccfd468d'




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多