目錄
前言
一、數據源介紹
1、目標網站
2、頁面渲染結構
二、XxlCrawler信息獲取
1、創建XxlCrawler對象
2、定義PageVo對象
3、直接PageVO解析
4、自定義解析
總結
前言
????????長距離旅行或者出差,飛機一定是出行的必備方式。對于旅行達人或者出差人員而言,登機牌也是隨身之物。還記得我第一次坐飛機出行的時候,相當激動,第一次在飛機上看祖國的大好河山,有一種豪邁的既視感。有點扯遠了,不知道大家出行的時候有沒有認真的研究一下登機牌。登機牌上都有什么信息呢。這里從網上貼一張別人的登機牌,我們來看一下。
????????在上面這張機票包含了一些重要的信息,以大木航為例,承運人:MU,航班:MU。這個MU表示的是什么呢?MU是航空公司的二字碼,官方名字IATA,國際航空運輸協會?(International Air Transport Association,IATA)?是一個由世界各國航空公司所組成的大型國際組織,其前身是1919年在海牙成立并在二戰時解體的國際航空業務協會。MU是這個協會給中國東方航空的一個唯一身份碼。
????????就像我們的身份證一樣,與IATA碼有一點區別的是ICAO碼。相對于IATA碼,ICAO一般老百姓接觸的比較少。因為ICAO是國際民航組織(International Civil Aviation Organization,縮寫為ICAO,是協調世界各國政府在民用航空領域內各種經濟和法律事務、制定航空技術國際標準的重要組織。ICAO主要用于安全保衛或空防安全活動,實施國際民航組織通信、導航、監視/空中交通管制系統,簡化手續、統計、技術合作、培訓等。簡單一點說,就是航空管控、導航方面,一般通用的是ICAO碼。而MU對應的ICAO碼是CES。這個信息可以從東航官網上可以查到。
?????????那么全球有哪些航空公司,他們的ICAO碼又是什么呢?本文通過從航班追蹤網站flightaware,獲取實時的航班對應的航空公司信息。本文介紹一種基于XxlCrawler的信息抓取技術,自動從網站上獲取全球的航空公司信息,同時分享兩種不同的數據解析方式,最后將獲取的信息保存為Excel,通過本文不僅可以獲取ICAO的數據,同時掌握兩種數據解決方法。如果您當前對數據處理有需求,可以看看本文是否有幫助。
一、數據源介紹
????????當然,想獲取ICAO數據不一定要從飛行跟蹤網站上獲取,這里只提供一種數據源。某度和某哥都可以拿到完整的ICAO數據。本節將對飛行網站上的數據進行簡單說明,為下一步我們來進行數據抓取奠定基礎。
1、目標網站
????????在個人瀏覽器中打開目標網站的地址,查看實時航班。然后點擊航空公司列表,可以看到下面的頁面:
????????在上面的頁面中其實就包含了我們需要的航空公司ICAO碼,以及對應航空公司的英文名稱。比如CES?China Eastern "China Eastern" (China) 就表示中國東方航空。
2、頁面渲染結構
????????在獲取了網站展示頁面之后,我們可以來看看具體的數據,打開網頁的調試功能,可以看到如下的信息:
????????請注意圖中紅色框標記的地方,從最頂層的pageContainer,到下級prettyTable,然后是表格中的tbody再到tr,最后是td沒一行。通過遍歷td即是我們需要的數據。因此我們要解析的就是獲取tr的集合,然后遍歷下面的td,第一個td的文本值是航班數,第二個就是ICAO代碼,第三個是航空公司的英文名稱。?
? ? ? ? 上面的知識一定要了解,這是下面章節的前提條件。
二、XxlCrawler信息獲取
????????在了解了信息渲染的對象和網頁層次之后,我們就可以采用熟悉的XxlCrawler來進行全球航空公司列表及ICAO代碼獲取實戰。本節主要講述如何進行代碼開發,同時講述兩種頁面解析模式,實際生產中,可以按照自己的需要進行靈活處理。
1、創建XxlCrawler對象
????????在進行信息抓取前,需要定義抓取對象,這里分享其代碼:
private static final String GET_ICAO_URL = "https://zh.flightaware.com/live/fleet/";private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36";
// 構造爬蟲
XxlCrawler crawler = new XxlCrawler.Builder().setUrls(GET_ICAO_URL)// 允許擴散爬取,將會以現有URL為起點擴散爬取整站,這里爬一個頁面,不允許擴散.setAllowSpread(false).setThreadCount(3).setPauseMillis(2000).setUserAgent(USER_AGENT)//設置user_agent.setIfPost(false).setFailRetryCount(3)// 重試三次.setPageParser(new PageParser<PageVo>() {@Overridepublic void parse(Document html, Element pageVoElement, PageVo pageVo) {// 解析封裝 PageVo 對象// String pageUrl = html.baseUri();//第一種方式:使用自助解析,實現更加靈活的模式// printElementVo(pageVoElement);//第二種方式:使用pageVO的方式解析printVo(pageVo);// System.out.println(pageUrl + ":" + pageVo.toString());}
}).build();
? ????????需要說明的是,這里只需要對目標頁面爬取一次,因此不需要進行擴散抓起,否則速度會很慢,相當于自我發現地址,同時還要實現抓取。這里通過.setAllowSpread(false) 就可以防止這種操作。
2、定義PageVo對象
????????pageVo對象用于網頁數據的解析,這里我們可以將數據過濾到tbody,然后剩下的解析到屬性中,這是一種防范,另一種方法是通過自定義解析。不管用那種解析,都需要對數據進行第一次解析,也就是pageVO的定義。下面來看一下PageVo對象怎么定義:
@PageSelect(cssQuery = ".pageContainer .prettyTable >tbody")
@Data
public static class PageVo {/*** 實時航班數*/@PageFieldSelect(cssQuery = ">tr >td:eq(0)")private List<String> flightsNum;/*** ICAO代號*/@PageFieldSelect(cssQuery = ">tr >td:eq(1)")private List<String> icaoCode;/*** 航空公司(英文)*/@PageFieldSelect(cssQuery = ">tr >td:eq(2)")private List<String> airline;
}
????????這里為了解析方便,同時在解析時,自動創建三個數組,分別用來保存第一個到最后一個td中的值。前文提過,三個值分別代表航班數、icao代碼、航空公司英文名稱。使用這種直接解析成數組的方式呢,優缺點都有。優點就是不需要再進行第二次解析,缺點就是,如果有多個td就得定義多個數組去接收,比較繁瑣。這里暫時不提自定義解析,先把這種固定模板的解析模式講解完。
3、直接PageVO解析
????????通過定義PageVO對象,同時給VO對象配置@PageFieldSelect(cssQuery = ">tr >td:eq(1)"),就可以實現屬性的自助解析。這里新增一個方法,把解析之后的數據打印輸出,方便觀察調試結果。
protected void printVo(PageVo pageVo) {System.out.println(pageVo);System.out.println(pageVo.getFlightsNum().size());System.out.println(pageVo.getFlightsNum());System.out.println(pageVo.getAirline().size());System.out.println(pageVo.getAirline());System.out.println(pageVo.getIcaoCode().size());System.out.println(pageVo.getIcaoCode());for (int i = 0; i < pageVo.getFlightsNum().size(); i++) {System.out.println("航班數:" + pageVo.getFlightsNum().get(i) + "\t ICAO代碼:" + pageVo.getIcaoCode().get(i)+ "\t 航空英文名稱:" + pageVo.getAirline().get(i));}
}
????????運行以上代碼可以看到以下結果:
????????通過觀察控制臺輸出可以看到,相關信息已經被成功爬取了。?
4、自定義解析
????????如果要解析的網頁信息量不是很大,以表格為例,其單元格也不是很多,可以使用上面的這種注解式的解析模式,但是如果單元格比較多,我們在pageVo中需要定義多個list,這樣也是比較麻煩的。這里分享一種自定義解析模式,自己根據xpath去解析網頁,獲取數據。
????????與注解解析模式原理差不多,自定義解析是根據網頁的變化,自動根據網頁結構解析內容,保存到相關集合中。
protected void printElementVo(Element pageVoElement) {System.out.println(pageVoElement);System.out.println(pageVoElement.childrenSize());List<AirlineVo> airlineList = new ArrayList<TestZhFlightawareCase.AirlineVo>();for (int i = 0; i < pageVoElement.childrenSize(); i++) {Element childElement = pageVoElement.child(i);// System.out.println(childElement.childrenSize());int childrenSize = childElement.childrenSize();System.out.println(childrenSize);String flightsNum = childElement.child(0).text();String icao = childElement.child(1).text();String airline = childElement.child(2).text();System.out.println("航班數:" + flightsNum + "\t ICAO代碼:" + icao + "\t 航空英文名稱:" + airline);airlineList.add(new AirlineVo(flightsNum, icao, airline));}// excel工具包ExcelUtil<AirlineVo> util = new ExcelUtil<AirlineVo>(AirlineVo.class);util.exportExcel(airlineList, "全球航空公司ICAO代碼表-20240514");
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AirlineVo {@Excel(name = "航班數")private String flightsNum;@Excel(name = "icao代碼")private String icaoCode;@Excel(name = "航空公司英文名稱")private String airlineEn;
}
????????代碼的最后,我們實現了將抓取的信息列表保存到excel表格中。當然,您也可以根據需要,把數據保存到業務數據庫中,這里暫且不表。
????????在數據解析之前,可以先拿到抓取的tbody信息,然后再來解析到具體的數據存儲對象中。最后是解析的數據打印信息:
航班數:413 ICAO代碼:AAL 航空英文名稱:American Airlines "American"
航班數:409 ICAO代碼:DAL 航空英文名稱:Delta "Delta"
航班數:387 ICAO代碼:UAL 航空英文名稱:United "United"
航班數:309 ICAO代碼:SWA 航空英文名稱:Southwest "Southwest" (Dallas, TX)
航班數:290 ICAO代碼:CSN 航空英文名稱:China Southern Airlines "China Southern" (China)
航班數:272 ICAO代碼:RYR 航空英文名稱:Ryanair "Ryanair" (Ireland)
航班數:236 ICAO代碼:CES 航空英文名稱:China Eastern "China Eastern" (China)
航班數:213 ICAO代碼:CCA 航空英文名稱:Air China "Air China" (China)
航班數:156 ICAO代碼:IGO 航空英文名稱:IndiGO "IFLY" (New Delhi)
????????最后到工程文件中看一下是否成功生成了excel文件,在工程目錄下有一個download目錄,在這個目錄中可以看到已經生成了對應的excel文件。
????????打開Excel看看是不是我們想要的數據,?
? ? ? ? 通過上圖可以看到,與我們的預期是一致的,已經成功的全球航空公司的名稱、航班數、ICAO代碼都保存到了Excel中。?
總結
????????以上就是本文的主要內容,本文介紹一種基于XxlCrawler的信息抓取技術,自動從網站上獲取全球的航空公司信息,同時分享兩種不同的數據解析方式,最后將獲取的信息保存為Excel,通過本文不僅可以獲取ICAO的數據,同時掌握兩種數據解決方法。如果您當前對數據處理有需求,可以看看本文是否有幫助。全球航空公司ICAO數據可以在評論區留言獲取哦。以后有機會可以把航空公司跟國家等關聯起來,就可以知道哪個是航空大國。行文倉促,定有不足之處,歡迎各位朋友在評論區批評指正,萬分感謝。