一个用python实现的东方时尚(驾校)抢课程序

  2014-12-23

  东方时尚约车还要网上选课,资源太紧张了,于是我决定自己写一个抢票程序来帮我刷票。

  第一步,抓包。浏览器登陆选课系统,用抓包工具观察网络行为,这里我用的fildder。这里抓包主要需要获取两个信息,一是浏览器发送了哪几条url请求,二是获得http报文的头部以及post出去的data内容和格式。

  第二步,模拟登陆。将抓取来的头部抄过来,让python模拟浏览器进行登陆,输入用户名和密码。这里登陆需要验证码,先来一个手工识别的,让python把获取到的.jpg文件保存到本地,然后暂停等待输入,人眼识别出验证码后输入给程序,让程序继续执行。一开始总是说验证码错误,最后发现时请求方式不对,这里要注意,每次获取url都要用同一个opener去获取,这样服务器才会认为是同一只浏览器。修改后,登录成功。

  第三步,解决验证码。手工输入验证码总非长远之计,还是要让机器去做。这里用了PIL包和pytesser包,里面有实现好了的解析验证码的方法,直接拿来用就行了。由于这个包对验证码的识别率不是100%,所以我把登录的代码放进一个while循环里,直到顺利登录为止。

  第四步,抢课。继续抓包,分析选课的ur请求过程,然后让程序模拟。比如在浏览器发现周五晚上有一节课可以选,然后让程序去抢周五晚上的课,程序返回结果显示ok,刷新浏览器,这节课确实选上了,说明程序大功告成了!

  后续,读数据。东方时尚网站的制作者也不是完全吃素的。由于好的时间段通常都选不到课,我让我的程序做while循环,一直刷课知道选上为止。刷了几小时后,网页说我的操作次数过多,今天禁止我的访问。为了解决这个问题,我把刷课的频率改为10分钟一次。由于选课也需要验证码,而验证码识别率不高,这样如果有课的时候因为验证码错误却要等待10分钟岂不是浪费机会了,所以我又将程序改为如果没课,就等待10分钟,如果有课就一直刷。这样就有需要提取数据,分析网页结构,发现有一个单独的url用了存储数据,剩余课时在其中的一个json格式的字符串里。先用正则匹配提取出这个串,然后解析这个json数据就得到需要的数据啦!

  最后,贴上我的代码:

  1 import re
  2 import json
  3 import time
  4 import urllib
  5 import urllib2
  6 import urlparse
  7 import cookielib
  8 from PIL import Image, ImageDraw, ImageFont, ImageFilter
  9 from pytesser import *
 10 from datetime import date
 11 import os
 12
 13 os.chdir(‘C://Python27/Lib/site-packages/pytesser‘)
 14
 15 def getVerify(name):
 16     #data = urllib2.urlopen(
 17     im = Image.open(name)
 18     imgry = im.convert(‘L‘)
 19     text = image_to_string(imgry)
 20     text = re.sub(‘\W‘,‘‘,text)
 21     return text
 22
 23 def urlToString(url):
 24     data = urllib2.urlopen(url).read()
 25     f = open(‘buffer/temp.jpg‘, ‘wb‘)
 26     f.write(data)
 27     f.close()
 28     return getVerify(‘buffer/temp.jpg‘)
 29
 30 def openerUrlToString(opener, url):
 31     data = opener.open(url).read()
 32     f = open(‘buffer/temp.jpg‘, ‘wb‘)
 33     f.write(data)
 34     f.close()
 35     return getVerify(‘buffer/temp.jpg‘)
 36
 37 def getOpener(head):
 38     # deal with the Cookies
 39     cj = cookielib.CookieJar()
 40     pro = urllib2.HTTPCookieProcessor(cj)
 41     opener = urllib2.build_opener(pro)
 42     header = []
 43     for key, value in head.items():
 44         elem = (key, value)
 45         header.append(elem)
 46     opener.addheaders = header
 47     return opener
 48
 49 def decodeAnyType(data):
 50     ret = data
 51     try:
 52         temp = data.decode(‘utf-8‘)
 53         ret = temp
 54     except:
 55         pass
 56     try:
 57         temp = data.decode(‘gbk‘)
 58         ret = temp
 59     except:
 60         pass
 61     try:
 62         temp = data.decode(‘gb2312‘)
 63         ret = temp
 64     except:
 65         pass
 66     return ret
 67
 68 header = {
 69     ‘Connection‘: ‘Keep-Alive‘,
 70     ‘Accept‘: ‘text/html, application/xhtml+xml, */*‘,
 71     ‘Accept-Language‘: ‘en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3‘,
 72     ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko‘,
 73     ‘Accept-Encoding‘: ‘gzip, deflate‘,
 74     ‘Host‘: ‘wsyc.dfss.com.cn‘,
 75     ‘DNT‘: ‘1‘
 76 }
 77
 78 ## the data below are settled by customer to select the class needed
 79 start = 13
 80 end = 17
 81 numid = ‘3‘
 82 year = 2014
 83 month = 12
 84 day = 22
 85 username = ‘11089212‘
 86 password = ‘235813‘
 87
 88 opener = getOpener(header)
 89 url1 = ‘http://wsyc.dfss.com.cn/‘
 90 url2 = ‘http://wsyc.dfss.com.cn/DfssAjax.aspx‘
 91 url3 = ‘http://wsyc.dfss.com.cn/validpng.aspx?aa=3&page=lg‘
 92 url4 = ‘http://wsyc.dfss.com.cn/pc-client/jbxx.aspx‘
 93 url5 = ‘http://wsyc.dfss.com.cn/validpng.aspx‘
 94
 95 ## try to login until the validcode is right
 96 count = 0
 97 while True:
 98     print ‘------------------------‘
 99     print ‘have tryed to login %d times, now try again!‘ % (count)
100     count = count + 1
101     validcode = openerUrlToString(opener, url3)
102     print ‘the validcode is ‘ + validcode
103     postDict = {
104         ‘AjaxMethod‘: ‘LOGIN‘,
105         ‘Account‘: username,
106         ‘ValidCode‘: validcode,
107         ‘Pwd‘: password
108     }
109
110     postData = urllib.urlencode(postDict).encode()
111     op = opener.open(url2, postData)
112     result = op.read().decode(‘utf-8‘)
113     print ‘the result of login is ‘ + result
114     #if result.find(‘true‘) >= 0:
115     if result == ‘true‘:
116         print ‘login success!‘
117         break
118     else:
119         continue
120
121
122 yuechedate = date(year, month, day)
123 today = date.today()
124 intervaldays = (yuechedate - today).days
125 print intervaldays
126 if intervaldays < 2:
127     exit()
128 validcode = ‘‘
129 count = 0
130 ## try to select a class until success
131 while True:
132     print ‘--------------------------‘
133     print ‘have tryed to select %d times, now try again!‘ % (count)
134     count = count + 1
135     try:
136         validcode = openerUrlToString(opener, url5)
137     except:
138         continue
139     url7 = ‘http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=stu‘140            + ‘&stuid=%s&sfznum=&carid=&ValidCode=%s‘ % (username, validcode)
141     data = opener.open(url7).read().decode(‘utf-8‘)
142     strs = re.search(‘\[\{\"fchrdate.*?\}\]‘, data)
143     #print data
144     print strs
145     if strs is None:
146         continue
147     jsontext = json.loads(strs.group())
148     num = jsontext[intervaldays][numid].split(‘/‘)[1]
149     print ‘remain num is ‘ + num
150     if num == ‘0‘:
151         print ‘no class avaliable!‘
152         time.sleep(600)
153         continue
154     try:
155         validcode = openerUrlToString(opener, url5)
156     except:
157         continue
158     url6 = ‘http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=yueche‘159            + ‘&stuid=%s&bmnum=BD14101500687&start=%d&end=%d‘ % (username, start, end)160            + ‘&lessionid=001&trainpriceid=BD13040300001&lesstypeid=02‘161            + ‘&date=%d-%d-%d‘ % (year, month, day)162            + ‘&id=1&carid=&ycmethod=03&cartypeid=01&trainsessionid=0‘ + numid163            + ‘&ReleaseCarID=&ValidCode=‘ + validcode
164     result = opener.open(url6).read().decode(‘utf-8‘)
165     print ‘result of select is ‘ + result
166     if result == ‘success‘:
167         print ‘select success!‘
168         break
169     else:
170         continue

时间: 2024-10-09 00:56:55

一个用python实现的东方时尚(驾校)抢课程序的相关文章

分享一下我在东方时尚学车的经历

楼主是4月26日报的名,7月22日拿的本,不算快的,不过也不算慢的.和大多数简子们一样,楼主也是个苦比的白领一族,白天上班,大多数都是晚上去学车,每一次请个小假还得胆战心惊的看经理大大的脸色,各种苦不堪言.特别是世界杯那段时间,楼主是白天上班,晚上学车,夜里看球,害得最后白天走路都打飘~~好了闲话不多扯了,接下来说一下关于在东方时尚学车的经历以及经验,也希望给后来的简子们一些帮助.先说科目一.其实吧科目一在学车里面算是最简单的一项了,可惜楼主那段时间报名的正是高峰期(话说东方时尚任何时间段都是高

【美妙的Python之中的一个】Python简单介绍及环境搭建

美妙的Python之Python简单介绍及安装         简而言之: Python 是能你无限惊喜的语言,与众不同.             1.Python:          Python英文意思为蟒蛇,故又称为蟒蛇语言,在图标设计上有所体现,贵铎·范·罗萨姆(Guido van Rossum)于1989年创立.Python的特质,简单,优雅,健壮,继承传统编程语言的强大性与通用性,同一时候兼具简单脚本的简单性.         Python的哲学:仅仅用一种方法,最好是仅仅有一种方法

Web2py是一个用Python语言编写的免费的开源Web框架

Zope 2是一款基于Python的Web应用框架,是所有Python Web应用程序.工具的鼻祖,是Python家族一个强有力的分支.Zope 2的"对象发布"系统非常适合面向对象开发方法,并且可以减轻开发者的学习曲线,还可以帮助你发现应用程序里一些不好的功能. Web2py是一个用Python语言编写的免费的开源Web框架,旨在敏捷快速的开发Web应用,具有快速.可扩展.安全以及可移植的数据库驱动的应用,遵循LGPLv3开源协议. Web2py提供一站式的解决方案,整个开发过程都可

psutil一个基于python的跨平台系统信息跟踪模块

受益于这个模块的帮助,在这里我推荐一手. https://pythonhosted.org/psutil/#processes psutil是一个基于python的跨平台系统信息监视模块.在python下,我们可以利用它来监视.检测和限制系统资源的使用.它提供了类似于一套控制台的指令功能,像是ps.netstat.ifconfig等等.当前这个模块支持的系统有windows/osx/linux/FreeBSD/Sun Solaris.32.64位均支持.python环境为2.6-3.5. 这里我

Python编程学习,高效求解素数程序实例

素数是编程中经常需要用到的. 作为学习Python的示例,下面是一个高效求解一个范围内的素数的程序,不需要使用除法或者求模运算. 1 #coding:utf-8 #设置python文件的编码为utf-8,这样就可以写入中文注释 2 def primeRange(n): 3 myArray=[1 for x in range(n+1)] ##列表解析,生成长度为(n+1)的列表,每个数值都为1 4 myArray[0]=0 5 myArray[1]=0 6 startPos=2 7 while s

python把汉字转换成拼音实现程序

python把汉字转换成拼音实现程序 文章一个简洁干的汉字转拼音 程序,复制下载就可以直接使用,有需要的同学可以参考一下下. #coding:utf-8 #基于python2.6 table = 'a,-20319;ai,-20317;an,-20304;ang,-20295;ao,-20292;ba,-20283;bai,-20265;ban,-20257;bang,-20242;bao,-20230;bei,-20051;ben,-20036;beng,-20032;bi,-20026;bi

一个可以自动生成静态库,自动安装程序的Makefile

.PHONY:clean install CC=g++ CFLAGS=-Wall -g BIN=libecho.a INCLUDE=echo SRC=src OBJS=Socket.o Rio.o TcpConnection.o PollPoller.o InetAddress.o TcpServer.o Thread.o Condition.o ThreadPool.o Exception.o Timer.o TimerThread.o STARD=-std=c++0x -rdynamic $

一个利用“永恒之蓝”漏洞传播的挖矿程序分析

背景介绍 近日,渔村安全团队追踪到一个利用永恒之蓝漏洞传播的挖矿程序,其具备高度的模块化和较强的传播能力,在短短数日就感染了数万台用户电脑.针对该突发情况,渔村安全团队迅速组织应急工作,最终使得目前的感染情况受到控制,下文为样本分析. 感染量 从微软发布ms17-010(永恒之蓝漏洞) 的修复补丁到现在已经过去四个月了,相继爆发的利用该漏洞传播的WannaCry,Petya 勒索病毒更是给 我们 上了一课.但目前来看,还是有不少用户没有及时更新补丁或者做相应的缓解措施,同时 Shadow Bro

python批量同步web服务器代码核心程序

#!/usr/bin/env python #coding:utf8 import os,sys import md5,tab from mysql_co.my_db import set_mysql from ssh_co.ssh_connect import sshd from ssh_co.cfg.config import ssh_message,item_path from file import findfile def my_mysql(): db_file={} my_conne