目录
前言
由于在学信息学奥赛,所以找了个题库
信息学奥赛一本通(C++版)在线评测系统http://ybt.ssoier.cn:8088/
前面的题不难基本上半分钟一题,但是题库提交限制40s/次,所以每次提示提交频繁就很无语,就在想能不能用网页自动化测试来自动提交,找了一下资料发现可以做到,那么下面我们就开始吧
正文
准备
- pycharm环境(也可以使用其他的环境,但是为了方便后文将使用此环境)
- python的环境
- edge的浏览器驱动(也可以使用其他的浏览器只需要更换驱动和部分代码即可)
- selenium
- 对应题目的答案
安装pycharm、python环境
这里引用一下菜鸟编程的文章
pycharm、python环境安装——菜鸟编程https://www.runoob.com/w3cnote/pycharm-windows-install.html
准备edge浏览器驱动
通过官网下载对应版本的浏览器驱动
edge浏览器驱动——Microsofthttps://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
下载好后得到的是一个.zip文件
这时候先打开安装好的pycharm,首先点击底部菜单栏的python console,等待它加载一会,将顶部的第一条路经复制下来(不用复制最后的python.exe,图中圈多了)如下图所示
在资源管理器中打开复制的路径,将浏览器驱动解压至此路径
准备selenium环境
首先要在pycharm中新建一个项目,在pycharm上方的菜单栏中打开file菜单点击第一条new project
在项目详情页面如下图所示,点击右下角的create完成创建
在pycharm的底部菜单栏中点击python packages菜单,在左上角的搜索框中输入selenium回车搜索,在搜索结果中选择pypl下拉选项卡中的selenium,在加载出的详情中右上角的install安装并配置selenium到此项目中
对应题目的答案
为了后文的统一,我们统一在C盘根目录下创建ybt.ssoier.cn8088_answer文件夹,如下所示
然后将下面的压缩包解压在此目录下(压缩包已经准备了1000-2086的文件,答案需要大家自行复制,所有答案)
百度网盘链接:百度网盘
提取码:自动填充
准备结束
至此,我们的准备工作就算是完成了,接下来我们就要开始写代码了。
代码分析
在这里我先将代码放上来,大家可以猜一下每一行代码是干什么用的
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
number = 1000
driver = webdriver.Edge()
driver.get("http://ybt.ssoier.cn:8088/")
input("")
while number != 2086: #!=2086
with open("C:\ybt.ssoier.cn8088_answer\\answer_" +str(number) + ".txt", encoding='utf-8') as text:
answer = text.read()
try:
driver.get("http://ybt.ssoier.cn:8088/submit.php?pid=" + str(number))
elem_radio = driver.find_element(by=By.NAME, value="source")
elem_radio.send_keys(answer)
elem_radio = driver.find_elements(by=By.NAME, value="submit")
elem_radio[0].click()
print(str(number)+" OK")
number = number + 1
time.sleep(40)
except:
print(str(number)+" null")
number=number+1
第一段
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
第一段,导入需要的库time(延时提交需要使用)、selenium(自动化测试的库)。这里的selenium库并没有使用全部,只用到了webdriver和By。
第二段
number = 1000
driver = webdriver.Edge()
driver.get("http://ybt.ssoier.cn:8088/")
input("")
第二段,首先初始化一下题目序号(题库的题是从1000开始的),其次实例一个实例driver,实例指向webdriver类里的Edge函数(可以根据自己的浏览器更改)有以下函数
"Firefox", "FirefoxProfile", "FirefoxOptions", "Chrome", "ChromeOptions", "Ie", "IeOptions", "Edge", "ChromiumEdge", "EdgeOptions", "Opera", "Safari", "WebKitGTK", "WebKitGTKOptions", "WPEWebKit", "WPEWebKitOptions", "Remote", "DesiredCapabilities", "ActionChains", "Proxy", "Keys",
然后访问题库,这里的input是用来暂停程序等待我们手动登录,完成之后 在控制台输入回车即可
第三段之前——分析网页
由于第三段涉及网页操作所以在操作前需要先分析网页,我们登陆好后看到的是如下界面
我们随意的点击一道题(这里以1000为例)进入以下界面
点击下方的提交按钮跳转至以下页面
注意观察图中圈住的部分
简单分析一下,首先前面的http://ybt.ssoier.cn:8088/ 指的是这个网站,重点是后半部分的submit.php?pid=1000通过翻译可以知道这个文件是提交题目的,需要传入一个get参数pid,稍稍联系一下我们选择的题目可知pid指题号,那么这样做的意义是什么?这样分析出链接上的规律,再通过链接来提交就会比在网页上点击元素要快而且更简单。所以我们第三段的代码要有访问提交界面的代码
如果我们要提交代码我们要先填写代码再点击下面的提交按钮,我们通过f12来查看这个两元素,如下图所示
提交按钮稍微用一点点的HTML知识知道,这是一个input元素的提交按钮,参数走的是post 方法,如果是这样那我们与其模拟一个psot请求还不如在页面上点击元素方便快捷,所以我们第三段的代码还要有点击提交按钮的代码。这里先将文本框和提交按钮的html代码复制出来方便元素定位
文本框
<textarea rows="30" name="source" cols="80" accesskey="c" onkeyup="if(this.value.length > 12768) this.value=this.value.substr(0,12768)"></textarea>
提交按钮
<input type="submit" value="提交" name="submit" accesskey="s">
点击提交后会跳转到如下界面
但这个页面对我们没有任何作用,甚至会影响我们的效率,所以这里我们不做任何处理,直接用过链接跳转到下一题,那既然第一步也是跳转这里用循环可以实现。
总结一下,第三段的代码与网页交互的代码要做到一下几步
- 通过链接访问题目的提交界面
- 填入代码
- 点击提交界面的提交按钮
- 循环1、2、3步
第三部分
分析完网页我们来看看如何实现,首先先放代码
while number != 2086: #!=2086
with open("C:\ybt.ssoier.cn8088_answer\\answer_" +str(number) + ".txt", encoding='utf-8') as text:
answer = text.read()
try:
driver.get("http://ybt.ssoier.cn:8088/submit.php?pid=" + str(number))
elem_radio = driver.find_element(by=By.NAME, value="source")
elem_radio.send_keys(answer)
elem_radio = driver.find_elements(by=By.NAME, value="submit")
elem_radio[0].click()
print(str(number)+" OK")
number = number + 1
time.sleep(40)
except:
print(str(number)+" null")
number=number+1
最外层的while循环控制提交次数,这里设为2086,因为最后一题的题号是2086。while循环层下是读取文件
with open("C:\ybt.ssoier.cn8088_answer\\answer_" +str(number) + ".txt", encoding='utf-8') as text:
answer = text.read()
try和except代码段中的代码才是重点
try:
driver.get("http://ybt.ssoier.cn:8088/submit.php?pid=" + str(number))
elem_radio = driver.find_element(by=By.NAME, value="source")
elem_radio.send_keys(answer)
elem_radio = driver.find_elements(by=By.NAME, value="submit")
elem_radio[0].click()
print(str(number)+" OK")
number = number + 1
time.sleep(40)
except:
print(str(number)+" null")
number=number+1
try中的代码是正常情况下的提交
首先driver.get去到相应的界面
driver.get("http://ybt.ssoier.cn:8088/submit.php?pid=" + str(number))
然后将elem_radio指向文本框这一网页元素
elem_radio = driver.find_element(by=By.NAME, value="source")
这里指向元素用的是元素的名称(在前面复制下来的代码中的name参数里)通过send_keys函数填入代码,这里要注意,不知道为什么提交的时候不能有txt中的tab,有的话就直接断了。
elem_radio.send_keys(answer)
然后再将elem_radio指向提交按钮这一网页元素,用的也是元素名称定位元素,这里就不过多赘述
elem_radio = driver.find_elements(by=By.NAME, value="submit")
通过click函数点击按钮,但是要注意,这里用的是列表elem_radio的第一个元素。
elem_radio[0].click()
然后打印一条日志到控制台,题号自增一,等待40s(题库提交时间限制)
print(str(number)+" OK")
number = number + 1
time.sleep(40)
except代码段中则是应对突发状况而准备的
except:
print(str(number)+" null")
number=number+1
内容很简单,打印一条日志到控制台,题号自增一(跳过报错的这题)
最后
将这一切都准备好后按下ctrl+shift+f10运行程序,在弹出的窗口中登陆好账号,在控制台敲下回车,程序就会自动提交啦