icode青少年编程比赛网站学生刷题进度爬虫

需求分析本人是带学生参加icode编程比赛的python项目的老师,学生比较懒,所以每天网络教学的同时,更要督促学生每天刷训练场的编程题。尤其决赛训练阶段,我每天都要登陆比赛同学的账号,然后登陆进去,依次记录学生四个训练场刷题所得的星数在excle表格里:如下图

 

检查学生每天是否努力做题了,所以我的需求,自动循环读取excle的学生账号,切换登陆学生的账号,然后爬取学生四个训练场所得的星数并记录在excle里。下面是我手工操作每天记录的学生刷题情况。

如图:

实战解错:此网站post提交的密码采用md5加密,因为只是学生比赛网站,安全性要求不高,也没有验证码检验的烦琐程序。相对js解密定位加密相关代码还是比较容易的。因为本人水平有限,也不会分析具体是哪些函数涉及md5加密的,索性把整个md5加密js文件代码都复制出来并且经过发条js调试工具通过,能够得到加密之后的密码。

 但是怪就怪在这里,我在第一天直接把这个所有的md5加密的js文件里的密码,通过python ,pyexecjs类库执行还没问题,第二天准备加入excle读写功能,再次运行相关解密代码时,竟然 报错了,一开始报错,md5 is not defined的错误,后来各种折腾一直显示编码报错:

 百度了好久,把pycharm所有的编码设置项,所设为"utf-8",报错都存在,实在没办法就想把md5加密的js文件一些无关代码去掉一些,我虽然学过一些前端,但是水平也很低,无奈中的尝试,竟然解决了问题,把下面的代码去掉竟然 解决了问题:

 实战源码:

import requests
import execjs
import xlwings as xw
import math
import time
import datetime
#==================================
#==所有用到的变量==
#标志作业检查工作表,之前是否存在,存在不写入相关信息,不存在则创建写入相关信息,避免第二次打开的重复写入
作业检查=False
#定义查询几级训练场的参数
leval=["0","10","20","30"]
#间隔写入需要传入的间隔列数
intervalCols=4
#===================================
# 打开Excel程序,默认设置:程序可见,只打开不新建工作薄,屏幕更新打开
app=xw.App(visible=True,add_book=False)
app.display_alerts=False
app.screen_updating= True
#另一种打开工作簿的方法
#workBook= xw.Book('./icode账号.xlsx')
workBook=app.books.open('./icode账号.xlsx')
#得到打开工作的所有工作表
sheets = workBook.sheets
if "作业检查" in str(sheets):
    print("作业检查工作表存在")
    作业检查 = True
else:
    print("作业检查工作表不存在")
    sheets.add(name="作业检查", after="账号")
print("打开的工作簿的所有工作表:",sheets)
#打开第一张学生账号工作表
sheet1st = workBook.sheets[0]
print("第一张工作表名字:",sheet1st.name)
# 获取工作表的活动区域
rng = sheet1st.range('a1').expand('table')
# 获取活动区域的行数
nrows = rng.rows.count
print("学生账户工作表总行数:",nrows)
# 接着就可以按准确范围读取了
accounts=sheet1st.range(f'c1:c{nrows}').value
pwds = sheet1st.range(f'd1:d{nrows}').value
#print("读取学生账号试验:",str(math.floor(accounts[1])))
print("学生密码:",pwds)
#读取姓名
names=sheet1st.range(f'b1:b{nrows}').value
print("学生姓名:",names)
#-------------------------------------------------
#打开作业检查工作表
sheet2nd=workBook.sheets["作业检查"]
#作业检查工作表自动调整宽度
sheet2nd.autofit()
#之前作业检查工作不存在,证明是第一次打开,则写入基本信息
if 作业检查==False:
    sheet2nd.range('A1').value="姓名"
    sheet2nd.range('A2').value="日期"
# 获取第2张工作表的活动区域
rng2nd = sheet2nd.range('a1').expand('table')
# 获取第2张工作表的活动区域的行数
nrows2ndUsed = rng2nd.rows.count
print("作业检查工作表总行数:",nrows2ndUsed )
#获取并写入时间
nowTime = datetime.datetime.now()
sheet2nd.range(nrows2ndUsed+1,1).value=nowTime
#--------------------------------------------------------------------------------
#1实例化一个node对象
node = execjs.get()
#2js源文件编译
ctx = node.compile(open("./icode.js", encoding="utf-8").read())
#----------------------------------------------------------------------------------------------
#创建一个session对象
session = requests.session()
signInUrl = "https://service.icode.org.cn/user/userLogin"
signInUrlHeaders = {
    "User-Agent":  "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0",
    "Origin": "https://home.icode.org.cn",
    "Referer": "https://home.icode.org.cn/signIn"
}
GameListUrl="https://service.icode.org.cn/user/getGameList"
GameListUrlHeaders = {
    "User-Agent":  "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)  /80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0",
    "Origin": "https://home.icode.org.cn",
    "Referer": "https://home.icode.org.cn/index"
}
#===================================================================================================

