问卷代填脚本

呃。好久不见。原因是我这里到conoha的网络炸了。前一阵子是直接就无连接,最近才有一些很慢很慢的连接。当然。也有部分原因是因为我配了台新机器,沉迷 GTA 和 starbound 所以一直没有更新。

废话不多说,讲正题。

首先呢,这两天学校让我们填一份问卷。大概又是学校抽风搞的活动,需要有人来填问卷完成指标。我们当时认为不就是几道题么。然后我们发现一共有接近 20 张问卷。每张都有七八十题。更气的是每份试卷还有 10 分钟的等待时间。在手艹控制台提交了两份之后实在忍不了了。干脆写个脚本吧!

python 版本: python3

用到的包: requests, BeautifulSoup4

 

由于这次的试卷是需要学号登录的,我们得先利用 requests 包的 session 来建立一个会话。随便抓了一下包发现这次学号密码都是明文 post 的,这就很简单了,新建一个 session 直接发一个 post 就好了。

s = requests.Session();
userinfo = {
    "username":"xxxxxxxxx",
    "password":"******"
    }
r = s.post("http://ibook.cslg.cn/Home/Login",params=userinfo)

由于 session 是会自动保存 cookies 的,服务器是通过 cookies 来保存用户的登陆情况的,这样我们的脚本就已经在服务器上正式登陆了。

 

接下来我们需要查看试卷提交的时候发了哪些包,懒得看代码了就出去串串门等 10 分 钟。

10 分钟之后我们提交了问卷,发现了提交的答案分成了两部分。0opco10s_xp42t8iwa

由于提交文本很乱,我们只能再去翻源码。

第一段是xxxxx=xxxxxx的格式。

搜索第一段的 44900 ,我们在题目描述里找到了这一段文本,再看这题的选项,我们在选项中找到了 167227 ,那么前面的一段就很好懂了,就是题号 = 答案号的格式。

后一段经过解析,我们发现其是一个 json 格式字符串的序列化,简单查看是类似于[{“name”:”xxxxx”,”value”:”xxxxxx”}]的格式。

辣鸡学校数据发两遍表示很重要

所以现在我们需要做的就是使用beautifulsoup解析试卷界面,然后单选题找到所有A选项的对应答案号,多选题选上所有的答案号,判断题找到“错”选项的答案号。

你问我为什么不全选C?因为有的题目没有D和C选项啊,就炸了。辣鸡学校(

由于我们最后还得在最后补上一个序列化 json 字符串,所以我们得开一个 list 保存一下数据。

questionid = {"courseId":"31"}
r = s.get("http://ibook.cslg.cn/Exam/Index",data=questionid)

soup = BeautifulSoup(r.text,"html.parser")

anslist = list()
opt = ""

for ans in soup.find_all("input"):
    if(ans.get_text()=="A" and ans.get("type")=="radio"):
        anslist.append(ans.get("name"))
        anslist.append(ans.get("value"))
        opt += ans.get("name") + "=" + ans.get("value") + "&"
        
for ans in soup.find_all("input"):
    if(ans.get("type")=="checkbox"):
        anslist.append(ans.get("name"))
        anslist.append(ans.get("value"))
        opt += ans.get("name") + "=" + ans.get("value") + "&"
        
for ans in soup.find_all("input"):
    if(ans.get_text()=="错" and ans.get("type")=="radio"):
        anslist.append(ans.get("name"))
        anslist.append(ans.get("value"))
        opt += ans.get("name") + "=" + ans.get("value") + "&"

接下来手动生成序列化字符串。

paperid = ""
for tid in soup.find_all("input"):
    if(tid.get("name")=="paperId" and tid.get("id")=="paperId"):
        paperid = tid.get("value")

opt += "paperId=" + paperid + "&answer=%5B"

for i in range(len(anslist)//2-1):
    opt += "7B%22name%22%3A%22" + anslist[i*2] + "%22%2C%22value%22%3A%22" + anslist[i*2+1] + "%22%7D%2C"

opt += "7B%22name%22%3A%22" + anslist[-2] + "%22%2C%22value%22%3A%22" + anslist[-1] + "%22%7D%5D"

好了,接下来我们交卷试试

fahead = {
        "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"
        }
r = s.post("http://ibook.cslg.cn/exam/submit",data = opt,headers = fahead)
print(r.text)

ok 返回了 true 说明我们交卷成功了,我们填完了一张问卷。

接下来我们需要查看我们有哪些问卷需要做。我们使用beautifulsoup对问卷列表页面进行了拆解。

testlist = []

r = s.get("http://ibook.cslg.cn/Home/Exam")

soupti = BeautifulSoup(r.text,"html.parser")

for link in soupti.find_all("a"):
    if(link.get_text()=="测试"):
        testlist.append(link.get("href")[link.get("href").find("=")+1:len(link.get("href"))])

这样我们就获取到了所有问卷的 id ,我们使用获取到的 id 替换掉我们上面的courseId。

这样,我们自动填问卷的脚本就完成了。

整个脚本如下:

import requests
from bs4 import BeautifulSoup

s = requests.Session();
userinfo = {
    "username":"xxxxxxxxx",
    "password":"******"
    }
r = s.post("http://ibook.cslg.cn/Home/Login",params=userinfo)

testlist = []

r = s.get("http://ibook.cslg.cn/Home/Exam")

soupti = BeautifulSoup(r.text,"html.parser")
for link in soupti.find_all("a"):
    if(link.get_text()=="测试"):
        testlist.append(link.get("href")[link.get("href").find("=")+1:len(link.get("href"))])

for qid in testlist:
    questionid = {"courseId":qid}
    r = s.get("http://ibook.cslg.cn/Exam/Index",data=questionid)
    
    soup = BeautifulSoup(r.text,"html.parser")

    anslist = list()
    opt = ""
    
    for ans in soup.find_all("input"):
        if(ans.get_text()=="A" and ans.get("type")=="radio"):
            anslist.append(ans.get("name"))
            anslist.append(ans.get("value"))
            opt += ans.get("name") + "=" + ans.get("value") + "&"
            
    for ans in soup.find_all("input"):
        if(ans.get("type")=="checkbox"):
            anslist.append(ans.get("name"))
            anslist.append(ans.get("value"))
            opt += ans.get("name") + "=" + ans.get("value") + "&"
            
    for ans in soup.find_all("input"):
        if(ans.get_text()=="错" and ans.get("type")=="radio"):
            anslist.append(ans.get("name"))
            anslist.append(ans.get("value"))
            opt += ans.get("name") + "=" + ans.get("value") + "&"
            
    paperid = ""
    for tid in soup.find_all("input"):
        if(tid.get("name")=="paperId" and tid.get("id")=="paperId"):
            paperid = tid.get("value")
    opt += "paperId=" + paperid + "&answer=%5B"


    for i in range(len(anslist)//2-1):
        opt += "7B%22name%22%3A%22" + anslist[i*2] + "%22%2C%22value%22%3A%22" + anslist[i*2+1] + "%22%7D%2C"
    opt += "7B%22name%22%3A%22" + anslist[-2] + "%22%2C%22value%22%3A%22" + anslist[-1] + "%22%7D%5D"

    fahead = {
        "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"
        }

    r = s.post("http://ibook.cslg.cn/exam/submit",data = opt,headers = fahead,timeout=5)

    print(str(qid)+":"+r.text)

虽然感觉自己也没写啥。。但是做了个东西不拿出来写写总感觉白做了。。就拿出来水一发好了。

发表评论

电子邮件地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据