S(神)T(通)E约课系统-抢课脚本实现

最近正在驾校学习,学生通过一个约课系统进行选课学习。每天只能抢课两次,因为只有周六周日有时间学习,所以每到星期四放课时的时候就要进行抢课,手慢了可能就会浪费一周的时间。基于此,我想通过Python实现一个抢课脚本,每到时间点就就行自动约课。

分析与实现

模拟登录
  1. 约车系统是在微信端公众号,所以首先要找到了约课系统的链接
    这一步很简单,直接打开公众号,然后选择复制链接就可以实现,最后他的链接如下:http://wechat.exc360.com/ukeywechat/student/index

  2. 接下来就是登录了,捕捉到的链接如下http://wechat.exc360.com/ukeywechat/student/login
    image.png
    使用chrome 的F12抓包请求:
    image.png
    我们可以看到最重要的有几个参数

请求头:
以下请求头经过测试是必须包含的
{
    “Content-Type”:“application/x-www-form-urlencoded; charset=UTF-8,(数据的格式,表示是表单的形式)
    "Referer:http":"//wechat.exc360.com/ukeywechat/student/login",(应该是来源网址,这个就是我之前没有弄所以一直登录失败)
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"(伪装浏览器)
    "X-Requested-With":"XMLHttpRequest"(这表示是ajax请求)
}

参数:
{
    "password":""
    "username":""
}

最后就是cookie信息了,这一步也是非常重要的:
{
    "JSESSIONID":"B9581181A83392FCE075CABE004062F2",
    "stjy-exc-user-type":"student"
}
可以从上图中看到请求头里面有很长的cookie,其实目前我们需要的就只有JSESSIONID和stjy-exec-user-type这两个cookie,而另一个token就是我们sign这一步所需要获取到的最重要的元素。但是因为我之前没有正常退出,所以重新登录的时候就直接获取到这个token。

如果成功响应,那么在响应头里面就会重新发送一个包含token的cookie信息,这个token就是我们后面所有操作的凭证了,所以一定要确保获取到了token值。

  1. 代码
    在这部分的代码实现上:
    1). 我遇到了一个难点,http请求中cookie的处理,通过查找资料,最终我选择cookielib这个python包来实现
    2). http请求我最终选择了urllib2,因为它的可定制性会让代码实现起来比较轻松。
    代码如下:
# 这一步骤是为了获取请求头里面的cookie信息
def login():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
        'Content-Type': 'application/json',
    }
    filename = "cookie.txt"

    # 声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
    tmp_cookie = cookielib.MozillaCookieJar(filename)
    # 利用urllib2库的HTTPCookieProcessor对象来创建cookie处理器
    # tmp_cookie = urllib2.MozillaCookieJar(cookie)
    handler = urllib2.HTTPCookieProcessor(tmp_cookie)
    opener = urllib2.build_opener(handler)

    # print(zip(headers.keys(), headers.values()))
    opener.addheaders = zip(headers.keys(), headers.values())
    urllib2.install_opener(opener)

    # 发送请求
    urllib2.urlopen(login_url)

# 正式发送登录请求
def sign():
    sign_url = "http://wechat.exc360.com/ukeywechat/student/sign"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'X-Requested-With': 'XMLHttpRequest',
        'Referer': 'http://wechat.exc360.com/ukeywechat/student/login'
    }
    filename = "cookie.txt"
    # 声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
    tmp_cookie = cookielib.MozillaCookieJar(filename)
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(tmp_cookie))

    # 这里需要填写用户名和密码 
    data = urlencode({"username": "", "password": ""})
    req = urllib2.Request(sign_url, data=data, headers=headers)
    response = opener.open(req)

    token = json.loads(response.read())['token']
选课

成功登录之后就比较简单了:

  1. 查询所有的课程,筛选自己需要的课程
    http://wechat.exc360.com//ukeywechat/student/bespoke/jplist
    访问这个URL可以查询到所有的相关课程
    image.png
    通过分析:
    1. token:在登录成功之后可以获取到
    2. 日期,时间:这是我们需要选择的课程的时间,是自定义的
    3. 请求头:除了Referer需要改一下其他部分可以是一样的。
    4. 响应:当成功返回之后我们会接收到一个html字符串文本,然后就可以根据自己的需要找到自己需要的课程。
    5. 这一步最重要的就是获取到pid也就是课程号。

