`
a137268431
  • 浏览: 144913 次
文章分类
社区版块
存档分类
最新评论

用httpclient开发的在线自动抢订火车票系统(铁老大不给力,哥给力)

 
阅读更多
前两天女友要在线订火车在票,一直都没有办法订到票,最后没办法,便给她写了个自动抢票的脚本,可周边的朋友听她说通过软件订到票了,都先后向她要软件,可原来的脚本只是基于控制台输入,这样给别人也没法用,兴趣一起,就花了一天的时间做了个WEB界面,然后分享给朋友用。先上几张图,看大家看看。

这个是登录界面,要使用前先设置一下常用的邮箱和登录密码,自动抢票过程中,如需要再输入登录验证码和订单验证码,或订单成功时,将通过此email通知您,建议使用qq邮箱,这样只要您在电脑时开打QQ,收到邮件时,qq会弹出窗口通知您,您可以即时响应。
第一次使用时,要先把在火车票官网注册的资料填在这里:

这资料都必码是已在官方上注册过的,在自动订票时,需要用到这些资料。



第一次登录后需要求先填写官网上的登录验证码和订单提交验证码,只要填写正确后,在填票过程中就一直可以使用,这也是官网的BUG,应该是他们在较正验证码后,没有让当前验证码失效,这样就只要不去刷新验证码,就可以一直使用第一次输入的正确验证码。


填写一下订票任务,主要就填写订票人资料(当然这个也是要在官网上添加过的),和订票信息,什么时候从哪到哪,从几列车等,保存完后,点开始,就则可以自动登录,找票,然后订票,订票成功后发邮件通知。


执行过程中,会时间更新执行的结果信息。




留言板功能,收集问题的反馈。


网友提供http代理,官方网站对一个IP的单位时间内访问次数据有限制,超过这个超制值IP会被封锁一段时间。
因为使用的人多,所以系统需要使用代理来向官网发送请求。

看到系统的整体内容后,再来介绍一下相关的技术
这个自动发送请求,提交数据,都依赖于httpclient4,火车票订票官方是使用ssl加密,这里是启用httpclient的ssl功能
Java代码收藏代码
  1. SSLContextsslcontext=SSLContext.getInstance("TLS");
  2. sslcontext.init(null,newTrustManager[]{easyTrustManager},null);
  3. SSLSocketFactorysf=newSSLSocketFactory(sslcontext);
  4. Schemesch=newScheme("https",sf,443);
  5. httpclient.getConnectionManager().getSchemeRegistry().register(sch);


大家都知道,这个官网的反映速度有时实在是惨不忍睹,所以我们也要设计一下请求等待的最长时间(30秒):
Java代码收藏代码
  1. httpclient.getParams().setIntParameter("http.socket.timeout",30000);//毫秒


官方网站对一个IP的单位时间内访问次数据有限制,超过这个超制值IP会被封锁一段时间。
因为使用的人多,所以系统需要使用代理来向官网发送请求,这个代理需要支持ssl,所以先网上找到一批代理IP过来,存在一个txt文字,格式为 ip:端口\n,以下读取IP代理,并且进行速试测试
Java代码收藏代码
  1. publicvoidrun(){
  2. try{
  3. System.out.println("-----设置代理服务器----");
  4. StringproxyFileString0=FileUtils.readFileToString(newFile(ApplicationUtils.getWebrootDir()+"/order/proxy_add.txt"),"UTF-8");
  5. StringproxyFileString1=FileUtils.readFileToString(newFile(ApplicationUtils.getWebrootDir()+"/order/proxy_enable.txt"),"UTF-8");
  6. StringproxyFileString=proxyFileString0+"\n"+proxyFileString1;
  7. for(StringproxyString:StringUtils.split(proxyFileString,"\n")){
  8. proxyString=proxyString.trim();
  9. if(StringUtils.isNotEmpty(proxyString)){
  10. System.out.print("-----测试代理服务器:"+proxyString);
  11. String[]proxyInfo=proxyString.split(":");
  12. HttpHosthttpHost=newHttpHost(proxyInfo[0],Integer.valueOf(proxyInfo[1]));
  13. longstart=System.currentTimeMillis();
  14. if(HttpUtils.testProxy(httpHost)){
  15. longusetime=System.currentTimeMillis()-start;
  16. if(usetime>10000){
  17. System.out.println("不使用,响应时间太长时间:"+usetime+"毫秒----");
  18. }else{
  19. System.out.println("可使用,使用时间:"+usetime+"毫秒----");
  20. httpHostList.add(httpHost);
  21. }
  22. }
  23. }
  24. }
  25. System.out.println("-----设置代理服务器成功,总数:"+httpHostList.size()+"----");
  26. }catch(Exceptione){
  27. }
  28. }


最后在每次请求时,选择一个代理
Java代码收藏代码
  1. //设置代理对象ip/代理名称,端口
  2. try{
  3. httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,ProxyHostUtils.next());
  4. }catch(Exceptione){}

每个用户在发送请求前,先从官网上读取两个验证码,一个是登录验证码,一个是提交订单验证码,一次性读取就可以了。
Java代码收藏代码
  1. /**
  2. *读取登录验证码
  3. *@throwsException
  4. */
  5. @Transient
  6. publicvoidgetRemoteLoginCode()throwsException{
  7. Filefile=HttpUtils.doGetFile(OrderRunTask.loginCodeUrl+"&nocache="+Utils.getRandomString(10),cookieContext);
  8. if(file!=null){
  9. FilecodeFile=newFile(ApplicationUtils.getWebrootDir()+getLoginCodeUrl());
  10. FileUtils.copyFile(file,codeFile);
  11. }
  12. }
  13. /**
  14. *读取提交订单验证码
  15. *@throwsException
  16. */
  17. @Transient
  18. publicvoidgetRemoteSumitCode()throwsException{
  19. Filefile=HttpUtils.doGetFile(OrderRunTask.submitCodeUrl+"&nocache="+Utils.getRandomString(10),cookieContext);
  20. if(file!=null){
  21. FilecodeFile=newFile(ApplicationUtils.getWebrootDir()+getSubmitCodeUrl());
  22. FileUtils.copyFile(file,codeFile);
  23. }
  24. }


每个用户可以同时订多张火车票,系统为每张火车票启动一个线程,持续的运行,直到订票成功或者是被中断。
Java代码收藏代码
  1. //建立线程池
  2. publicstaticExecutorServicerunningTaskPool=Executors.newFixedThreadPool(1000);
  3. //启动订票任务
  4. OrderRunTaskorderRunTask=newOrderRunTask(account,orderTask);
  5. OrderRunTaskUtils.runningTaskMap.put(orderTask.getId(),orderRunTask);
  6. Future<?>future=OrderRunTaskUtils.runningTaskPool.submit(orderRunTask);
  7. orderRunTask.setFuture(future);
  8. //中断任务
  9. OrderRunTaskorderRunTask=OrderRunTaskUtils.runningTaskMap.get(taskId);
  10. try{
  11. orderRunTask.setStop();
  12. orderRunTask.getFuture().cancel(true);
  13. }catch(Exceptione){
  14. e.printStackTrace();
  15. }
  16. //判断是否订票成功,并且发送邮件
  17. if(body.indexOf("45分钟")!=-1){
  18. Datenow=newDate();
  19. account.sendMail(orderTask.getQueryTrainDate()+"_订票成功",
  20. orderTask.getQueryTrainDate()+""+
  21. orderTask.getFromStation()+"到"+orderTask.getToStation()+(StringUtils.isEmpty(orderTask.getTrainNo())?orderTask.getTrainNo():"")+"--订票时间:"
  22. +DateUtils.getDateTime("HH:mm:ss",now)
  23. );
  24. account.setReload(true);
  25. orderTask.setState(200);
  26. orderTask.setRuningTime(now);
  27. this.account.error(orderTask.toString()+":订票成功。");
  28. breaknext;
  29. }


这也只是本人兴趣开发,不使用在商品场合,以上分享的只是这个系统的设计思想,有时间再深入讨论。
顺便附上本机(随时变动的)的一个链接地址,大家可以看看http://125.77.229.129:7070/order.html
  • 大小: 64.8 KB
  • 大小: 75.2 KB
  • 大小: 48.7 KB
  • 大小: 64.4 KB
  • 大小: 25.3 KB
  • 大小: 20.7 KB
  • 大小: 22.5 KB
分享到:
评论
1 楼 niwai 2014-05-08  
你好我用httpclient4.2 登录亚马逊怎么提示没有激活cookie,网上试过很多方法还是不行啊,

相关推荐

Global site tag (gtag.js) - Google Analytics