Enliveをさわってみたのでメモ
Enliveをさわってみたのでメモ。
導入
- project.clj の :dependencies に下記を追加
[enlive "1.1.5"]
REPLから試用
user=> (use 'net.cgrand.enlive-html) nil user=> (dir net.cgrand.enlive-html) (中略) html html-content html-resource html-snippet (中略) select (以下略)
html関数
user=> (doc html) ------------------------- net.cgrand.enlive-html/html ([& nodes-specs]) Allows to define inline fragments with a hiccup-like syntax. nil user=> (html [:div {:id "divHoge"} [:input {:id "textHoge" :type "text"}]]) ({:tag :div, :attrs {:id "divHoge"}, :content ({:tag :input, :attrs {:type "text", :id "textHoge"}, :content ()})})
html-resource関数
user=> (doc html-resource) ------------------------- net.cgrand.enlive-html/html-resource ([resource] [resource options]) Loads an HTML resource, returns a seq of nodes. nil user=> ; clojure.java.io の reader 関数を用いて HTML resource を取得して渡してみる user=> (use 'clojure.java.io) nil user=> (doc reader) ------------------------- clojure.java.io/reader ([x & opts]) Attempts to coerce its argument into an open java.io.Read Default implementations always return a java.io.Buffered Default implementations are provided for Reader, Buffere InputStream, File, URI, URL, Socket, byte arrays, charac and String. If argument is a String, it tries to resolve it first as as a local file name. URIs with a 'file' protocol are c local file names. Should be used inside with-open to ensure the Reader is closed. nil user=> (reader "http://google.com") #<BufferedReader java.io.BufferedReader@1969526c> user=> (html-resource (reader "http://google.com")) ({:type :dtd, :data ["html" nil nil]} {:tag :html, :attrs { (以下略)
select関数
user=> (doc select) ------------------------- net.cgrand.enlive-html/select ([node-or-nodes selector]) Returns the seq of nodes or fragments matched by the specified selector. nil user=> (select #_=> (html [:div {:id "divHoge"} [:input {:id "textHoge" :type "text"}]]) #_=> [:input]) ({:tag :input, :attrs {:type "text", :id "textHoge"}, :content ()}) user=> (select #_=> (html [:div {:id "divHoge"} [:input {:id "textHoge" :type "text"}] [:input {:id "textToge" :type "check"}]]) #_=> [:input#textToge]) ({:tag :input, :attrs {:type "check", :id "textToge"}, :content ()}) user=> (select #_=> (html [:html [:div {:id "divHoge"} [:input {:id "textHoge" :type "text"}]] [:input {:id "textToge" :type "check"}]]) #_=> [:div :input]) ({:tag :input, :attrs {:type "text", :id "textHoge"}, :content ()}) user=> (select #_=> (html [:html [:div {:id "divHoge"} [:input {:id "textHoge" :type "text"}]] [:input {:id "textToge" :type "check"}]]) #_=> #{[:div :input] [:#textToge]}) ({:tag :input, :attrs {:type "text", :id "textHoge"}, :content ()} {:tag :input, :attrs {:type "check", :id "textToge"}, :content ()})
実用
強引感が半端ないが、Yahoo!ファイナンスから板気配を取得するコードを書いてみた。
(use 'net.cgrand.enlive-html) (use 'clojure.java.io) (defn kehai-url [meigara-code] (str "http://stocks.finance.yahoo.co.jp/stocks/detail/?code=" meigara-code "." "T")) (defn kehai [meigara-code] (let [[title-row row1 row2] (select (html-resource (reader (kehai-url meigara-code))) [:.main2colL :table :tr])] {:meigara-code meigara-code :uri-kehai (first (:content (first (select row1 [[:td (nth-of-type 1)]])))) :uri-kehai-kabuka (first (:content (first (select row1 [[:td (nth-of-type 3)] :strong])))) :kai-kehai (first (:content (first (select row2 [[:td (nth-of-type 5)]])))) :kai-kehai-kabuka (first (:content (first (select row2 [[:td (nth-of-type 3)] :strong]))))}))
user=> (map kehai [4689 4755]) ({:meigara-code 4689, :uri-kehai "---", :uri-kehai-kabuka "---", :kai-kehai "---", :kai-kehai-kabuka "---"} {:meigara-code 4755, :uri-kehai "---", :uri-kehai-kabuka "---", :kai-kehai "---", :kai-kehai-kabuka "---"})