はじめに
おはようございます。当ブログにアクセス頂き、ありがとうございます。『臥薪嘗胆』が高校時代の座右の銘だった、たなけんです。
本エントリでは、アプリケーションの実装について記載いたします。
アプリケーションの実装(2)
本日は以下のコードを紹介します。- url構築関数
- xml取得関数
- JSON文字列出力関数
- 意味検索メイン関数
url構築関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn build-url | |
"to build url string with parameters" | |
[host vid q type site] | |
(apply str "http://" host "/v001?vid=" vid "&q=" q "&type=" type "&site=" site)) |
引数に与えられた文字列をurlテンプレートに埋め込みます。
Dictionary.comは意味取得以外にもAPIを提供しているため、
柔軟にurlを構築出来るよう引数を設定しています。
- str関数: 引数を文字列として結合する
xml取得関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn extract-xml | |
"to send request and extract xml part from reply" | |
[url] | |
(:body (try | |
(http-client/get url) | |
(catch java.io.IOException ioe (handle-exception ioe))))) |
引数のurlへhttpリクエストを送信し、レスポンスを受信します。
レスポンスのbody要素をxml文字列として取得します。
- clj-http.client/get関数: 引数のurlにGETメソッドのhttpリクエストを送信
JSON文字列出力関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn generate-json | |
"to return a hashmap including word and entries" | |
[xml-string] | |
;; local function to call xpath/$x safely | |
(letfn [(safety-xpath-call | |
[xpath xml] | |
(try | |
(xpath/$x xpath xml) | |
(catch org.xml.sax.SAXException saxe (handle-exception saxe))))] ; end of letfn safety-xpath-call | |
(let [word (:query (:attrs (first (safety-xpath-call "//dictionary" xml-string)))) | |
entries (let [pos (for [line (safety-xpath-call "//partofspeech" xml-string)] (:pos (:attrs line)))] ; end of let pos | |
; local function to extract mean from //partofspeach/defset/def | |
(letfn [(get-mean | |
[each-pos xml-string] | |
(for [line (safety-xpath-call (str "//partofspeech[@pos=\"" each-pos "\"]/defset/def") xml-string)] (:text line)))] ; end of letfn get-mean | |
; generating entries | |
(for [i pos] | |
(for [j (get-mean i xml-string)] {:pos i :mean j}))))] ; end of let word, entries | |
; get-dictionary-define-json (cont.) | |
(json/generate-string {:word word :entries (flatten entries)})))) |
xml文字列から、単語、品詞、意味を含むJSON文字列を生成します。
例えば下記のようなxmlから
下記のようなJSONを作成します。(改行、エスケープシーケンスは若干異なります)
動作のイメージとしては、forの後の角括弧内のiにリストの各要素が束縛され、角括弧の後のS式を評価した結果のリストを返すといったものです。
1変数の場合は、map関数を用いても同様の結果を得ることが出来ます。
(map #(+ 10 %) '(1 2 3))
forの場合は複数の変数や、階層を持たせる(入れ子のfor文のイメージ)ことができます。
複数の変数を利用すると、Pythonのタプルのような、2要素のhashmapを簡単に作ることができます。
複数変数の例 (for [i '(:a :b :c) j '(1 2 3)] {i j})
結果 ({:a 1} {:a 2} {:a 3} {:b 1} {:b 2} {:b 3} {:c 1} {:c 2} {:c 3})
入れ子の例
(for [i '(:a :b :c)]
(for [j '(1 2 3)] {i j})
)
結果
(
({:a 1} {:a 2} {:a 3})
({:b 1} {:b 2} {:b 3})
({:c 1} {:c 2} {:c 3})
)
今回の作業は以上。最後までお読み頂きありがとうございました。
- letfn特殊形式: スコープ内でのみ利用する関数を束縛
- clj-xpath.core/$x: 第1引数のxpath問い合わせを、第2引数のxmlに対して実行する
- let特殊形式: スコープ内でのみ利用する変数を束縛
- for特殊形式: リスト内包表記
- clj-json.core/generate-string: ClojureオブジェクトからJSON文字列を生成する
例えば下記のようなxmlから
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8" ?> | |
<dictionary query="test" totalresults="1"> | |
<entry source="pdict" id="4162883"> | |
<display_form ><![CDATA[test]]></display_form> | |
<pron><![CDATA[[test]]]></pron> | |
<partofspeech pos="noun"> | |
<defset> | |
<def charcnt="68" defno="1"><![CDATA[the means used to determine the quality, content, etc., of something]]></def> | |
<def charcnt="42" defno="2"><![CDATA[examination to evaluate a student or class]]></def> | |
</defset> | |
</partofspeech> | |
<partofspeech pos="verb (used with object)"> | |
<defset> | |
<def charcnt="20" defno="3"><![CDATA[to subject to a test]]></def> | |
</defset> | |
</partofspeech> | |
</entry> | |
</dictionary> |
下記のようなJSONを作成します。(改行、エスケープシーケンスは若干異なります)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"word":"test", | |
"entries":[ | |
{"pos":"noun", | |
"mean":"the means used to determine the quality, content, etc., of something"}, | |
{"pos":"noun", | |
"mean":"examination to evaluate a student or class"}, | |
{"pos":"verb (used with object)", | |
"mean":"to subject to a test"} | |
] | |
} |
追記: リスト内包表記について
例えば、(for [i '(1 2 3)] (+ 10 i))を評価すると、(11 12 13)が結果として返されます。動作のイメージとしては、forの後の角括弧内のiにリストの各要素が束縛され、角括弧の後のS式を評価した結果のリストを返すといったものです。
1変数の場合は、map関数を用いても同様の結果を得ることが出来ます。
(map #(+ 10 %) '(1 2 3))
forの場合は複数の変数や、階層を持たせる(入れ子のfor文のイメージ)ことができます。
複数の変数を利用すると、Pythonのタプルのような、2要素のhashmapを簡単に作ることができます。
複数変数の例 (for [i '(:a :b :c) j '(1 2 3)] {i j})
結果 ({:a 1} {:a 2} {:a 3} {:b 1} {:b 2} {:b 3} {:c 1} {:c 2} {:c 3})
入れ子の例
(for [i '(:a :b :c)]
(for [j '(1 2 3)] {i j})
)
結果
(
({:a 1} {:a 2} {:a 3})
({:b 1} {:b 2} {:b 3})
({:c 1} {:c 2} {:c 3})
)
今回の作業は以上。最後までお読み頂きありがとうございました。
たなけん (作業時間45分)
0 件のコメント:
コメントを投稿