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': ''
  76. }
  77.  
  78. ## the data below are settled by customer to select the class needed
  79. start =
  80. end =
  81. numid = ''
  82. year =
  83. month =
  84. day =
  85. username = 'myname'
  86. password = 'mypasswd'
  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 =
  97. while True:
  98. print '------------------------'
  99. print 'have tryed to login %d times, now try again!' % (count)
  100. count = count +
  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. yuechedate = date(year, month, day)
  122. today = date.today()
  123. intervaldays = (yuechedate - today).days
  124. print intervaldays
  125. if intervaldays < :
  126. exit()
  127. validcode = ''
  128. count =
  129. ## try to select a class until success
  130. while True:
  131. print '--------------------------'
  132. print 'have tryed to select %d times, now try again!' % (count)
  133. count = count +
  134. try:
  135. validcode = openerUrlToString(opener, url5)
  136. except:
  137. continue
  138. url7 = 'http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=stu'\
  139. + '&stuid=%s&sfznum=&carid=&ValidCode=%s' % (username, validcode)
  140. data = opener.open(url7).read().decode('utf-8')
  141. strs = re.search('\[\{\"fchrdate.*?\}\]', data)
  142. #print data
  143. print strs
  144. if strs is None:
  145. continue
  146. jsontext = json.loads(strs.group())
  147. num = jsontext[intervaldays][numid].split('/')[]
  148. print 'remain num is ' + num
  149. if num == '':
  150. print 'no class avaliable!'
  151. time.sleep()
  152. continue
  153. try:
  154. validcode = openerUrlToString(opener, url5)
  155. except:
  156. continue
  157. url6 = 'http://wsyc.dfss.com.cn/Ajax/StuHdl.ashx?loginType=2&method=yueche'\
  158. + '&stuid=%s&bmnum=BD14101500687&start=%d&end=%d' % (username, start, end)\
  159. + '&lessionid=001&trainpriceid=BD13040300001&lesstypeid=02'\
  160. + '&date=%d-%d-%d' % (year, month, day)\
  161. + '&id=1&carid=&ycmethod=03&cartypeid=01&trainsessionid=0' + numid\
  162. + '&ReleaseCarID=&ValidCode=' + validcode
  163. result = opener.open(url6).read().decode('utf-8')
  164. print 'result of select is ' + result
  165. if result == 'success':
  166. print 'select success!'
  167. break
  168. else:
  169. continue

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

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

    受益于这个模块的帮助,在这里我推荐一手. https://pythonhosted.org/psutil/#processes psutil是一个基于python的跨平台系统信息监视模块.在pytho ...

  2. 一个使用 Python 的人工智能聊天机器人框架

    一个Python 的 AI Chatbot框架 建立一个聊天室可以听起来很棒,但它是完全可行的. IKY是一个内置于Python中的AI动力对话对话界面. 使用IKY,很容易创建自然语言会话场景,无需 ...

  3. 部署一个基于python语言的web发布环境

    ---恢复内容开始--- 1) 一门面向对象的语言 2)拥有丰富的库 3)可移植性 4)免费.开源 5)简单易易学 可做软件开发.人工智能.web开发等等 部署流程: Cnetos7.5+Nginx+ ...

  4. 一个用python写的比特币均线指标

    https://blog.csdn.net/gsl222/article/details/104554397 https://github.com/yyy999/auto_ma912 一个用pytho ...

  5. 推荐一个学习python非常好的网站

    推荐一个入门python非常好的网站(也可以学习JAVA)非常适合入门,不说多易于理解,也是比较亲民的0基础学习教程,还免费…… 网址:https://www.liaoxuefeng.com/(廖雪峰 ...

  6. python函数的实例,书写一个创建有针对性的专用密码字典的程序

    python学习,实战学习,函数的学习与使用,综合知识的运用.包括for ,while循环,if...else.. 和if... elif ... else 的条件判断! 问题描述:书写一个创建有针对 ...

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

    python把汉字转换成拼音实现程序 文章一个简洁干的汉字转拼音 程序,复制下载就可以直接使用,有需要的同学可以参考一下下. #coding:utf-8 #基于python2.6 table = 'a ...

  8. Python 项目实践三(Web应用程序)第一篇

    一 Djangao入门 当今的网站实际上都是富应用程序(rich application),就像成熟的桌面应用程序一样.Python提供了一组开发Web应用程序的卓越工具.在本章中,你将学习如何使用D ...

  9. 20180821 Python学习笔记:如何获取当前程序路径

    20180821 Python学习笔记:如何获取当前程序路径 启动的脚本的路径为:D:\WORK\gitbase\ShenzhenHouseInfoCrawler\main.py 当前脚本的路径为:D ...

随机推荐

  1. ACM第六周竞赛题目——A LightOJ 1317

    A - A Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status P ...

  2. 在javaweb中通过servlet类和普通类读取资源文件

    javaweb有两种方式读取资源文件 在Servlet中读取,可以使用servletContext,servletContext可以拿到web所有的资源文件,然后随便读,但是这种方法不常用,尽量少在S ...

  3. VB.net 连接池

    上篇博客介绍了临时表的使用,以及它的生命周期和连接池的关系.那么为了能更好的把握临时表的产生和消亡,本篇博客就介绍Vb.net连接池.在打开和关闭数据库连接时的耗费的资源是非常高的.那么在程序需要频繁 ...

  4. MVC4中EasyUI Tree异步加载JSON数据生成树

      1,首先构造tree接受的格式化数据结构MODEL /// <summary> /// 定义EasyUI树的相关数据,方便控制器生成Json数据进行传递 /// </summar ...

  5. AE 3D摄像机工作原理

    看了AE教程的3D可视化音频和序列法导入三维模型之后对于视频解析3D是有了更深的认识.很感谢AE在CS6之后加入了3D摄像机跟踪器的功能.它是通过摄像机跟踪反求来得到影片中的平面特征点.然后由用户指定 ...

  6. 【wpf基础】wpf MediaElement全屏播放视频功能

    最近在研究如何将视频全屏播放,一开始思路A:弹窗将MediaElement对象add到一个新的全屏窗体,报错 指定的元素已经是另一个元素的逻辑子元素.请先将其断开连接. 后续转换思路B:将本窗体其他控 ...

  7. Scriptcase演示程序

    为了方便大家对Scriptcase有一个非常直观的印象,现在将Scriptcase的示例程序进行了适当汉化,并且放在互联网上,您可以直接点击这个地址访问. 需要说明的是,示例程序中提供的范例,基本上都 ...

  8. [Flux] Component / Views

    The application will dislay a some catalogs, and each catalog has title image, description. Catalog: ...

  9. 多线程下的performSelector和NSThread的使用

    多线程下的performSelector和NSThread的使用 NSThread的多线程使用: 我们可以使用这两种方法来使用线程中的问题 - (id)initWithTarget:(id)targe ...

  10. google(转帖)

    本帖最后由 qiushui_007 于 2014-6-10 16:14 编辑 IP Addresses of Google Global Cachewww.kookle.co.nr Bulgaria  ...