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

一,分析

  之前所用的直接通过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类型返回

public static String geturl(String url){
StringBuffer json = new StringBuffer();
try {
URL u = new URL(url);
URLConnection yc = u.openConnection();
//读取返回的数据
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
String inputline = null;
while((inputline=in.readLine())!=null){
json.append(inputline);
}
in.close(); } catch (Exception e) {
e.printStackTrace();
}
//将StringBuffer转化为json格式的字符串
String jsonStr=json.toString();
          //将不规范的字符串形式的json数据规范化
jsonStr=jsonStr.substring(jsonStr.indexOf("{"),jsonStr.length()-1);
return jsonStr;
}

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

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

  3,查询火车票的代码

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

 

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

 

五,完整代码

package test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.List; import com.travel.bean.TrainMess;
import com.travel.util.AddressLngLatExchange; import net.sf.json.JSONArray;
import net.sf.json.JSONObject; public class GetTrainTest {
//解析URL
public static String geturl(String url){
StringBuffer json = new StringBuffer();
try {
URL u = new URL(url);
URLConnection yc = u.openConnection();
//读取返回的数据
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
String inputline = null;
while((inputline=in.readLine())!=null){
json.append(inputline);
}
in.close(); } catch (Exception e) {
e.printStackTrace();
}
//将StringBuffer转化为json格式的字符串
String jsonStr=json.toString();
jsonStr=jsonStr.substring(jsonStr.indexOf("{"),jsonStr.length()-1);
return jsonStr;
}
//调用将地址转化为经纬度的方法
public static String getLngLat(String address) {
StringBuffer json = new StringBuffer();
try {
URL u = new URL("http://restapi.amap.com/v3/geocode/geo?address="+address+"&output=JSON&key=7f4ffae4074e8b8e4d147190527a4b72");
URLConnection yc = u.openConnection();
//读取返回的数据
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(),"UTF-8"));
String inputline = null;
while((inputline=in.readLine())!=null){
json.append(inputline);
}
// System.out.println(json);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
String jsonStr=json.toString();
JSONObject jsonObject = JSONObject.fromObject(jsonStr);
// System.out.println(jsonObject.getJSONArray("geocodes"));
if(jsonObject.getJSONArray("geocodes").size()>0)
return jsonObject.getJSONArray("geocodes").getJSONObject(0).get("location").toString();
else
return null;
}
@SuppressWarnings("null")
public static List<TrainMess> loadTrainRoute(String startPoint,String endPoint,String date) {
String strUrl="https://train.qunar.com/dict/open/s2s.do?callback=jQuery17203917861486539813_1558231852669"
+ "&dptStation="+startPoint+"&arrStation="+endPoint+"&date="+date //日期格式2019-05-20
+ "&type=normal&user=neibu&source=site&start=1&num=500&sort=3&_=1558231852892"; //调用方法将url转为json格式的字符串
String jsonStr=geturl(strUrl);
JSONObject jsonObject = JSONObject.fromObject(jsonStr); JSONArray jArray=jsonObject.getJSONObject("data").getJSONArray("s2sBeanList"); for(int i=0;i<jArray.size();i++) { jsonObject=(jArray.getJSONObject(i)); System.out.println("起点:"+startPoint);
System.out.println("起点经纬度:"+getLngLat(startPoint)); //getLngLat 调用将地址转化为经纬度的方法
System.out.println("车次"+jsonObject.get("trainNo").toString());
System.out.println("车站:"+jsonObject.get("dptStationName")+"-"+jsonObject.get("arrStationName"));
System.out.println("时间段:"+jsonObject.get("dptTime")+"-"+jsonObject.get("arrTime"));
System.out.println("一等座的价格:"+jsonObject.getJSONObject("seats").getJSONObject("一等座").get("price"));
System.out.println("一等座的剩余票数:"+jsonObject.getJSONObject("seats").getJSONObject("一等座").get("count")); }
return null;
}
public static void main(String[] args) {
loadTrainRoute("北京", "上海", "2019-06-10"); }
}

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

  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. Spring MVC-页面重定向示例(转载实践)

    以下内容翻译自:https://www.tutorialspoint.com/springmvc/springmvc_page_redirection.htm 说明:示例基于Spring MVC 4. ...

  2. axios 全攻略之基本介绍与使用(GET 与 POST)

    axios axios 是一个基于 Promise 的 HTTP 客户端,专门为浏览器和 node.js 服务 Vue 2.0 官方推荐使用 axios 来代替原来的 Vue request,所以这里 ...

  3. Python:利用 selenium 库抓取动态网页示例

    前言 在抓取常规的静态网页时,我们直接请求对应的 url 就可以获取到完整的 HTML 页面,但是对于动态页面,网页显示的内容往往是通过 ajax 动态去生成的,所以如果是用 urllib.reque ...

  4. CodeForces - 344A Magnets (模拟题)

    CodeForces - 344A id=46664" style="color:blue; text-decoration:none">Magnets Time ...

  5. BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree+划分树

    题目大意: 给定n个点m条边的无向图.求问当图中仅仅有[编号在[l,r]区间内]的边存在时图中的联通块个数 强制在线 注意联通块是指联通了就是同一块,不是Tarjan求的那种块 看到这题的那一刻我就想 ...

  6. Ralink5350开发环境搭建

    一.安装虚拟机(Oracle VM VirtualBox  或 VMware Workstation) 二.在虚拟机中安装linux操作系统(当前使用的是Ubuntu1204桌面版) 三.配置linu ...

  7. Linux学习笔记——例说makefile 索引博文

    0.前言     从学习C语言開始就慢慢開始接触makefile.查阅了非常多的makefile的资料但总感觉没有真正掌握makefile,假设自己动手写一个makefile总认为非常吃力.所以特意借 ...

  8. 【待解决】使用JUnit时报错java.lang

    编写selenium自动化代码,代码逻辑应该都没有错,运行时老是报如下错误 java.lang.NoClassDefFoundError: org/json/JSONException 解决办法:导入 ...

  9. Android利用Intent与其它应用交互

    前言: 上一篇博客给大家聊了Intent的定义.分类.属性和功能,相信大家对于Intent在Android中的作用已经清楚,这一篇博客将会给大家聊Intent的使用方法. Android系统的一个重要 ...

  10. Python 3.x 判断 dict 是否包含某个键

    Python 3.x不再支持 has_key() 函数,而被__contains__('key')所替代,会返回bool,可以用其做判断. 代码示例: >>> user = 'dad ...