热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

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

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



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


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


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




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


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

看到系统的整体内容后,再来介绍一下相关的技术 
这个自动发送请求,提交数据,都依赖于httpclient4,火车票订票官方是使用ssl加密,这里是启用httpclient的ssl功能 
Java代码   收藏代码
  1. SSLContext sslcontext = SSLContext.getInstance("TLS");  
  2. sslcontext.init(nullnew TrustManager[]{easyTrustManager}, null);  
  3. SSLSocketFactory sf = new SSLSocketFactory(sslcontext);  
  4. Scheme sch = new Scheme("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. public void run(){  
  2.       try {  
  3.         System.out.println("-----设置代理服务器----");  
  4.         String proxyFileString0 = FileUtils.readFileToString(new File(ApplicationUtils.getWebrootDir()+"/order/proxy_add.txt"), "UTF-8");  
  5.         String proxyFileString1 = FileUtils.readFileToString(new File(ApplicationUtils.getWebrootDir()+"/order/proxy_enable.txt"), "UTF-8");  
  6.         String proxyFileString = proxyFileString0+"\n"+proxyFileString1;  
  7.         for(String proxyString : StringUtils.split(proxyFileString, "\n")){  
  8.             proxyString = proxyString.trim();  
  9.             if(StringUtils.isNotEmpty(proxyString)){  
  10.                 System.out.print("-----测试代理服务器: "+proxyString);  
  11.                 String[] proxyInfo = proxyString.split(":");  
  12.                   
  13.                 HttpHost httpHost = new HttpHost(proxyInfo[0], Integer.valueOf(proxyInfo[1]));   
  14.                 long start = System.currentTimeMillis();  
  15.                 if(HttpUtils.testProxy(httpHost)){  
  16.                     long usetime = System.currentTimeMillis()-start;  
  17.                     if(usetime > 10000){  
  18.                         System.out.println(" 不使用,响应时间太长时间:"+usetime+"毫秒----");  
  19.                     }else{  
  20.                         System.out.println(" 可使用,使用时间:"+usetime+"毫秒----");  
  21.                         httpHostList.add(httpHost);  
  22.                     }  
  23.                 }  
  24.             }  
  25.         }  
  26.         System.out.println("-----设置代理服务器成功,总数:"+httpHostList.size()+"----");  
  27.     } catch (Exception e) {  
  28.     }  
  29. }  


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

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


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


这也只是本人兴趣开发,不使用在商品场合,以上分享的只是这个系统的设计思想,有时间再深入讨论。 
顺便附上本机(随时变动的)的一个链接地址,大家可以看看  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
  • 用httpclient开发的自动抢订火车票系源代码_控制台输入版本_.rar (108.6 KB)
  • 下载次数: 7168
  • HttpUtils.rar (4.6 KB)
  • 下载次数: 3031
  • OrderMain.rar (3.7 KB)
  • 下载次数: 2047

推荐阅读
  • 在Java领域,谈到网络编程,可能大家脑海里第一反应就是MINA,NETTY,GRIZZLY等优秀的开源框架。没错,不过在深入探究这些框架之前,我们需要先从最original的技 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 移动端常用单位——rem的使用方法和注意事项
    本文介绍了移动端常用的单位rem的使用方法和注意事项,包括px、%、em、vw、vh等其他常用单位的比较。同时还介绍了如何通过JS获取视口宽度并动态调整rem的值,以适应不同设备的屏幕大小。此外,还提到了rem目前在移动端的主流地位。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • centos安装Mysql的方法及步骤详解
    本文介绍了centos安装Mysql的两种方式:rpm方式和绿色方式安装,详细介绍了安装所需的软件包以及安装过程中的注意事项,包括检查是否安装成功的方法。通过本文,读者可以了解到在centos系统上如何正确安装Mysql。 ... [详细]
  • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
    ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
  • 现在比较流行使用静态网站生成器来搭建网站,博客产品着陆页微信转发页面等。但每次都需要对服务器进行配置,也是一个重复但繁琐的工作。使用DockerWeb,只需5分钟就能搭建一个基于D ... [详细]
  • 【技术分享】一个 ELF 蠕虫分析
    【技术分享】一个 ELF 蠕虫分析 ... [详细]
  • 如何搭建服务器环境php(2023年最新解答)
    导读:本篇文章编程笔记来给大家介绍有关如何搭建服务器环境php的相关内容,希望对大家有所帮助,一起来看看吧。本文目录一览:1、怎么搭建p ... [详细]
  • pc电脑如何投屏到电视?DLNA主要步骤通过DLNA连接,使用WindowsMediaPlayer的流媒体播放举例:电脑和电视机都是连接的 ... [详细]
  • charles3.11.1抓https包
    结论先行:用的是安卓测试机,没加固之前的生产环境的安装包,可以抓到https请求加固之后的包【也就是要上应用市场的包】,抓不到https请求电脑上的操作:1.安装证书【电脑上安装了 ... [详细]
  • 1.webkit内核中的一些私有的meta标签,这些meta标签在开发webapp时起到非常重要的作用(1) ... [详细]
  • 目前正在做毕业设计,一个关于校园服务的app,我会抽取已完成的相关代码写到文章里。一是为了造福这个曾经帮助过我的社区,二是写文章的同时更能巩固相关知识的记忆。一、前言在爬取教务系统 ... [详细]
author-avatar
FrxxGp
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有