本文章为原创文章,转载请注明,欢迎评论和改正。

一,分析

  之前所用的直接通过HTML中的元素值来爬取一些网页上的数据,但是一些比较敏感的数据,很多正规网站都是通过json数据存储,这些数据通过HTML元素是爬取不到的,所以只能通过json数据的api接口来爬取数据。

二,网站处理

  1,打开去哪儿网的网站https://train.qunar.com/,找到火车票查询,输入起点终点和日期,查询。

  

  2,右击打开审查元素,点击network

  3,刷新网页,找到XHR,点击链接

  4,找到s2sBeanList这一属性,打开即为所需要的数据

header里有所需的地址

三,项目结构

  1,所需jar包,基本是分析json数据的时候用到

  

  2,项目目录结构

 

四,代码分析

  1,解析URL地址,并以将json数据转化为String类型返回

  1. public static String geturl(String url){
  2. StringBuffer json = new StringBuffer();
  3. try {
  4. URL u = new URL(url);
  5. URLConnection yc = u.openConnection();
  6. //读取返回的数据
  7. BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
  8. String inputline = null;
  9. while((inputline=in.readLine())!=null){
  10. json.append(inputline);
  11. }
  12. in.close();
  13.  
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. }
  17. //将StringBuffer转化为json格式的字符串
  18. String jsonStr=json.toString();
              //将不规范的字符串形式的json数据规范化
  19. jsonStr=jsonStr.substring(jsonStr.indexOf("{"),jsonStr.length()-1);
  20. return jsonStr;
  21. }

  2,将地址转化为经纬度的方法(用到即可取)

  1. public static String getLngLat(String address) {
  2. StringBuffer json = new StringBuffer();
  3. try {
  4. URL u = new URL("http://restapi.amap.com/v3/geocode/geo?address="+address+"&output=JSON&key=7f4ffae4074e8b8e4d147190527a4b72");
  5. URLConnection yc = u.openConnection();
  6. //读取返回的数据
  7. BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
  8. String inputline = null;
  9. while((inputline=in.readLine())!=null){
  10. json.append(inputline);
  11. }
  12. in.close();
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }
  16. String jsonStr=json.toString();
  17. JSONObject jsonObject = JSONObject.fromObject(jsonStr);
                  //判断是否有这个点
  18. if(jsonObject.getJSONArray("geocodes").size()>0)
  19. return jsonObject.getJSONArray("geocodes").getJSONObject(0).get("location").toString();
  20. else
  21. return null;
  22. }

  3,查询火车票的代码

  1. public static List<TrainMess> loadTrainRoute(String startPoint,String endPoint,String date) {
  2. String strUrl="https://train.qunar.com/dict/open/s2s.do?callback=jQuery17203917861486539813_1558231852669"
  3. + "&dptStation="+startPoint+"&arrStation="+endPoint+"&date="+date //日期格式2019-05-20
  4. + "&type=normal&user=neibu&source=site&start=1&num=500&sort=3&_=1558231852892";
  5.  
  6. //调用方法将url转为json格式的字符串
  7. String jsonStr=geturl(strUrl);
  8. JSONObject jsonObject = JSONObject.fromObject(jsonStr);
  9.  
  10. JSONArray jArray=jsonObject.getJSONObject("data").getJSONArray("s2sBeanList");
  11.  
  12. for(int i=0;i<jArray.size();i++) {
  13.                    //循环遍历所有车次
  14. jsonObject=(jArray.getJSONObject(i));
  15.  
  16. System.out.println("起点:"+startPoint);
  17. System.out.println("起点经纬度:"+getLngLat(startPoint)); //getLngLat 调用将地址转化为经纬度的方法
  18. System.out.println("车次"+jsonObject.get("trainNo").toString());
  19. System.out.println("车站:"+jsonObject.get("dptStationName")+"-"+jsonObject.get("arrStationName"));
  20. System.out.println("时间段:"+jsonObject.get("dptTime")+"-"+jsonObject.get("arrTime"));
  21. System.out.println("一等座的价格:"+jsonObject.getJSONObject("seats").getJSONObject("一等座").get("price"));
  22. System.out.println("一等座的剩余票数:"+jsonObject.getJSONObject("seats").getJSONObject("一等座").get("count"));
  23.  
  24. }
  25. return null;
  26. }

 

  1. jsonObject=(jArray.getJSONObject(i));为循环遍历所有车次

 

