java獲取全國到深圳一個月的機票價格資訊
哈哈我又來了。又到週末了,留著鼻涕 本想偷個懶休息一下,可一想到還有小夥伴等著看我的拙文,最終沒有戰勝我的虛榮心O(∩_∩)O,一狠心又在電腦面前坐了12個小時終於完成了一篇我認為稍微有點分析價值的爬蟲了。慣例謝謝留言的小夥伴@Tibetan_Mastiff.
目標網站:
首先還是說一下我的想法:
- 獲取全國到某個城市的最近一個月的機票價格資訊,並分析這一個月的機票價格波動,找出谷點。
實現思路:
- 如果要獲取全國機場城市到我們選定的城市機票資訊,那麼我們首先需要獲取有哪些城市,並將獲取到的城市資訊抓取出來存入資料庫中。有了第一步思路我們接下來就好辦了。
-
抓取城市資訊
老規矩F12獲取介面地址。(注意的一個點,速度一定要慢!!!不然就會和我一樣慘)
-
接下來就是程式碼來獲取並解析資訊了。
/**
*
* @ClassName: QueryCityCode
* @Description: 這裡主要是獲取淘寶機票網中的城市名稱以及城市的cityCode為了後面獲取機票詳情提供基礎資料支援
* @author liangchu
* @date 2018-1-13 上午12:06:59
*
*/
public class QueryCityCode {
private static MongoClient mongo = new MongoClient("127.0.0.1", 27017);
/*
* 根據url獲取返回的城市code
*/
//@SuppressWarnings("finally")
public static String getCodeJson(String url) {
String html = null;
try {
/*
// 建立httpclient例項
CloseableHttpClient httpClient = HttpClients.createDefault();
// 建立httpget例項
HttpGet httpGet = new HttpGet(url);
// 執行http get 請求
CloseableHttpResponse response = null;
response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();// 獲取返回實體
// EntityUtils.toString(entity,"utf-8");//獲取網頁內容,指定編碼
html = EntityUtils.toString(entity, "UTF-8");
response.close();
httpClient.close();
*/
// 如果遇到ssl安全驗證通不過可以用下面的方法
SslTest st = new SslTest();
html = st.getRequest(url,3000);
return html;
} catch (Exception e) {
e.printStackTrace();
}
return html;
}
/*
* 根據返回的字串解析成Json物件
*/
public static JSONObject analysis(String str){
// 根據返回的字串 分析並建立解析規則
int first = str.indexOf("(");
int last = str.lastIndexOf(")");
if(first >=0 && last >0){
String newStr = str.substring(first+1, last);
return JSON.parseObject(newStr);
}
return null;
}
/*
* 解析JSON物件並將JSON物件存入mongodb中
*/
public static void analysisJsonAndSave(JSONObject json){
// 選擇集合存取
DB db = mongo.getDB("taobao");
DBCollection emp = db.getCollection("cityCode2");
// 利用aili的JSON包解析
JSONArray datas =
JSON.parseArray((JSON.parseObject(JSON.parseObject(json.getString("267040"))
.getString("value")).
getString("cityArray")));
// 這裡說明一下為什麼i=1因為第一個json資料不是我們想要的資料所以直接截掉
for(int i=1;i<datas.size();i++){
JSONObject jo = datas.getJSONObject(i);
// 這裡解析出來同樣是一個JSON陣列
JSONArray joTemp = JSON.parseArray(jo.getString("tabdata"));
// 在一層for迴圈
for(int j=0;j<joTemp.size();j++){
JSONObject joj = joTemp.getJSONObject(j);
// 這是dd層的 下面就是我們最終需要的城市資料了
JSONArray jsond = JSON.parseArray(joj.getString("dd"));
for(int m=0;m < jsond.size();m++){
JSONObject jom = jsond.getJSONObject(m);
DBObject obj = new BasicDBObject();
obj.put("cityCode", jom.getString("cityCode"));
obj.put("cityName", jom.getString("cityName"));
obj.put("tce_rule_count", jom.getString("tce_rule_count"));
obj.put("isVister", 0);//0表示未訪問過 為後面獲取機票資訊準備
emp.insert(obj);
obj = null;
}
}
}
}
跨過ssl證照驗證
public class SslTest {
public String getRequest(String url,int timeOut) throws Exception{
URL u = new URL(url);
if("https".equalsIgnoreCase(u.getProtocol())){
SslUtils.ignoreSsl();
}
URLConnection conn = u.openConnection();
//setRequestProperty("User-agent", "Mozilla/5.0");
conn.setRequestProperty("User-Agent", "ozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36");
conn.setRequestProperty("Cookie", "t=49fa205140c4f940349fc1a0efd8da2c; _tb_token_=f33f533398b5d; cookie2=18c83127673f8672abe76a0569b187a1; cna=KL3gEjkBG2kCAXkil7IqSeTH; isg=AlBQD0vJPorWPuKOKsOCNSTNIZ6o3zVqfSNk20ohHKt-hfAv8ikE86a3KXue");
conn.setRequestProperty("Accept-Language","zh-CN,zh;q=0.8");
conn.setConnectTimeout(timeOut);
conn.setReadTimeout(timeOut);
//System.out.println(conn.getInputStream());
return IOUtils.toString(conn.getInputStream());
}
public String postRequest(String urlAddress,String args,int timeOut) throws Exception{
URL url = new URL(urlAddress);
if("https".equalsIgnoreCase(url.getProtocol())){
SslUtils.ignoreSsl();
}
URLConnection u = url.openConnection();
u.setDoInput(true);
u.setDoOutput(true);
u.setConnectTimeout(timeOut);
u.setReadTimeout(timeOut);
OutputStreamWriter osw = new OutputStreamWriter(u.getOutputStream(), "UTF-8");
osw.write(args);
osw.flush();
osw.close();
u.getOutputStream();
return IOUtils.toString(u.getInputStream());
}
第一步準備工作到這裡基本結束了,接下來準備獲取機票資訊。這裡說一下用到的解析工具FastJSON阿里開源的,號稱最快的。(PS作為小白的我好像察覺不出其中的差距哈哈)
由於獲取的json格式包的比較嚴實,剩下的就是漫長的解析之旅了。
package com.xdl.flightInfo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.xdl.cityCode.QueryCityCode;
public class Flight {
private static DB db ;
private static DBCollection emp2 ;
static {
MongoClient mongo = new MongoClient("127.0.0.1", 27017);
// 選擇集合存取
db = mongo.getDB("taobao");
emp2 = db.getCollection("cityCode2");
}
/*
* 根據url獲取機票的資訊 注意 這裡的機票資訊 暫時定義的是當天的最低價
*/
public static void getFlightInfo(String url) {
// 這裡根據url獲取返回的資料
String str = QueryCityCode.getCodeJson(url);
//System.out.println(str);
// 解析返回的字串 並返回json物件
JSONObject jo = QueryCityCode.analysis(str);
// 獲取資訊中我們需要的資料 ()
JSONObject jof = JSON.parseObject(jo.getString("data"));
// 獲取 aircodeNameMap 資訊
JSONObject joAirInfo = JSON
.parseObject(jof.getString("aircodeNameMap"));
// 獲取airportMap 機場資訊
JSONObject joAirPortInfo = JSON
.parseObject(jof.getString("airportMap"));
// 獲取出發地資訊以及目的地資訊
String depCityCode = jof.getString("depCityCode");
String depCityName = jof.getString("depCityName");
String arrCityCode = jof.getString("arrCityCode");
String arrCityName = jof.getString("arrCityName");
// 獲取航班資訊 flight 這裡只獲取最低價 取第一個
JSONObject joFlight = JSON.parseArray(jof.getString("flight"))
.getJSONObject(0);
// 獲取資訊詳情
String airlineCode = joFlight.getString("airlineCode");// 航線資訊
String arrAirport = joFlight.getString("arrAirport");// 目的機場code
String arrTime = joFlight.getString("arrTime");// 到達時間
String depAirport = joFlight.getString("depAirport");// 出發機場code
String depTime = joFlight.getString("depTime");// 出發時間
String flightNo = joFlight.getString("flightNo");// 航班編號
String stop = joFlight.getString("stop");// 是否有中轉 1是0否
// 獲取機票價格資訊 最低價
JSONObject joP = JSON.parseObject(joFlight.getString("cabin"));
String bestPrice = joP.getString("bestPrice");// 最低價格
String cabinNum = joP.getString("cabinNum");// 票數
String bestDiscount = joP.getString("bestDiscount");// 最高的折扣
// 將資訊存入資料庫中
DBCollection emp = db.getCollection("sz-bj");
DBObject obj = new BasicDBObject();
obj.put("airlineCode", airlineCode);
obj.put("arrAirport", arrAirport);
obj.put("arrTime", arrTime);
obj.put("depAirport", depAirport);
obj.put("depTime", depTime);
obj.put("flightNo", flightNo);
obj.put("stop", stop);
obj.put("bestPrice", bestPrice);
obj.put("cabinNum", cabinNum);
obj.put("bestDiscount", bestDiscount);
obj.put("depCityCode", depCityCode);
obj.put("depCityName", depCityName);
obj.put("arrCityCode", arrCityCode);
obj.put("arrCityName", arrCityName);
emp.insert(obj);
}
/*
* deptCity 出發城市
* arrCity 目的城市
* deptTime 出發時間
*/
public static String updatURL(String deptCityName,String arrCityName,String deptTime){
String url = "";
// 這裡需要根據城市的名稱獲取城市的code碼
BasicDBObject queryObjectDept = new BasicDBObject("cityName",deptCityName);
DBObject objDept = emp2.findOne(queryObjectDept);
BasicDBObject queryObjectArr = new BasicDBObject("cityName",arrCityName);
DBObject objArr = emp2.findOne(queryObjectArr);
// 判斷是否存在這樣的城市碼 存在在進行下面的url拼接
if(objDept != null && objArr != null && !("".equals(deptTime))){
String depCityCode = (String) objDept.get("cityCode");
String arrCityCode = (String) objArr.get("cityCode");
url = "https://sjipiao.alitrip.com/searchow/search.htm" +
"?_ksTS=1515770795165_176&callback=jsonp177&" +
"tripType=0&depCity="+depCityCode+"&" +
"depCityName="+deptCityName+"&" +
"arrCity="+arrCityCode+"&arrCityName="+arrCityName+"&depDate="+deptTime;
}
return url;
}
/*
* 轉化日期並將時間加一天
*/
public static String changeTimeFormat(String date){
SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd" );
Calendar c = Calendar.getInstance();
String time = "";
try {
Date d = sdf.parse(date);
c.setTime(d);
c.add(Calendar.DAY_OF_MONTH, 1);
Date tomorrow = c.getTime();
time = sdf.format(tomorrow);
return time;
} catch (Exception e) {
e.printStackTrace();
}
return time;
}
public static void main(String[] args) {
//String url = "https://sjipiao.alitrip.com/searchow/search.htm?_ksTS=1515770795165_176&callback=jsonp177&tripType=0&depCity=SZX&depCityName=%E6%B7%B1%E5%9C%B3&arrCity=BJS&arrCityName=%E5%8C%97%E4%BA%AC&depDate=2018-01-19";
DBCursor dbc = emp2.find();
String deptName = "深圳";
while(dbc.hasNext()){
DBObject obj = dbc.next();
// 過濾 出發地
String arrCityName = (String) obj.get("cityName");
if(!deptName.equals(arrCityName)){
String time = "2018-1-20";
for(int i=0;i<30;i++){
String url = updatURL(deptName,arrCityName,time);
getFlightInfo(url);
System.out.println(deptName+"==>"+arrCityName+time+"機票資訊資料抓取成功");
time = changeTimeFormat(time);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
因為程式碼中的註釋個人感覺也還是算解釋的比較清楚了,所以我下面也就不做過多描述。
注:這裡最好用ip動態代理訪問,防止被封。下次統一補上。
這裡本來還需要對獲取到的機票資訊進行統計分析的,由於時間的緣故留到下次統一放出,有興趣的小夥伴可以擴充套件開放。這裡在提醒各位小夥伴,要麼用ip代理去抓取,要麼就降速抓取。不要把自己當老司機,容易翻車的。好了今天就弄到這裡,如果想要我爬什麼的歡迎留言。同時如果大牛路過的話,能有幸得您點播在下也不勝感激。下期見~~~
相關文章
- 出行平臺採集機票價格資訊
- 淘寶API系列:淘寶/天貓獲取商品歷史價格資訊API
- 爬取市場價格,全國農產品商務資訊公共服務平臺
- 獲取地圖的資訊到input裡地圖
- product.get( 獲取一個產品的資訊 )
- 機票大資料價格預測應用Hopper獲得1600萬美元投資大資料
- 利用PHP獲取一個頁面上的連結資訊PHP
- java 獲取上月、一個月最後一天、週一、週日、本月日期Java
- Java獲取堆疊資訊的3種方法Java
- JavaScript獲取每個月最後一天的日期JavaScript
- 無良網站暗地操控預售機票 網上價格比全價票高網站
- java獲取redis的日誌資訊和動態監控資訊JavaRedis
- 通過Java反射動態獲取資訊Java反射
- Java解析微信獲取手機號資訊Java
- PHP使用strtotime獲取上個月、下個月、本月的日期PHP
- mysql日期 獲取本月第一天 獲取下個月的第一天MySql
- bat之獲取指定幾個月前的月份資訊BAT
- 5 個獲取 Linux 主機資訊的命令Linux
- Java知識點總結(反射-獲取類的資訊)Java反射
- 001量化專案總結 --01獲取實時價格
- Java反射獲取類和物件資訊全解析Java反射物件
- java獲取前端頁面傳送的cookie中的資訊Java前端Cookie
- Windows系統安全獲取重要資訊的方法(一)Windows
- Java獲取精確到秒的時間戳(轉)Java時間戳
- jProcesses:使用Java獲取跨平臺程式的詳細資訊Java
- JAVA根據IP地址獲取詳細的地域資訊(轉)Java
- 獲取.crt證書的資訊
- 使用uwolfer gerrit-rest-java-client獲取Gerrit資訊RESTJavaclient
- Java 獲取PDF數字簽名證照資訊Java
- mac獲取cpu資訊Mac
- 獲取資訊版本1
- Java 獲取Excel分頁座標位置(單元格)JavaExcel
- Java classpath的獲取Java
- python獲取全國地鐵資料Python
- Python:如何用一行程式碼獲取上個月是幾月Python行程
- JavaScript獲取上一個元素JavaScript
- jQuery獲取上一個元素jQuery
- Linux基礎(一):獲取LinuxCPU資訊Linux