本文解释一下代码,如果有想要用机器刷题的(前提是能找的到答案),可以参考一下。

开发原因:作业又多又无聊自己不想做,干脆用机器刷题。

主要方法:主要用Python的selenium库实现刷题。

需要基础:Python你得会点吧 html你得会的吧 正则表达式你得会点吧

登录部分

导入以下包

from selenium import webdriver

#导入selenium的webdriver 如果这个看不懂的话请移步selenium教程

from fuzzywuzzy import fuzz

#计算相似度的工具,没听过也没关系,看到了自己查

import re

import random

定义一些变量

name='15000000'

#用户名

password='**********'

#密码

wrong=85

#准确率(百分比)

count=148

#总题数

wrong=count*(100-wrong)*0.01

#错题数

然后打开登录界面

dr=webdriver.Chrome()

#用chrome打开 Firefox同理

dr.get('http://passport2.chaoxing.com/login?fid=1400&refer=http://i.mooc.chaoxing.com/space/index.shtml')

自动输入用户名密码,手动输入验证码

dr.find_element_by_class_name("zl_input").send_keys(name)

dr.find_element_by_class_name("zl_input2").send_keys(password)

#上面是用class name定位的用户名密码位置(用F12找)

code=input('Verification code >>>')

dr.find_element_by_class_name("zc_input32").send_keys(code)

dr.find_element_by_class_name("zl_btn_right").click()

#手动输入验证码,并用相同方法填入,并点击登录

f7c3076c8f30?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

登录图

定位到作业部分

尝试点击《计算机网络基础》学测,(你会发现没用,待会解释为什么没用)

dr.find_element_by_xpath("/html/body/div/div[2]/div[2]/ul/li[2]/div[2]/h3/a").click()

#用xpath的方式定位超链接,并click。请自己补充一定的xpath知识。