五,完整代码

  1. package test;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.InputStreamReader;
  5. import java.net.URL;
  6. import java.net.URLConnection;
  7. import java.util.List;
  8.  
  9. import com.travel.bean.TrainMess;
  10. import com.travel.util.AddressLngLatExchange;
  11.  
  12. import net.sf.json.JSONArray;
  13. import net.sf.json.JSONObject;
  14.  
  15. public class GetTrainTest {
  16. //解析URL
  17. public static String geturl(String url){
  18. StringBuffer json = new StringBuffer();
  19. try {
  20. URL u = new URL(url);
  21. URLConnection yc = u.openConnection();
  22. //读取返回的数据
  23. BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
  24. String inputline = null;
  25. while((inputline=in.readLine())!=null){
  26. json.append(inputline);
  27. }
  28. in.close();
  29.  
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. }
  33. //将StringBuffer转化为json格式的字符串
  34. String jsonStr=json.toString();
  35. jsonStr=jsonStr.substring(jsonStr.indexOf("{"),jsonStr.length()-1);
  36. return jsonStr;
  37. }
  38. //调用将地址转化为经纬度的方法
  39. public static String getLngLat(String address) {
  40. StringBuffer json = new StringBuffer();
  41. try {
  42. URL u = new URL("http://restapi.amap.com/v3/geocode/geo?address="+address+"&output=JSON&key=7f4ffae4074e8b8e4d147190527a4b72");
  43. URLConnection yc = u.openConnection();
  44. //读取返回的数据
  45. BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
  46. String inputline = null;
  47. while((inputline=in.readLine())!=null){
  48. json.append(inputline);
  49. }
  50. // System.out.println(json);
  51. in.close();
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. }
  55. String jsonStr=json.toString();
  56. JSONObject jsonObject = JSONObject.fromObject(jsonStr);
  57. // System.out.println(jsonObject.getJSONArray("geocodes"));
  58. if(jsonObject.getJSONArray("geocodes").size()>0)
  59. return jsonObject.getJSONArray("geocodes").getJSONObject(0).get("location").toString();
  60. else
  61. return null;
  62. }
  63. @SuppressWarnings("null")
  64. public static List<TrainMess> loadTrainRoute(String startPoint,String endPoint,String date) {
  65. String strUrl="https://train.qunar.com/dict/open/s2s.do?callback=jQuery17203917861486539813_1558231852669"
  66. + "&dptStation="+startPoint+"&arrStation="+endPoint+"&date="+date //日期格式2019-05-20
  67. + "&type=normal&user=neibu&source=site&start=1&num=500&sort=3&_=1558231852892";
  68.  
  69. //调用方法将url转为json格式的字符串
  70. String jsonStr=geturl(strUrl);
  71. JSONObject jsonObject = JSONObject.fromObject(jsonStr);
  72.  
  73. JSONArray jArray=jsonObject.getJSONObject("data").getJSONArray("s2sBeanList");
  74.  
  75. for(int i=0;i<jArray.size();i++) {
  76.  
  77. jsonObject=(jArray.getJSONObject(i));
  78.  
  79. System.out.println("起点:"+startPoint);
  80. System.out.println("起点经纬度:"+getLngLat(startPoint)); //getLngLat 调用将地址转化为经纬度的方法
  81. System.out.println("车次"+jsonObject.get("trainNo").toString());
  82. System.out.println("车站:"+jsonObject.get("dptStationName")+"-"+jsonObject.get("arrStationName"));
  83. System.out.println("时间段:"+jsonObject.get("dptTime")+"-"+jsonObject.get("arrTime"));
  84. System.out.println("一等座的价格:"+jsonObject.getJSONObject("seats").getJSONObject("一等座").get("price"));
  85. System.out.println("一等座的剩余票数:"+jsonObject.getJSONObject("seats").getJSONObject("一等座").get("count"));
  86.  
  87. }
  88. return null;
  89. }
  90. public static void main(String[] args) {
  91. loadTrainRoute("北京", "上海", "2019-06-10");
  92.  
  93. }
  94. }

  六,火车车次的站点信息查询

  1,分析:因为火车车次和改车次的站点数据存储的位置不同,所以车站站点信息要更改URL

  2,刷新网页点击一个车次,展开查看经停

  

  3,先点击XHR,然后点击js,查看到改车次的信息

  

根据URL道理同上,对json数据进行分析,然后爬取下来。

本文章为原创文章,转载请注明,欢迎评论和改正。