课程的html文本如下:

        <li class="fl" name="bespoke" id="145797" hours="1" datestr="11月22日" date="08:00-09:00" km="2" prize="0" minute="60" coachname="顾春雷C1">
                <h2 class="ft12">科目二  08:00~09:00</h2>
                <ul class="img_box_all">
                    <li><img src="/ukeywechat/resource/student/images/pople_d.png" alt=""></li>
                </ul>
                <div style="margin-top: 6px;font-size: 10px;overflow: hidden;">
                       <i class="fl"></i><span class="fl">
                    (60分钟)</span>
                </div>           
        </li>

这部分的完整代码如下:

def chooseClass(token):
    no_student_list = []
    class_url = "http://wechat.exc360.com/ukeywechat/student/bespoke/jplist"
    filename = "cookie.txt"
    os.remove('john.txt')
    f_handle = open("john.txt", "a")

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'X-Requested-With': 'XMLHttpRequest',
        'Referer': index_url + token
    }

    # 声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
    tmp_cookie = cookielib.MozillaCookieJar(filename)
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(tmp_cookie))
    data = {
        "token": token,
        "date": "2017-11-26",
        "km": "",
        "startime": "2017-11-26%2006:00:00",
        "endtime": "2017-11-26%2021:00:00"
    }
    req = urllib2.Request(class_url, data=urlencode(data), headers=headers)
    response = opener.open(req)
    response_html = response.read()

    # 解析该文本,获取所选教练的所有空课程,解析出pid,
    # pid,日期,练车时间,教练
    bs = BeautifulSoup(response_html, "html5lib")
    # class_list = bs.findAll("li", {'name': 'bespoke', 'coachname': '教练名'})
    class_list = bs.findAll("li", {'name': 'bespoke', 'coachname': '教练名'})
    if len(class_list) == 0:
        log("课程还没有发布,请稍后再试!")
        exit()

    for class_info in class_list:
        tmp_class_info = {}
        class_type = class_info.findAll('h2')[0].contents[0]
        class_id = class_info.attrs['id']
        class_datestr = class_info.attrs['datestr'].decode('utf-8')
        class_date = class_info.attrs['date']
        class_coachname = class_info.attrs['coachname'].decode('utf-8')

        f_handle.write(class_id + "  " + class_datestr + "  " + class_coachname + "  " + class_date + class_type)

        # 查询该课程是否已经被选
        img_src = class_info.find('img')
        if img_src.attrs['src'] == "/ukeywechat/resource/student/images/pople_d.png":
 f_handle.write("  " + "no student" + "\n")
            tmp_class_info['id'] = class_id
            tmp_class_info['datetime'] = class_type
            no_student_list.append(tmp_class_info)
        else:
            f_handle.write("  " + "has student" + "\n")

    print(no_student_list)
    return [no_student_list[2], no_student_list[3]]
  1. 确认选课
    直接访问下面这个url就可以了
    url:http://wechat.exc360.com/ukeywechat/student/bespoke/ok
{
    "token":""
    "pid":""
    "spick_up":0 //(是否接送,默认是0)
}
Tips:
这里可能有很多响应码,目前我只遇到过406表示当天选课已经超过,后期遇到了其他的可以添加进去,反正200表示选课成功应该是没有问题的

代码如下:

def finalClass(token, id_list):
    confirm_url = "http://wechat.exc360.com/ukeywechat/student/bespoke/ok"
    filename = "cookie.txt"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'X-Requested-With': 'XMLHttpRequest',
        'Referer': index_url + token
    }
    # 声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
    tmp_cookie = cookielib.MozillaCookieJar(filename)
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(tmp_cookie))

    for pinfo in id_list:
        data = {
            "token": token,
            "pid": pinfo['id'],
            "spick_up": 0
        }
        req = urllib2.Request(confirm_url, data=urlencode(data), headers=headers)
        response = opener.open(req)
        response_html = response.read()

        status = json.loads(response_html)['status']
        if status == '406':
            log("当前的预约次数已经超过了本日限制")
            exit()
        else:
            log("课程" + pinfo['datetime'] + "选择成功!")

完整代码可以访问:yoooknight.github

总结:这是我第一次将所学习的知识用于实际的生活中,前前后后写了半个月左右,刚开始在cookie那里卡住,停止了一段时间,后面想了想不应该半途而废,就又重新开始。从哪里跌倒就从哪里爬起。
最后虽然这个脚本不是很完美,但完成了自己的需求,还是很有成就感的。
所以很多事情一定多思考,多学习,不要害怕困难,坚持下去一定会迈向成功的。

ps:
该文章同步发布在简书:https://www.jianshu.com/p/863753481d11

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yooKnight

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值