杭电选课脚本(二)

上一篇实现了伪登陆选课系统,获取了cookie中的sessionID,这篇主要就是选课操作,大致过程就是不断地抓包,分析请求参数,请求参数可以在页面上抓取,比如很多form中的input都是隐藏的,都是可以抓取到,具体很多请求参数的抓取不想赘述。

大致过程

  • 通过跨专业选课根据学号来查询课程
  • 获取课程的详细开班信息
  • 验证码的识别
  • 伪造参数选课!!

细节

这里不想说很多繁琐的过程,只说几点

  • 默认选课的是一个课程号当中众多开班数的第一个(可以根据程序定制更改)
  • 验证码的识别我是购买的阿里云市场上的API,目前还有40次左右的使用剩余,其实也很便宜60次访问只要9毛钱
  • 需要在程序中填写一些信息参数,比如学号,密码,班级号,年级,行政班,要选的课程代码
  • 如果可以选多门课程,可以使用多线程

我的一个选课请求返回结果(部分):

<script language='javascript'>alert('现在不是选课时间!!');</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML lang="gb2312">
    <HEAD>
        <title>现代教学管理信息系统</title>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
        <meta http-equiv="Content-Language" content="gb2312">
        <meta content="all" name="robots">
        <meta name="author" content="作者信息">
        <meta name="Copyright" content="版权信息">
        <meta name="description" content="站点介绍">
        <meta name="keywords" content="站点关键词">
        <link rel="icon" href="style/base/favicon.ico" type="image/x-icon">
            <link rel="stylesheet" href="style/base/jw.css" type="text/css" media="all" />
            <link rel="stylesheet" href="style/standard/jw.css" type="text/css" media="all">
                <SCRIPT language="javascript">

            function jcgl(ydjc){
                if (ydjc.length==1) {
                    document.xsxjs_form.RadioButtonList1(1).checked=true;
                    document.xsxjs_form.RadioButtonList1(1).readonly=true;
                }
            }


          function ChangeCor(){
                    var i;
                    var obj1=document.getElementById("xjs_table");
                    var rl;            
                    var rs; 
                    var bz=
                    var sfxs=0
                    //alert(bz);
                    if (bz=="1")
                    {       
                        for(i=1;i<obj1.rows.length;i++)
                        { 
                        rl=Trim(obj1.rows[i].getElementsByTagName("td")[9].innerText);
                        rs=Trim(obj1.rows[i].getElementsByTagName("td")[11].innerText);

                        //alert(rl+'-'+rs);

因为现在不是选课时间,第一行的结果表明我所有参数和验证码是正确的,只是不在选课时间内

具体程序代码:

github : https://github.com/DrawBlack/hdu/

运行环境:Python3.5 macOS 10.12

import base64
from io import BytesIO
import hashlib
from PIL import Image
from lxml import etree
import requests
import json

host = 'http://jisuyzmsb.market.alicloudapi.com'
path = '/captcha/recognize'
method = 'POST'
querys = 'type=n5'
bodys = {}
url = host + path + '?' + querys

example_base64 = 'iVBORw0KGgoAAAANSUhEUgAAADwAAAAWCAIAAAATqWh1AAAABnRSTlMAZgAAAAB41IV8AAAEaElEQVR4nNWXQZrrKAyE//TXp4HZVV+FHIEco/2OYY4QruJa4utkFmB3OnHyvVkOC+JgIaRCKsmn5boQofE/mk9LWxTE0yhrUZOj91npQOxw9L27fKlFUW5+Mx/acDhczXydb0djuS6PK22Zr/OrucvMbX7e+F/HK5N2M34hvUOSU/bq994/CHg1DYBIB49GvyIivySr31za+7fdyNNyXZ6FugX7kTQOFbl6j7Pu6hsP96B0tNChzrKWHF4q2VV9Eg/8U9PpbBCQJ3JyqagfubpMMhaQlBmg5pRdy+U8NDPl5ftOYRAB1nLpapty2qBZiycPsetC+EH0GIXGh5sBJbmOnayczhYCBGWiVClCsyuXaayDqC5VNBMp526xASEmf539cFyZ7O5Ss2tREBRPw2DA56+y4mqvr+8t8qE48FBSWQtQzgZ05XZTTv0QuZkoV4Q1sdzyfLUR1U6ZhiuApjw35Qmwqi/VrvZaSrXrxRV1t4AosP/0a5nn25wnAE9F6R2ZuPljZE9PrCZXlwZIsXtCBk8mioqxkQJlNWjGIFYUhylK0CAhZBAmopBzwufuPwI2jnMzKH/L1YQsoPrxgn4PRX0QKbW4WkFKUhRIWGFIeA+GxHLLt5tykpqBS1fTimG+am5ST6+Ke5ykrCBXu7oAk/IWCQDr0L1l1GbuuuFYj+xvfPYcuoffXdFqNxQRFCBApWeJq4kqsefitr0nUABcJoScRFeSuJysqDnpMtk4Dz0d+tw5QCmLy25mWV8kYuSTiKsdURsxsDukaNqGSrUx6+AsR4zAeeo+2E1dvpyLN9rpOXr5xyC+NZJ+hzB4wDQIcRjs5ico70Bt/qBZSTnI/Ip9JY27Y2SPotwg2rELW1ep2RFapxfKeVzUfMs5SClToeFJmcGqQ1VE9CM0InM/O4no49gARX0S1aHqHEdA2BsYXZEhAzinfPmnx6vmW+6xri02NkZjezWgMdJULj0vQXCJX/m6ED24ZIUAof+RqpUygbI6P9NI48OjnqkTjZLmJKCgnDQwTr2yqJyLG6Dc9KDMf0qpAHPLrOUHp8bOcvuTkGsh5JwEna+gb0k/lTIHuZZHo4+7vOrTWdpyWaAJJWfyV/RA7s4OXTVHLnGnqp+Amm+Z6r33cC2jCNzm3HO9/pTDoa0tOdwv9JTzXt5LLR+0p9BJul35sbhp/lYOuWxOby72XynKdSt1vRz2dVyqjyvFiqtpKOU85V2bro8WA0rKIe9Xp6iX/TTPfdwdZu/HfSNFwxGNIBwNDBEYhKOQO3v8Zb/uelcRn9892hfxa2Gv3uZCb1QiP9QUvXEo4znknKSQ6e1UfFFKnserL5fDpta1MLrke+RMk5J6L95VldX6BbP1RLpb94saZrRHfwO5q0/zdX6gcdfi2AlY6rkfj9vfPkq1IgraNv7tRe/WK+i+g3//defVp6Ut9/3+r7DrpaRJdx8jRLPp7WHwAD/D27He5Z+C20LjFRs6d5IHnz9sLuF/AYr1AhGdzQ8qAAAAAElFTkSuQmCC'
example_appcode = '45fbfd16abe04372ac45479aed31b5cb'

# 学号
username = ''
# 密码
password = ''
# 年级
nj = ''
#行政班
hidXZB = ''


def getCode(pic, appcode):
    bodys['pic'] = pic
    headers = {'Authorization': 'APPCODE ' + appcode,
               'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
    r = requests.post(url, bodys, headers=headers)
    data = json.loads(r.text)
    return data['result']['code']


def md5(str):
    m = hashlib.md5(str.encode("utf-8"))
    return m.hexdigest()


# 获取请求参数中的lt
def getLT():
    lt_url = 'http://cas.hdu.edu.cn/cas/login?service=http%3A%2F%2Fi.hdu.edu.cn%2Fdcp%2Findex.jsp'
    r = requests.get(lt_url)
    html_text = r.text
    html_tree = etree.HTML(html_text)
    print('LT')
    return html_tree.xpath('//*[@id="login_form"]/div/div[1]/input[2]')[0].get('value')


def getValueByXpath(html_text, xpath, ele_type):
    html_tree = etree.HTML(html_text)
    return html_tree.xpath(xpath)[0].get(ele_type)


def getAllByXpath(html_text, xpath):
    html_tree = etree.HTML(html_text)
    return html_tree.xpath(xpath)


def getCookie():
    url = 'http://cas.hdu.edu.cn/cas/login'
    payload = {'encodedService': 'http://i.hdu.edu.cn/dcp/index.jsp', 'service': 'http://jxgl.hdu.edu.cn/default.aspx',
               'serviceName': '', 'loginErrCnt': '0', 'username': username, 'password': md5(password), 'lt': getLT()}

    # 获取登陆ticket
    r = requests.post(url, data=payload)
    ticket_xpath = '/html/body/noscript/p/a'
    url_ticket = getValueByXpath(r.text, ticket_xpath, 'href')

    # 获取选课页面的cookie,后面的选课请求都会在header中设置cookie,没有cookie将无法登陆选课页面和选课操作
    next = requests.get(url_ticket)
    cookie = str(next.headers.get('Set-Cookie'))
    print(cookie)
    return cookie


def getParams(headers, xh, nj):
    select_class_by_kzy = 'http://jxgl.hdu.edu.cn/zylb.aspx?xh=' + username + '&nj=' + nj
    mianban = requests.get(select_class_by_kzy, headers=headers)

    view_state_xpath = '//*[@id="__VIEWSTATE"]'
    event_validation_xpath = '//*[@id="__EVENTVALIDATION"]'

    view_state = getValueByXpath(mianban.text, view_state_xpath, 'value')
    view_validation = getValueByXpath(mianban.text, event_validation_xpath, 'value')
    query_class_by_num_payload = {
        '__EVENTTARGET': '',
        '__EVENTARGUMENT': '',
        '_LASTFOCUS': '',
        '__VIEWSTATE': view_state,
        '__EVENTVALIDATION': view_validation,
        'cx': 'cx',
        'DropDownList2': '01',
        'TextBox1': xh,
        'RadioButtonList1': '3',
        'Button3': '%C8%B7%B6%A8',
        'DropDownList1': nj
    }
    print(query_class_by_num_payload)
    return query_class_by_num_payload


def select_class(xh):
    headers = {'Cookie': getCookie()}
    query_class_by_num_payload = getParams(headers, xh, nj)
    select_class_by_kzy = 'http://jxgl.hdu.edu.cn/zylb.aspx?xh=' + username + '&nj=' + nj
    class_info = requests.post(select_class_by_kzy, data=query_class_by_num_payload, headers=headers)
    class_with_teachers_urltext = getValueByXpath(class_info.text, '//a', 'onclick')

    strs = str(class_with_teachers_urltext).split(',')
    print(strs[0])
    start = int(strs[0].find('(') + 2)
    end = int(strs[0].find(')'))
    class_with_teachers_url = strs[0][start:end]

    class_with_teachers_detail = requests.get('http://jxgl.hdu.edu.cn/' + class_with_teachers_url,
                                              headers=headers)

    # 识别验证码
    yz_code_img_url = 'http://jxgl.hdu.edu.cn/CheckCode.aspx'
    img_response = requests.get(yz_code_img_url, headers=headers)
    img = Image.open(BytesIO(img_response.content))
    # 转换成RGB模式
    img = img.convert('RGB')
    img.save('out.jpg')

    f = open('out.jpg', 'rb')  # 二进制方式打开图文件
    img_base64 = str(base64.b64encode(f.read()))  # 读取文件内容,转换为base64编码
    f.close()
    img_base64 = img_base64[2:-1]
    img_code = getCode(img_base64, example_appcode)  # 识别出来的验证码
    print(img_code)

    # 获取选课课号(默认第一个)
    inputs = getAllByXpath(class_with_teachers_detail.text, '//input')
    xkkh = inputs[0].get('value')
    hidZYDM = inputs[8].get('value')

    select_class_params = {'__EVENTTARGET': 'Button1',
                           '__EVENTARGUMENT': '',
                           '__VIEWSTATE': '/wEPDwULLTEzMDk5NDU3NTEPFgweAnhtBQbmsarmnbAeAnh5BQ'
                                          '/orqHnrpfmnLrlrabpmaIeBHp5bWMFDOi9r'
                                          '+S7tuW3peeoix4FZHFzemoFBDIwMTUeA3h6YgUIMTUwNTI3MTIeBHp5ZG0FBDA1MjcWAmYPZBYCAgMPEGRkFgBkZA==',
                           '__EVENTVALIDATION': '/wEWDQKXyNPgBQKS+9acCwL444i9AQLn44i9AQL3jKLTDQLax9vVBgKM54rGBgKF2fXbAwLWlM+bAgK7q7GGCALejczkBgKgpuLGBALujYy8Bg==',

                           'xkkh': xkkh, 'txtYz': img_code,
                           'RadioButtonList1': '0',
                           'hidNJ': nj, 'hidZYDM': hidZYDM, 'hidXZB': hidXZB}

    select_result = requests.post(
        'http://jxgl.hdu.edu.cn/' + class_with_teachers_url,
        data=select_class_params, headers=headers)

    print(select_result.text)


# 要选的课程代码
xh = 'B0502670'
select_class(xh)
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值