for i in range(nrows-1):
    # 之前作业检查工作不存在,证明是第一次打开,则写入基本信息
    if 作业检查 == False:
        #每隔4列写入数据
        sheet2nd.range(1,2+intervalCols*i).value=names[1+i]
        #合并姓名单元格
        # sheet2nd.range((1, 2 + intervalCols * i), (1, 2 + intervalCols * i + 3)).api.merge()
        #写入四个训练场文字
        sheet2nd.range(2, 2 + 4 * i).value = ["1级训练场","2级训练场","3级训练场","4级训练场"]
    #--------------------------------------------------------
    # 3.执行js函数
    funcName = 'getPwd("{0}")'.format(pwds[i+1])
    pwdEncrypted = ctx.eval(funcName)
    signInData = {
        #读出的账号数据是类似"13813396052.0"这样的数据所以必须作下处理,取出整数,并转换成字符串
        "email": str(math.floor(accounts[i+1])),
        "password": pwdEncrypted
    }
    text = session.post(url=signInUrl, headers=signInUrlHeaders, data=signInData).text
    print("登陆请求返回的信息:",text)
    for j in range(4):
        GameListData = {
            "mode": "1",
            # 0是1级训练场,10是2级训练场;20是3级训练场;30是4级训练场
            "level": leval[j]
        }
        GameListJson = session.post(url=GameListUrl, headers=GameListUrlHeaders, data=GameListData).json()
        # print(str(GameListJson["data"]["star"])+"/"+str(GameListJson["data"]["totalStar"]))
        # print('"{0}/{1}"'.format(str(GameListJson["data"]["star"]),str(GameListJson["data"]["totalStar"])))
        sheet2nd.range(nrows2ndUsed+1, 2+intervalCols*i + j).value ="{0}/{1}".format(GameListJson["data"]["star"],GameListJson["data"]["totalStar"])
        # print(”所得星数:“,GameListJson["data"]["star"])
        # print(”总星数:“,GameListJson["data"]["totalStar"])
    #---------------------------------------------------------------------------
    #--取消息上次最后一行数据的下边框--
    sheet2nd.range((1, 1), (nrows2ndUsed, 1)).api.Borders(9).LineStyle = 0
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed, 2 + intervalCols * i + 3)).api.Borders(9).LineStyle = 0
    #--------------------------------------------------------------------------------------------------------------------
    #--第一列边框处理--
    sheet2nd.range((1, 1), (nrows2ndUsed+1, 1)).api.Borders(7).LineStyle = 1
    sheet2nd.range((1, 1), (nrows2ndUsed+1, 1)).api.Borders(7).Weight = 3
    sheet2nd.range((1, 1), (nrows2ndUsed + 1, 1)).api.Borders(8).LineStyle = 1
    sheet2nd.range((1, 1), (nrows2ndUsed + 1, 1)).api.Borders(8).Weight = 3
    sheet2nd.range((1, 1), (nrows2ndUsed + 1, 1)).api.Borders(9).LineStyle = 1
    sheet2nd.range((1, 1), (nrows2ndUsed + 1, 1)).api.Borders(9).Weight = 3

    #------------------------------------------------------------------------------------------------------------------------------------
    #--对一个人的四列数据加上边框便于好看--
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(7).LineStyle = 1
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(7).Weight = 3
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(8).LineStyle = 1
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(8).Weight = 3
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(9).LineStyle = 1
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(9).Weight = 3
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(10).LineStyle = 1
    sheet2nd.range((1, 2 + intervalCols * i), (nrows2ndUsed+1, 2 + intervalCols * i + 3)).api.Borders(10).Weight = 3
    time.sleep(1)
#==================================================================================================
# 所有列宽度自适应
# sheet2nd.range('a1').expand('table').columns.autofit()
# 所有列宽水平居中 -4108 水平居中。 -4131 靠左,-4152 靠右。
sheet2nd.range('a1').expand('table').api.HorizontalAlignment = -4108
# 保存工作簿,若未指定路径,保存在当前工作目录。
workBook.save()

实现效果:

自动读取学生账号工作表的姓名,账户和密码,模拟登陆,获取学生账户的闯关成绩,接着创建一个作业检查的工作表,然后把学生每天完成四个训练场的编程关卡所得的星数采集到excle里,便于每天检查学生的每天努力情况

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值