一个用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数据就得到需要的数据啦!
最后,贴上我的代码:
- import re
- import json
- import time
- import urllib
- import urllib2
- import urlparse
- import cookielib
- from PIL import Image, ImageDraw, ImageFont, ImageFilter
- from pytesser import *
- from datetime import date
- import os
- os.chdir('C://Python27/Lib/site-packages/pytesser')
- def getVerify(name):
- #data = urllib2.urlopen(
- im = Image.open(name)
- imgry = im.convert('L')
- text = image_to_string(imgry)
- text = re.sub('\W','',text)
- return text
- def urlToString(url):
- data = urllib2.urlopen(url).read()
- f = open('buffer/temp.jpg', 'wb')
- f.write(data)
- f.close()
- return getVerify('buffer/temp.jpg')
- def openerUrlToString(opener, url):
- data = opener.open(url).read()
- f = open('buffer/temp.jpg', 'wb')
- f.write(data)
- f.close()
- return getVerify('buffer/temp.jpg')
- def getOpener(head):
- # deal with the Cookies
- cj = cookielib.CookieJar()
- pro = urllib2.HTTPCookieProcessor(cj)
- opener = urllib2.build_opener(pro)
- header = []
- for key, value in head.items():
- elem = (key, value)
- header.append(elem)
- opener.addheaders = header
- return opener
- def decodeAnyType(data):
- ret = data
- try:
- temp = data.decode('utf-8')
- ret = temp
- except:
- pass
- try:
- temp = data.decode('gbk')
- ret = temp
- except:
- pass
- try:
- temp = data.decode('gb2312')
- ret = temp
- except:
- pass
- return ret
- header = {
- 'Connection': 'Keep-Alive',
- 'Accept': 'text/html, application/xhtml+xml, */*',
- 'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3',
- 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko',
- 'Accept-Encoding': 'gzip, deflate',
- 'Host': 'wsyc.dfss.com.cn',
- 'DNT': ''
- }
- ## the data below are settled by customer to select the class needed
- start =
- end =
- numid = ''
- year =
- month =
- day =
- username = 'myname'
- password = 'mypasswd'
- opener = getOpener(header)
- url1 = 'http://wsyc.dfss.com.cn/'
- url2 = 'http://wsyc.dfss.com.cn/DfssAjax.aspx'
- url3 = 'http://wsyc.dfss.com.cn/validpng.aspx?aa=3&page=lg'
- url4 = 'http://wsyc.dfss.com.cn/pc-client/jbxx.aspx'
- url5 = 'http://wsyc.dfss.com.cn/validpng.aspx'
- ## try to login until the validcode is right
- count =
- while True:
- print '------------------------'
- print 'have tryed to login %d times, now try again!' % (count)
- count = count +
- validcode = openerUrlToString(opener, url3)
- print 'the validcode is ' + validcode
- postDict = {
- 'AjaxMethod': 'LOGIN',
- 'Account': username,
- 'ValidCode': validcode,
- 'Pwd': password
- }
- postData = urllib.urlencode(postDict).encode()
- op = opener.open(url2, postData)
- result = op.read().decode('utf-8')
- print 'the result of login is ' + result
- #if result.find('true') >= 0:
- if result == 'true':
- print 'login success!'
- break
- else:
- continue
- yuechedate = date(year, month, day)
- today = date.today()
- intervaldays = (yuechedate - today).days
- print intervaldays
- if intervaldays < :
- exit()
- validcode = ''
- count =
- ## try to select a class until success
- while True:
- print '--------------------------'
- print 'have tryed to select %d times, now try again!' % (count)
- count = count +
- try:
- validcode = openerUrlToString(opener, url5)
- except:
- continue
- url7 = 'http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=stu'\
- + '&stuid=%s&sfznum=&carid=&ValidCode=%s' % (username, validcode)
- data = opener.open(url7).read().decode('utf-8')
- strs = re.search('\[\{\"fchrdate.*?\}\]', data)
- #print data
- print strs
- if strs is None:
- continue
- jsontext = json.loads(strs.group())
- num = jsontext[intervaldays][numid].split('/')[]
- print 'remain num is ' + num
- if num == '':
- print 'no class avaliable!'
- time.sleep()
- continue
- try:
- validcode = openerUrlToString(opener, url5)
- except:
- continue
- url6 = 'http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=yueche'\
- + '&stuid=%s&bmnum=BD14101500687&start=%d&end=%d' % (username, start, end)\
- + '&lessionid=001&trainpriceid=BD13040300001&lesstypeid=02'\
- + '&date=%d-%d-%d' % (year, month, day)\
- + '&id=1&carid=&ycmethod=03&cartypeid=01&trainsessionid=0' + numid\
- + '&ReleaseCarID=&ValidCode=' + validcode
- result = opener.open(url6).read().decode('utf-8')
- print 'result of select is ' + result
- if result == 'success':
- print 'select success!'
- break
- else:
- continue
一个用python实现的东方时尚(驾校)抢课程序的更多相关文章
- psutil一个基于python的跨平台系统信息跟踪模块
受益于这个模块的帮助,在这里我推荐一手. https://pythonhosted.org/psutil/#processes psutil是一个基于python的跨平台系统信息监视模块.在pytho ...
- 一个使用 Python 的人工智能聊天机器人框架
一个Python 的 AI Chatbot框架 建立一个聊天室可以听起来很棒,但它是完全可行的. IKY是一个内置于Python中的AI动力对话对话界面. 使用IKY,很容易创建自然语言会话场景,无需 ...
- 部署一个基于python语言的web发布环境
---恢复内容开始--- 1) 一门面向对象的语言 2)拥有丰富的库 3)可移植性 4)免费.开源 5)简单易易学 可做软件开发.人工智能.web开发等等 部署流程: Cnetos7.5+Nginx+ ...
- 一个用python写的比特币均线指标
https://blog.csdn.net/gsl222/article/details/104554397 https://github.com/yyy999/auto_ma912 一个用pytho ...
- 推荐一个学习python非常好的网站
推荐一个入门python非常好的网站(也可以学习JAVA)非常适合入门,不说多易于理解,也是比较亲民的0基础学习教程,还免费…… 网址:https://www.liaoxuefeng.com/(廖雪峰 ...
- python函数的实例,书写一个创建有针对性的专用密码字典的程序
python学习,实战学习,函数的学习与使用,综合知识的运用.包括for ,while循环,if...else.. 和if... elif ... else 的条件判断! 问题描述:书写一个创建有针对 ...
- python把汉字转换成拼音实现程序
python把汉字转换成拼音实现程序 文章一个简洁干的汉字转拼音 程序,复制下载就可以直接使用,有需要的同学可以参考一下下. #coding:utf-8 #基于python2.6 table = 'a ...
- Python 项目实践三(Web应用程序)第一篇
一 Djangao入门 当今的网站实际上都是富应用程序(rich application),就像成熟的桌面应用程序一样.Python提供了一组开发Web应用程序的卓越工具.在本章中,你将学习如何使用D ...
- 20180821 Python学习笔记:如何获取当前程序路径
20180821 Python学习笔记:如何获取当前程序路径 启动的脚本的路径为:D:\WORK\gitbase\ShenzhenHouseInfoCrawler\main.py 当前脚本的路径为:D ...
随机推荐
- ACM第六周竞赛题目——A LightOJ 1317
A - A Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit Status P ...
- 在javaweb中通过servlet类和普通类读取资源文件
javaweb有两种方式读取资源文件 在Servlet中读取,可以使用servletContext,servletContext可以拿到web所有的资源文件,然后随便读,但是这种方法不常用,尽量少在S ...
- VB.net 连接池
上篇博客介绍了临时表的使用,以及它的生命周期和连接池的关系.那么为了能更好的把握临时表的产生和消亡,本篇博客就介绍Vb.net连接池.在打开和关闭数据库连接时的耗费的资源是非常高的.那么在程序需要频繁 ...
- MVC4中EasyUI Tree异步加载JSON数据生成树
1,首先构造tree接受的格式化数据结构MODEL /// <summary> /// 定义EasyUI树的相关数据,方便控制器生成Json数据进行传递 /// </summar ...
- AE 3D摄像机工作原理
看了AE教程的3D可视化音频和序列法导入三维模型之后对于视频解析3D是有了更深的认识.很感谢AE在CS6之后加入了3D摄像机跟踪器的功能.它是通过摄像机跟踪反求来得到影片中的平面特征点.然后由用户指定 ...
- 【wpf基础】wpf MediaElement全屏播放视频功能
最近在研究如何将视频全屏播放,一开始思路A:弹窗将MediaElement对象add到一个新的全屏窗体,报错 指定的元素已经是另一个元素的逻辑子元素.请先将其断开连接. 后续转换思路B:将本窗体其他控 ...
- Scriptcase演示程序
为了方便大家对Scriptcase有一个非常直观的印象,现在将Scriptcase的示例程序进行了适当汉化,并且放在互联网上,您可以直接点击这个地址访问. 需要说明的是,示例程序中提供的范例,基本上都 ...
- [Flux] Component / Views
The application will dislay a some catalogs, and each catalog has title image, description. Catalog: ...
- 多线程下的performSelector和NSThread的使用
多线程下的performSelector和NSThread的使用 NSThread的多线程使用: 我们可以使用这两种方法来使用线程中的问题 - (id)initWithTarget:(id)targe ...
- google(转帖)
本帖最后由 qiushui_007 于 2014-6-10 16:14 编辑 IP Addresses of Google Global Cachewww.kookle.co.nr Bulgaria ...