Python 模拟登陆教务选课系统

原创 2015年07月10日 21:40:15

前言

本来,可爱的教务选课系统从出生就没有验证码的,但快到选课的时候,突然有验证码了,只好重写一次登陆模块。这次在win8.1系统下写,打造IDE和其他各种库的安装弄了好久,实际抓包写代码的时间不长。


编程环境 及 其他准备

python 2.7
sublime text 3 & JEDI
PIL
chrome
wireshark
(安装和配置请自行搜索)

开始抓包

chrome打开选课系统页面:
登陆页面

分析抓到的包:
登陆页面的包

获取关键点:
GET方法,但是没有带参数。需要cookie。

验证码怎么办呢?看看源代码里有没有图片地址,如果有。直接下载下来就简单了。
页面代码
然而并没有直接的地址,似乎是动态生成的。
看到点击会调用changePic(this)函数,肯定就会发包来获取新的图片,那么我们把它抓下来看看。

点击验证码更换验证码,抓包:
验证码的包
获取地址:
验证码地址
获取关键点:
GET方法,有一个参数v。需要cookie,并且与打开主页的是相同的。

至此可以写出获取验证码图片的代码:

#-*- coding:utf-8 -*-

import urllib,urllib2
import cookielib

class Login(object):
    #构造函数
    def __init__(self):
        super(Login, self).__init__()
        print r"初始化中..."
        #jid即是cookie
        self.jid = ''
    #获取cookie
    def getCookie(self):
        #创建CookieJar对象,自动管理cookie,可迭代
        ck = cookielib.CookieJar()
        #创建类内部对象opener,把CookieJar塞进去,每次打开页面都会自动使用cookie
        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(ck))
        try:
            #打开登陆页面,获取cookie
            self.opener.open('http://XXX.Mosaic.XXX.XXX/elect')
        except urllib2.URLError,e:
            print "Error code:", e.code
            print "Return content", e.read()
            return None
        for item in ck:
            #将cookie存到类内部变量jid中。
            self.jid = item.name+'='+item.value
            return self.jid
        return None
    #获取验证码
    def getCAPTCHA(self, cookie):
        #输出cookie检查
        print self.jid
        #按照包内格式,写好头部,是一个字典类型对象。
        header = {
            'Accept':'image/webp,*/*;q=0.8',\
            'Accept-Encoding':'gzip, deflate, sdch',\
            'Accept-Language':'zh-CN,zh;q=0.8',\
            'Connection':'keep-alive',
            #cookie的值使用self.jid
            'Cookie':self.jid,\
            'Host':'XXX.Mosaic.XXX.XXX',\
            'Referer':'http://XXX.Mosaic.XXX.XXX/elect/',\
            'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36'}
        #随机数既然是随机的,服务器也应该不知道是什么,所以这里随便给一个。
        #并且,随机数的值并没有和图片绑定,可以说是然并卵。
        #编码参数`v`
        params = urllib.urlencode({'v':'0.1932646029163152'})
        #构造`GET`的地址,格式为:`服务器地址`+`?`+`编码后的参数`
        capurl = ('http://XXX.Mosaic.XXX.XXX/elect/login/code?%s' % params)
        #用opener打开页面,加上头部
        response = self.opener.open(urllib2.Request(capurl,headers=header))
        #response就是图片内容,将它写入本地图片文件中
        f = file("code.jpg",'wb')
        f.write(response.read())
        f.close()
        #关闭图片,之后可以在其他函数中用绝对路径打开图片。
        return 

验证码获取后,就可以用Image库打开,人眼识别后手动输入。

登陆

还是先抓包吧,用浏览器正常登陆后,抓包分析:
登陆的包
获取关键点:
POST方法,有6个POST DATA。账号密码都是明文传输。j_code就是验证码,也是明文。使用了cookie,并且需要和获取验证码图片时的cookie一样。
仿写包并发送,整体代码如下:

#获取sid,上面那块代码有小更改
#-*- coding:utf-8 -*-

import urllib,urllib2
import cookielib
import Image