下图是如何在chrome中找到元素xpath的方法(xpath 大概就是 一种唯一定位html元素的方式#我自己也不是很清楚)

f7c3076c8f30?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

用selenium定位元素是没有办法跨frame的,所以需要定位某元素时,dr必须在某frame中。所以需要找到对应的frame并层层切换过去。用F12找到课程所在frame的ID-->frame_content,然后

dr.switch_to_frame('frame_content')

#用这个方法切frame

dr.find_element_by_xpath("/html/body/div/div[2]/div[2]/ul/li[2]/div[2]/h3/a").click()

#再点击,会打开一个新标签页

打开新标签以后要把dr切换到新标签中

dr.switch_to_window(dr.window_handles[1])

#dr.window_handles是所有标签的句柄list

想办法点击进入题目页

hwxpath='/html/body/div[6]/div[1]/div[2]/div[3]/div/div[2]/h3/span[2]/a'

dr.find_element_by_xpath(hwxpath).click()

f7c3076c8f30?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

进去以后

f7c3076c8f30?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

处理题目

点进去以后发现 题目被三层frame嵌套所以要切进去:

dr.switch_to_frame(0)

dr.switch_to_frame(0)

dr.switch_to_frame(0)

#0就是切入当前frame下的第一个frame,虽然这样不是很规范,但是方便啊,无脑啊

好现在dr在题目的frame里了,现在要把所有的单选框放在一个列表里。我们用find_elements_by_tag_name方法(根据标签名寻找),因为所有的单选框都是。但是并不是所有的input标签都是单选框,看了看发现只有可见的input标签才是单选框。所以我们要做两件事,找到所有input,然后再在这里面挑出所有display的:

inputs=[]

for n in dr.find_elements_by_tag_name('input'):

if n.is_displayed():

inputs.append(n)

print(n,'ok')

上一步做完,所有的单选框都在inputs这个list里了,四个一组(ABCD)。然后用正则表达式从页面源码中提取出所有题目。

qs=re.findall('(\d*?)[\s\S]*?【单选题】([\s\S]*?)

',dr.page_source)

然后要找对应的答案,查了一下,发现,这个练习的所有题目来自一个题库,下载该题库,保存成answer.txt存在同一目录下。然后把问题和答案分别用正则表达式提取出来,一一对应。

f7c3076c8f30?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image.png

with open(file,'r',encoding='utf-8') as f:

ass=f.read()

asq=re.findall('\d+ . (.*?)\n',ass)

asa=re.findall('答案:(.)',ass)

接下来就是匹配页面上的问题和下载的答案集了。但是因为页面源码和某些原因,题目可能会比答案多个空格少个字符什么的,所以有的时候不能完全匹配,就需要用模糊匹配和全匹配结合的方法。思路:先全匹配(因为快),如果不行,就计算两个题目的相似度,取相似度最高的。

asls=[]

for i in qs:

if i[1] in asq:

asls.append(asa[asq.index(i[1])])

else:

rls=[fuzz.ratio(i,ii) for ii in asq]

op=asa[rls.index(max(rls))]

asls.append(op)

#asls 里的结果大概就是这个样子['A','C','B'............'B']

然后我们要把所有的ABCD点上啊,第一个的A对应inputs里的0,B对应1......第二个的A对应4所以有公式——(ABCD的ASCII码-65+列表下标乘4)

asls=[ord(i)-65+e*4 for e,i in enumerate(asls)]

#列表推倒,不会的话自己用for写

#asls 里的结果大概就是这个样子[0,6,12........]

最后把inputs里的相应下标的inputs标签点击一下

for i in asls:

inputs[i].click()

当然,不能做全对吧,那就随机瞎点几个答案吧(错误率根据开始定义的错误率)

for i in range(int(wrong)):

random.choice(inputs).click()

全部解释完,撒花

下面贴全部源码

from selenium import webdriver

from fuzzywuzzy import fuzz

import re

import random

name='15000232'

password='a1008611'

wrong=85

count=148

wrong=count*(100-wrong)*0.01

dr=webdriver.Chrome()

dr.get('http://passport2.chaoxing.com/login?fid=1400&refer=http://i.mooc.chaoxing.com/space/index.shtml')

#open website

dr.find_element_by_class_name("zl_input").send_keys(name)

dr.find_element_by_class_name("zl_input2").send_keys(password)

code=input('Verification code >>>')

dr.find_element_by_class_name("zc_input32").send_keys(code)

dr.find_element_by_class_name("zl_btn_right").click()

#login

dr.switch_to_frame('frame_content')

dr.find_element_by_xpath("/html/body/div/div[2]/div[2]/ul/li[2]/div[2]/h3/a").click()

dr.switch_to_window(dr.window_handles[1])

#switch to frame and click 'SQL SERVER'

hwxpath='/html/body/div[6]/div[1]/div[2]/div[3]/div/div[2]/h3/span[2]/a'

dr.find_element_by_xpath(hwxpath).click()

dr.switch_to_frame(0)

dr.switch_to_frame(0)

dr.switch_to_frame(0)

inputs=[]

for n in dr.find_elements_by_tag_name('input'):

if n.is_displayed():

inputs.append(n)

print(n,'ok')

qs=re.findall('(\d*?)[\s\S]*?【单选题】([\s\S]*?)',dr.page_source)

file='answers.txt'

with open(file,'r',encoding='utf-8') as f:

ass=f.read()

asq=re.findall('\d+ . (.*?)\n',ass)

asa=re.findall('答案:(.)',ass)

asls=[]

for i in qs:

if i[1] in asq:

asls.append(asa[asq.index(i[1])])

else:

rls=[fuzz.ratio(i,ii) for ii in asq]

op=asa[rls.index(max(rls))]

asls.append(op)

asls=[ord(i)-65+e*4 for e,i in enumerate(asls)]

for i in asls:

inputs[i].click()

for i in range(int(wrong)):

random.choice(inputs).click()

当然你们做的题和我的不一样,所以要自己改改,这个程序并不是很健全,因为我懒就这样。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