目录

利用python写一个作业帮自动抢题脚本

大概在两个月前,我的好舍友决定参加作业帮的VIP问答,通过帮助平台回答VIP用户提出的问题,来赚取课外零花钱。 不过群主提供的抢题方法太慢了,而且占用了一大部分的计算机资源(使用自动点击器来抢题),为了帮助舍友,我便写了一个python的抢题脚本。

版本更新 2021.07.18 发布1.12.3 2021.07.30 发布1.12.4

分析抢题流程

我比较喜欢通过画图的方式来进行分析,以下是我画的草图。要完成抢题大致就需要模拟抢题按钮的功能。

https://cdn.bingbingzi.cn/blog/20210714161232.png
picture

根据这个图,我们将整个过程分为:抓包分析、模拟抢题。

抓包分析

由于我使用的是macOS系统,抓包工具使用的是Charles,在Windows下可以使用Fiddler来进行抓包。

需要抓的包

要让这个工具能够全自动化操作,我们需要抓到:

  • 登录包(用来获取用户Token,作为后续操作的参数)
  • 题池包(判断题池是否有题可抢)
  • 抢题包(进行抢题操作)

开始抓包

配置好系统代理后打开作业帮VIP问答微信小程序

登录包

首先来抓取登录包

https://cdn.bingbingzi.cn/blog/20210714162420.png
picture

一开始我猜测pwd这个参数是使用MD5加密的,后来发现是进行了二次MD5加密。使用python测试一下:

1
2
3
4
5
6
7
import hashlib

def md5(s):
    m = hashlib.md5(s.encode())
    return(m.hexdigest())

print(md5(md5('2')))

https://cdn.bingbingzi.cn/blog/20210714162935.png
picture

经过测试,确实是使用了二次MD5加密。

题池包

在问答小程序中进行刷新操作,抓取到题池请求包。其中参数taskFrom的值代表学生任务(1)和平台任务(2)。

https://cdn.bingbingzi.cn/blog/20210714164114.png
picture

返回包中,total代表着题池内可抢的题目数量。

抢题包

饼干抓了很久,终于抓到了这个包,但是没有截图。好在已经写好了模拟程序,就不细说了,跟前面的步骤基本一致。位于/commitui/question/getitem路径下。

模拟抢题

接下来我将会使用python的部分代码来进行模拟抢题。

登录模拟

按照以上分析出来的逻辑,首先需要进行登录模拟,以此来获取用户TOKEN值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
user_token = ''

def md5(s):
    m = hashlib.md5(s.encode())
    return(m.hexdigest())

def get_token():
    # 传入登录接口的参数
    login_datas = {
        'code':'**************************',
        'userName':user_name,
        'pwd':user_pwd,
        'fromChannel':'wechat',
        'token':'*********************************',
        'mpversion':'202012291627'
    }
    request = req.post(login_url,data=login_datas)
    re_temp = re.compile(r'en":"(.*?)"},"lo')
    global user_token
    user_token = re_temp.findall(request.text)[0]

这里的密码需要进行二次MD5加密login_url是第一步抓取到的登录地址。

题池模拟

接着是疯狂请求题池库,判断题池内可抢题目数量是否大于一。

1
2
3
4
5
6
task1_datas = {
        'taskFrom':'1',
        'token':user_token
    }
while(not do_flag):
    request = req.post(task1_url,data=task1_datas,timeout=200)

这一步可以将do_flag的默认值设置成False,待抢题成功后设置为True结束访问题池。

抢题模拟

最后一步就是将题池数据带入抢题中作为参数发送。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
do_datas={
        'businessId':'**********',
        'ts':'1615569262',
        'sign':'',
        'ticket':'',
        'randStr':'',
        'taskFrom':s,
        'token':user_token
    }
    request = req.post(do_task_url,data=do_datas)

这里的businessId就是抢题的任务值,可以使用一个随机数代替。至此,完成全部抢题操作。

下载

精力问题,将其开源:https://github.com/binganao/zuoyebang