class Login(object):
    """save sid and cookie"""
    def __init__(self):
        super(Login, self).__init__()
        print r"初始化中..."
        self.sid = ''
        self.jid = ''
    #获取cookie
    def getCookie(self):
        #创建CookieJar对象,自动管理cookie,可迭代
        ck = cookielib.CookieJar()
        #创建类内部对象opener,把CookieJar塞进去,每次打开页面都会自动使用cookie
        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(ck))
        try:
            #打开登陆页面,获取cookie
            self.opener.open('http://XXX.Mosaic.XXX.XXX/elect')
        except urllib2.URLError,e:
            print "Error code:", e.code
            print "Return content", e.read()
            return None
        for item in ck:
            #将cookie存到类内部变量jid中。
            self.jid = item.name+'='+item.value
            return self.jid
        return None
    #获取验证码
    def getCAPTCHA(self, cookie):
        #输出cookie检查
        print self.jid
        #按照包内格式,写好头部,是一个字典类型对象。
        header = {
            'Accept':'image/webp,*/*;q=0.8',\
            'Accept-Encoding':'gzip, deflate, sdch',\
            'Accept-Language':'zh-CN,zh;q=0.8',\
            'Connection':'keep-alive',
            #cookie的值使用self.jid
            'Cookie':self.jid,\
            'Host':'XXX.Mosaic.XXX.XXX',\
            'Referer':'http://XXX.Mosaic.XXX.XXX/elect/',\
            'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36'}
        #随机数既然是随机的,服务器也应该不知道是什么,所以这里随便给一个。
        #并且,随机数的值并没有和图片绑定,可以说是然并卵。
        #编码参数`v`
        params = urllib.urlencode({'v':'0.1932646029163152'})
        #构造`GET`的地址,格式为:`服务器地址`+`?`+`编码后的参数`
        capurl = ('http://XXX.Mosaic.XXX.XXX/elect/login/code?%s' % params)
        #用opener打开页面,加上头部
        response = self.opener.open(urllib2.Request(capurl,headers=header))
        #response就是图片内容,将它写入本地图片文件中
        f = file("code.jpg",'wb')
        f.write(response.read())
        f.close()
        #关闭图片,之后可以在其他函数中用绝对路径打开图片。
        return 

    #获取sid,因为后面选课的时候要用,获取到了说明登陆成功。
    #传入账号,密码,验证码。
    def getSid(self,username,password,j_code):
        #build header
        header = {
            'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',\
            'Accept-Encoding':'gzip, deflate',\
            'Accept-Language':'zh-CN,zh;q=0.8',\
            'Cache-Control':'max-age=0',\
            'Connection':'keep-alive',\
            'Content-Length':'80',\
            'Content-Type':'application/x-www-form-urlencoded',\
            'Cookie':self.jid,\
            'Host':'XXX.Mosaic.XXX.XXX',\
            'Origin':'http://XXX.Mosaic.XXX.XXX',\
            'Referer':'http://XXX.Mosaic.XXX.XXX/elect/index.html',\
            'User-Agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36',\
            }

        #build post data
        #后三个直接照抄
        postData = {'username':username,\
                'password':password,\
                'j_code':j_code,\
                'lt':'',\
                '_eventId':'submit',\
                'gateway':'true',\
                }
        #编码postdata
        postData = urllib.urlencode(postData)
        #目标服务器地址
        posturl = 'http://XXX.Mosaic.XXX.XXX/elect/login'
        #构建request
        request = urllib2.Request(posturl,postData,header)
        #用带有cookie的opener打开
        response = self.opener.open(request)
        #分析返回的地址,`geturl()`就是这么用的。从中提取`sid`并储存。
        string = str(response.geturl())
        self.sid = string[string.find(r'sid=')+4:]
        return self.sid

if __name__ == '__main__':
    #创建类对象
    lo = Login()
    #获取验证码
    j_code = lo.getCAPTCHA(lo.getCookie())
    #打开验证码
    Image.open('code.jpg').show()
    #输入信息
    j_code = raw_input(r"输入看到的验证码:")
    username = raw_input('username:')
    password = raw_input('password:')
    #获取sid并输出,证明登陆成功。
    print lo.getSid(username, password, j_code)

运行效果:
运行效果
账号密码打码了- -,如果不想明文输入密码,可以用getpass库。


后记

为防止被人肉,网址和账号密码等都打码了,包括代码里面的,因此代码是不能直接运行的。
有一段时间一直登陆不上,500错误,就是被服务器拒绝。通过wireshark抓包后对比发现,self.jid写成了jid,所以头部的cookie是空的,把他加上就行了。
还没有写上异常处理,打开网页的地方出错较多,用urllib2.URLError异常类就行了。
有问题或吐槽可以留言,谢谢大家。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java解码网页表单post内容小记

对网页表单post提交的数据进行解码。一般编码是base64或application/x-www-form-urlencoded类型,本文主要是针对这个实现。当然有很多是js加密的,就只能看怎么破解j...

谷歌浏览器-网络开发人员常见问题解答

简介 谷歌浏览器揭秘 何处可以找到有关其他浏览器的信息? 用户代理 谷歌浏览器的用户代理字符串是什么? 语言编码 谷歌浏览器未正确显示字符 无法使用 Ja...

python 爬虫 教务系统模拟登陆 并下载课表

使用requests 的get post 方式访问网址,requests.Session()的方法保持登陆状态cookie,模拟登陆教务系统...
  • qq8677
  • qq8677
  • 2017年05月09日 22:13
  • 219

python爬虫——模拟登陆教务系统

目录 python urllib库的使用 python带cookie的爬取方法首先来说一下python爬取页面的基本方法即urllib库的使用:import urllib2response = url...
  • tracy_n
  • tracy_n
  • 2016年10月06日 14:36
  • 784

Python模拟登陆3: 进入选课系统(手工输入验证码阶段)

其实最想做的是选课插件,于是这次试试了下选课系统,但是选课系统 有验证码。 很是蛋疼。 需要识别。 但是现在可以用另一种方法。就是下载到本地手动输入。也只需要一次就够了。因为登陆成功后就可以随意操作其...

Java--使用httpClient模拟登陆正方教务系统获取课表

首先,感谢这篇博文给了我思路:http://www.blogfshare.com/php-curl-zhengfang.html  最近形如课程格子与超表课程表应用如雨后春笋般涌现,他们自动获取课程表...

Android实现模拟登陆教务系统并解析网页数据

前言

PHP的curl带验证码模拟登陆学校的教务系统(验证码已被自动识别,不需要输入)

用PHP的curl模拟登录教务系统的简单实现

php模拟登陆校园教务网络管理系统

写在前面:使用了python进行爬虫之后,发现还没用过我的老本行php进行爬取过,加上大四狗刚开学就遇到坑*的所谓的实训,又不能出去找实习,于是只能自娱自乐,刚好看到最近学校经营的公众号,有绑定学号,...

java 模拟登陆正方教务系统

比较懒,主要说一下思路。。 1、首先正方教务系统的验证码当你不去向服务器申请的时候,可以直接无视它不需要去输入验证码。可以通过浏览器屏蔽学校教务系统的图片就可以直接输入账号密码回车进去。。 2、通...
  • a73265
  • a73265
  • 2016年03月09日 20:27
  • 2172
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Python 模拟登陆教务选课系统
举报原因:
原因补充:

(最多只允许输入30个字)