1. 程式人生 > >12306余票高效查詢--clojure實現

12306余票高效查詢--clojure實現

quest cookie a記錄 conn ons 資源 查詢 can div

寫在前面

參考 https://www.cnblogs.com/guozili/p/6144561.html
由於各地CDN節點Cache更新存在時差,所以批量查詢全國12306 CDN節點,找到最快的節點獲取購票的必要信息。
該文章主要用戶學習使用clojure並發獲取網絡資源,僅限用於學習。
本篇不涉及具體源碼,只記錄工具、方法。

主要方法

獲取CDN節點

根據摸索,大約有兩種方式:

  1. 直接使用站長工具->ping測試獲取各個地方ping域名,該方式簡單粗暴,但是可能不同時間ping獲取的IP不一致。
  2. 利用DNS協議,直接向全國各地DNS服務請求獲取指定域名的A記錄,該方式可以獲取較全面的CDN節點,實現較為復雜。

請求指定CDN節點

參考文章中作者使用.NET語言,其中細節可能不適用。
找到類似問題:
https://stackoverflow.com/questions/7648872/can-i-override-the-host-header-where-using-javas-httpurlconnection-class
其中提到可以使用apache http client實現,而clj-http就是封裝的apache http client。
所以只需將訪問的url中域名替換為具體的CDN節點IP,然後在請求的Header中帶上Host: xxx.com即可。

批量獲取

多線程並發獲取,目標只是獲取最快成功的。

使用clojure.core.async中的channelalts!!可以滿足我們的需求。
參考示例:
https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj

;; Since go blocks are lightweight processes not bound to threads, we
;; can have LOTS of them! Here we create 1000 go blocks that say hi on
;; 1000 channels. We use alts!! to read them as they're ready.

(let [n 1000
      cs (repeatedly n chan)
      begin (System/currentTimeMillis)]
  (doseq [c cs] (go (>! c "hi")))
  (dotimes [i n]
    (let [[v c] (alts!! cs)]
      (assert (= "hi" v))))
  (println "Read" n "msgs in" (- (System/currentTimeMillis) begin) "ms"))

使用工具

clojure相關庫可以在 https://www.clojure-toolbox.com/ 查詢。

http client

網上查找,發現兩個比較受歡迎的庫:clj-httphttp-kit。後者PR較好,於是先嘗試其。
當涉及cookie相關發現支持並不是很好,於是查看clj-http,發現其是包裝了org.apache.http.client.CookieStore

clj-http地址:https://github.com/dakrone/clj-http

core.async

參考資料:
https://morrxy.github.io/2016/08/02/brave-clojure-core-async/
http://clojuredocs.org/clojure.core.async/alts!!
https://segmentfault.com/a/1190000004314890

總結

通過對core.async的簡單學習,學以致用,實現並發訪問網絡資源。

12306余票高效查詢--clojure實現