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

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

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数据就得到需要的数据啦!

最后,贴上我的代码:

1import re2import json3import time4import urllib5import urllib26import urlparse7import cookielib8fromPIL import Image, ImageDraw, ImageFont, ImageFilter9frompytesser import *10fromdatetime import date11import os1213os.chdir('C://Python27/Lib/site-packages/pytesser')1415def getVerify(name):16#data =urllib2.urlopen(17im =Image.open(name)18imgry = im.convert('L')19text =image_to_string(imgry)20text = re.sub('\W','',text)21returntext2223def urlToString(url):24data =urllib2.urlopen(url).read()25f = open('buffer/temp.jpg','wb')26f.write(data)27f.close()28returngetVerify('buffer/temp.jpg')2930def openerUrlToString(opener, url):31data =opener.open(url).read()32f = open('buffer/temp.jpg','wb')33f.write(data)34f.close()35returngetVerify('buffer/temp.jpg')3637def getOpener(head):38# deal with the Cookies39cj =cookielib.CookieJar()40PRo =urllib2.HTTPCookieProcessor(cj)41opener =urllib2.build_opener(pro)42header =[]43forkey, valueinhead.items():44elem =(key, value)45header.append(elem)46opener.addheaders =header47returnopener4849def decodeAnyType(data):50ret =data51try:52temp = data.decode('utf-8')53ret =temp54except:55pass56try:57temp = data.decode('gbk')58ret =temp59except:60pass61try:62temp = data.decode('gb2312')63ret =temp64except:65pass66returnret6768header ={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}7778## the data below are settled by customer toselecttheclassneeded79start =1380end =1781numid ='3'82year =201483month =1284day =2285username ='myname'86passWord='mypasswd'8788opener =getOpener(header)89url1 ='http://wsyc.dfss.com.cn/'90url2 ='http://wsyc.dfss.com.cn/DfssAjax.aspx'91url3 ='http://wsyc.dfss.com.cn/validpng.aspx?aa=3&page=lg'92url4 ='http://wsyc.dfss.com.cn/pc-client/jbxx.aspx'93url5 ='http://wsyc.dfss.com.cn/validpng.aspx'9495##tryto login until the validcodeisright96count =097whileTrue:98print'------------------------'99print'have tryed to login %d times, now try again!'%(count)100count = count +1101validcode =openerUrlToString(opener, url3)102print'the validcode is'+validcode103postDict ={104'AjaxMethod':'LOGIN',105'Account': username,106'ValidCode': validcode,107'Pwd': password108}109110postData =urllib.urlencode(postDict).encode()111op =opener.open(url2, postData)112result = op.read().decode('utf-8')113print'the result of login is'+result114#ifresult.find('true') >= 0:115ifresult =='true':116print'login success!'117

break118else:119continue120121122yuechedate =date(year, month, day)123today =date.today()124intervaldays = (yuechedate -today).days125print intervaldays126ifintervaldays <2:127exit()128validcode =''129count =0130##trytoselectaclassuntil success131whileTrue:132print'--------------------------'133print'have tryed to select %d times, now try again!'%(count)134count = count +1135try:136validcode =openerUrlToString(opener, url5)137except:138continue139url7 ='http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=stu'\140+'&stuid=%s&sfznum=&carid=&ValidCode=%s'%(username, validcode)141data = opener.open(url7).read().decode('utf-8')142strs = re.search('\[\{\"fchrdate.*?\}\]', data)143#print data144print strs145ifstrsisNone:146continue147jsontext =json.loads(strs.group())148num = jsontext[intervaldays][numid].split('/')[1]149print'remain num is'+num150ifnum =='0':151print'no class avaliable!'152time.sleep(600)153continue154try:155validcode =openerUrlToString(opener, url5)156except:157continue158url6 ='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'+numid\163+'&ReleaseCarID=&ValidCode='+validcode164result = opener.open(url6).read().decode('utf-8')165print'result of select is'+result166ifresult =='success':167print'select success!'168

break169else:170continue

View Code

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航