java实现根据起点终点和日期查询去哪儿网的火车车次和火车站点信息的更多相关文章

  1. Saiku根据入参日期查询出对应的数据(二十)

    Saiku根据入参日期查询出对应的数据 之前好像有写过一篇博客关于saiku date range的,现在进一步更新啦!!! 这里的日期筛选会更完善一些,需要提供两个参数 开始日期与结束日期(star ...

  2. java和mysql之间的时间日期类型传递

    摘自:http://blog.csdn.net/weinianjie1/article/details/6310770 MySQL(版本:5.1.50)的时间日期类型如下: datetime 8byt ...

  3. JAVA / MySql 编程—— 第三章 高级查询(一)

    1.        修改表: (1)修改表名语法: ALTER TABLE <旧表名> RENAME [ TO ] <新表名>: 注意:其中[TO]为可选参数,使用与否不影响结 ...

  4. (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例)

    (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例) https://pan.baidu.com/s/1L54VuFwCdKVnQGVc8vD1TQnwmj java手册 Ja ...

  5. 如何解决Mybatis 日期查询时后面带.0

    关于如何解决Mybatis 日期查询时后面带.0   MySQL数据库: 直接在MySQL查询语句中解决: SELECT T.ID, T.USERNAME, DATE_FORMAT(t.birthda ...

  6. Java如何保存含有时间的日期到Oracle数据库

    原文:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01 从Oracle ...

  7. SQLServer根据日期查询星期

    --根据日期查询星期SELECT SYSDATETIME();select datepart(weekday,getdate()); SET DATEFIRST 1select '星期'+case w ...

  8. Java知多少(77)日期和时间类

    Java 的日期和时间类位于 java.util 包中.利用日期时间类提供的方法,可以获取当前的日期和时间,创建日期和时间参数,计算和比较时间. Date 类 Date 类是 Java 中的日期时间类 ...

  9. Java对MySQL数据库进行连接、查询和修改(转)

    Java对MySQL数据库进行连接.查询和修改 0. 一般过程: (1) 调用Class.forName()方法加载驱动程序. (2) 调用DriverManager对象的getConnection( ...

随机推荐

  1. sublime text 插件emmet快捷命令

    原文链接:http://www.17yaobai.com/?p=255 语法: 后代:> 缩写:nav>ul>li <nav> <ul> <li> ...

  2. Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

    1.Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理 2. 自定义注解: 使用@interfac ...

  3. Android学习心得(13) --- Android代码混淆(1)

    我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 这一篇我们讲述一下最新的ADT环境下怎样进行Android混淆 在新版本号的ADT创建项目时.混码的文件不再是proguard.cf ...

  4. 新手git: ssh: connect to host localhost port 22: Connection refused

    由于gitlab上要git pull或者git clone,可是每次都出现这个问题.之前偶尔出现这个问题.可是仅仅是偶尔.这是为什么呢?然后就開始搜索网上的解决方式了. 这个问题搜索网上非常多答案.可 ...

  5. SVNserver搭建和使用(二)

    上一篇介绍了VisualSVN Server和TortoiseSVN的下载,安装,汉化.这篇介绍一下怎样使用VisualSVN Server建立版本号库,以及TortoiseSVN的使用. 首先打开V ...

  6. URL重写及ASP.NET路由、Http处理模块、程序等

    这段时间在学习ASP.NET路由.HTTP处理等内容,了解了一些,但又未完全弄懂,似是而非,不管如何,作一总结,供日后借鉴和修改. 一.IIS6和IIS7经典模式和集成模式 在IIS6及IIS7经典模 ...

  7. ubuntu之修改ls显示颜色

    Linux 系统中 ls 文件夹的痛苦我就不说了,为了不伤眼睛,一般 ssh 终端背景都用的黑色,文件夹又是你妈的深蓝色,每次看文件夹都要探头仔细去看.这下彻底解决这个问题.   因为ubuntu下的 ...

  8. Swift3.0中关于日期类的使用指引

    日期的处理在大大小小的iOS项目中都十分常见,随着Swift3.0正式版的即将推出,语法的改变让NSDate以及相关类的使用都与之前略有不同,这里将会对基于Swift3.0版本的NSDate及相关类的 ...

  9. 【联系】—— Beta 分布与二项分布、共轭分布

    1. 伯努利分布与二项分布 伯努利分布:Bern(x|μ)=μx(1−μ)1−x,随机变量 x 取值为 0,1,μ 表示取值为 1 的概率: 二项分布:Bin(m|N,μ)=(Nm)μm(1−μ)N− ...

  10. redis配置文件参数详解

    配置文件参数说明: 1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 daemonize no 2. 当Redis以守护进程方式运行时,Redis默认会把pi ...