ラベル Clojure の投稿を表示しています。 すべての投稿を表示
ラベル Clojure の投稿を表示しています。 すべての投稿を表示

2013年12月18日水曜日

[Clojure][Ruby]RougeでSelenium WebDriverを使う

Ruby + Clojure = Rouge
Selenium WebDriverを使ってGoogle検索してみた。

Rubyは最新版を使用した。
$ ruby -v
ruby 2.0.0p353 (2013-11-22 revision 43784) [i686-linux]

Rougeのインストールと起動

gemでインストールできる。簡単だ。
$ gem install rouge-lang
REPLを起動するには rougeコマンドを使う。
$ rouge
Rouge 0.0.15
user=>

ついついprintlnとやってしまいそうになるが、putsでhello。

user=> (puts "hello, Rouge!")
hello, Rouge!
nil
user=> ^Dで終了

Selenium WebDriverを使ってみる

gemでselenium-webdriverをインストールしておく。
$ gem install selenium-webdriver

Rubyのコード

require "selenium-webdriver"

driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://google.com"

element = driver.find_element(:name, 'q')
element.send_keys "Clojure Ruby Rouge"
element.submit

puts driver.title

driver.quit


Rougeのコード

(require "selenium-webdriver")

(def driver (Selenium.WebDriver/for :firefox))

(-> driver
  (.navigate)
  (.to "http://www.google.com/"))

(def element (.find_element driver :name "q"))

(.send_keys element "Clojure Ruby Rouge")
(.submit element)

(puts (.title driver))

;; (.quit driver) ;; ブラウザを終了させないようにコメントアウト


Rougeで実行

拡張子はrgのようだ。
上記のコードはgoogle.rgとした。

rougeコマンドに渡せば良い。
最初分からずに(load-file "google.rg")とやってみたが、
load-fileは定義されていなった。
https://github.com/rouge-lang/rouge/blob/master/lib/boot.rg
https://github.com/rouge-lang/rouge/blob/master/lib/rouge.rb
を見ても、load〜は定義されていないみたい。

$ rouge google.rg
Google

Firefoxが立ち上がり、「Clojure Ruby Rouge」を検索する。

感想

Rougeは起動が早くて良い。
Emacs ciderで接続できない。これはかなり残念。
https://github.com/clojure/tools.nrepl をrougeに移植すれば良いのかな?
でも大変そう。
Rubyの豊富なライブラリが利用できるのは便利だ。
エラーが起きても、該当行が表示されないので、デバッグが大変だ。

参考


2013年12月16日月曜日

[Clojure][Emacs]EmacsのCiderを起動するLeiningen pluginを作ってみた

$ lein cider
とすると、REPLを起動して、Emacsのciderコマンドを実行して、Emacs側でもREPLを起動するLeiningen pluginを作ってみた。

私はDebianを常用しており、Clojureでの開発には、REPLとして、Emacs上で動作するCiderを使用している。Emacsと同時に複数のターミナルを開いて、Emacsとターミナルの間を行き来している。
lein replは、ターミナルで起動して、Emacsからはciderコマンドで接続していた。
EmacsとターミナルのREPLを同時に使っていることも多い。
毎回ターミナルでlein replした後に、Emacsからciderで再接続するのが面倒なので、このpluginを作ってみた。

便利かなと思って作ってみたものの、cider-jack-inコマンドがあることを考えると、機能的には微妙なプラグインだな...

使い方

~/.lein/profiles.clj に lein-cider の設定を追加する。

{:user {:plugins [[lein-cider "0.1.0-SNAPSHOT"]]}}

Emacsをサーバーとして起動しておく(server-start関数を使用)。
プロジェクトのディレクトリで、
$ lein cider
を実行すると、Emacs上でciderコマンドが実行されて、REPLを起動する。

ソース

ソースはこちら
標準のREPL(lein repl)を起動後に、emacsclientコマンド経由で ELispのcider関数を呼び出している。
REPLが完全に起動した後に、Emacs側でcider関数を実行しないと、
IllegalAccessError pp does not exist clojure.core/refer
というエラーがでてしまうので、手っ取り早く、もう完全に起動した頃かなーという3秒後に、emacsclientコマンドを実行するようにした。

(defn server [project cfg headless?]
  (let [port (apply original-server-func [project cfg headless?])
        host (:host cfg)]
    (future
      (Thread/sleep leiningen.cider/WAIT_TIME) ; ←◆コレ
      (call-cider host port))
    port))


うーむ。まったくもって、行き当たりばったりな実装だ。

Emacsサーバー

こちらを見ると、
Note that since Emacs 23 this is the preferred way to use Emacs in daemon mode. (start-server) is now mostly deprecated.
というコメントがあった。
ほー。今はdaemon modeで使う方が良いようだ。

参考

2013年12月14日土曜日

[Clojure]lein-tryで外部ライブラリを使う

外部のClojureライブラリを使うには、project.cljのdependenciesに記述しなければならない。ちょっとお試しでライブラリを使用したい場合、これは面倒くさかった。

lein-tryプラグインを使うと、project.cljはそのままで、使用したい外部ライブラリを引数に渡すだけで、試すことができるようになる。

準備

以下のように~/.lein/profiles.cljを編集して、lein-tryプラグインを使えるようにする。
{:user {:plugins [[lein-try "0.4.1"]]}}

試してみる

satoshi@debian:~/workspace/clojure$ lein deps
Retrieving lein-try/lein-try/0.4.1/lein-try-0.4.1.pom from clojars
Retrieving lein-try/lein-try/0.4.1/lein-try-0.4.1.jar from clojars
Couldn't find project.clj, which is needed for deps

プラグインを読み込んだことを確認。

clj-timeの最新版を試してみる。

satoshi@debian:~/workspace/clojure$ lein try clj-time
Retrieving clj-time/clj-time/0.6.0/clj-time-0.6.0.pom from clojars ← clj-timeをロードしている
Retrieving joda-time/joda-time/2.2/joda-time-2.2.pom from central
Retrieving clj-time/clj-time/0.6.0/clj-time-0.6.0.jar from clojars
Retrieving joda-time/joda-time/2.2/joda-time-2.2.jar from central
nREPL server started on port 51459 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> (require '[clj-time.core :as t])
nil
user=> t/date-time
#<core$date_time clj_time.core$date_time@6849b9>
user=> (t/date-time 2013 12 13)
#<DateTime 2013-12-13T00:00:00.000Z>
user=>

バージョン番号の指定もできる。

satoshi@debian:~/workspace/clojure$ lein try clj-time "0.5.1"
Retrieving clj-time/clj-time/0.5.1/clj-time-0.5.1.pom from clojars
Retrieving clj-time/clj-time/0.5.1/clj-time-0.5.1.jar from clojars
nREPL server started on port 49481 on host 127.0.0.1
REPL-y 0.3.0
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=>

今まで、いちいちproject.cljにライブラリの設定を書いてからlein replしていたので、これはお手軽で、とても便利。

参考


2013年12月13日金曜日

[Clojure]マルコフ連鎖に基づく文生成

先日購入した、はじめてのAIプログラミング C言語で作る人工知能と人工無能を読んでいる。
文生成が面白そうだったので、Clojureで書いてみた。

処理内容としては、以下の通り。
(1)形態素解析ライブラリKuromojiを使用して、元ネタとなる文章を形態素解析する。
(2)その形態素の連鎖をモデル化して、マルコフ連鎖に基づく文生成をする。

プログラム

(ns ai.sentence
  (:import (org.atilika.kuromoji Token Tokenizer)))

(def ^:dynamic *words*
  "マルコフ連鎖のモデル
次のキーと値のマップ
キー: 形態素
値: キーを次の形態素、値を出現数とするマップ"
  (ref {}))

(defn tokenize [text]
  (let [tokenizer (. (Tokenizer/builder) build)]
    (. tokenizer tokenize text)))

(defn token-word [token]
  (.trim (.getSurfaceForm token)))

(defn inc-map-value [m k]
  (if (get m k)
    (update-in m [k] inc)
    (assoc m k 1)))

(defn register-word [m word1 word2]
  (let [word2-map (get m word1 {})]
    (assoc m word1 (inc-map-value word2-map word2))))

(defn load-text [file-name]
  (let [text (slurp file-name)
        tokens (tokenize text)]
    (reduce (fn [m [token1 token2]]
              (let [word1 (token-word token1)
                    word2 (token-word token2)]
                (if (or (= word1 ""))
                  m
                  (register-word m word1 word2))))
            {} (partition 2 1 tokens))))

(defn select-word [word-map]
  (first (rand-nth (seq word-map))))

(defn select-next-word [word-map word]
  (let [next-word-map (get word-map word)]
    (select-word next-word-map)))

(defn create-sentence [word-map word]
  (loop [sentence ""
         word word]
;    (println (str "*" word))
    (if word
      (if (or (= word "。") (= word "?") )
        sentence
        (recur (str sentence word) (select-next-word word-map word)))
      sentence)))

(defn init []
  (dosync
   (ref-set *words*
            (load-text "/home/satoshi/work/sample.txt"))))


サンプルの文章(sample.txt)

夏目漱石 「我輩は猫である」(青空文庫より)の最初の部分を使用した。

吾輩は猫である。
名前はまだ無い。
どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。
この書生というのは時々我々を捕えて煮て食うという話である。
しかしその当時は何という考もなかったから別段恐しいとも思わなかった。
ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。
掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。
この時妙なものだと思った感じが今でも残っている。
第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。
その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。
のみならず顔の真中があまりに突起している。
そうしてその穴の中から時々ぷうぷうと煙を吹く。
どうも咽せぽくて実に弱った。
これが人間の飲む煙草というものである事はようやくこの頃知った。

実行結果

user> (in-ns 'ai.sentence)
#<Namespace ai.sentence>
ai.sentence> (init)
{"だ" {"と" 1, "。" 2}, "ニャーニャー" {"泣い" 1}, "一" {"度" 1, "毛" 1}, "何だか" {"フワフワ" 1}, "所" {"で" 1}, "ここ" {"で" 1}, "名前" {"は" 1}, "あっ" {"た" 2}, "
〜略〜
ai.sentence> (create-sentence @*words* "何")
"何というの飲む煙草という人間というのは何でも残って食うという考もだいぶ逢った"
ai.sentence> (create-sentence @*words* "猫")
"猫でニャーニャー泣いてまるで薬缶だと思った時何だかフワフワして書生のがない"
ai.sentence> (create-sentence @*words* "煙草")
"煙草というものを吹く"

# まさに、人工無能...

形態素を使っているので、n-gramを使用した場合より、まともな文章になっているが、文法に従った文生成をしていないため、意味不明な文になっている。
また、本来は、ある形態素の次の形態素を決めるときには、遷移確率を考慮しなければならないが、均等な確率としている(select-word関数のrand-nth関数)。
このような文字列を扱う処理は、C言語よりも圧倒的にClojureの方が書き易い。

2013年12月12日木曜日

[Clojure]トランザクションの最大リトライ回数

トランザクション内で、リファレンスの値の変更に失敗した場合は、トランザクションの最初から処理をリトライする。

トランザクションの処理に時間がかかり、何回繰り返してもリファレンスの値を更新できない場合は Live lock 状態になる。Clojureでは、これを防ぐため、リトライ回数がある一定値を越えると、例外を投げる仕組みになっている。

リトライ回数の最大値はどのくらいかなと、調べてみた。

(def x (ref 0))

(defn test1 []
 (dosync
  @(future (dosync (alter x inc)))
  (ref-set x -1)))


user> (test1)
RuntimeException Transaction failed after reaching retry limit  clojure.lang.Util.runtimeException (Util.java:219)
user> x
#<Ref@843d62: 10000>
user>

最大10000回もリトライしていた。
数十回程度かなと思っていたので、少しびっくり。
この値は変更できるのか、ざっと調べてみたが、変更方法は見付からなかった。
Clojure の STM のドキュメントのどこかに書いてあるのかな?

2013年12月7日土曜日

[Clojure]形態素解析ライブラリKuromojiを使う

オーム社の100周年記念セールで、はじめてのAIプログラミング C言語で作る人工知能と人工無能を購入した。2006年に出版された書籍で、C言語(Borland C)での実装が解説してある。
この類のプログラムをCで実装するのは煩雑になってしまうので、Clojureで作ったらどんなふうになるのかなと思い、文字列の解析時に使用する形態素ライブラリを調べてみた。
Lucene や Solr に対応したlucene-gosen が、結構使われているようだけど、mavenリポジトリにあるバージョンは少し古く、また、多くのライブラリに依存していており、それらのラブラリのバージョンも少し古かった。
その点、Kuromojiは、依存ライブラリがなく、lucene-gosenと同様に辞書も同梱されているので、こちらのライブラリを試してみた。

project.cljにKuromojiの設定を追加

Kuromojiをmavenで使うためには、リポジトリの追加が必要である。
project.cljに次の設定を書く。

:repositories [["Atilika Open Source repository"
                "http://www.atilika.org/nexus/content/repositories/atilika"]]
:dependencies [[[org.atilika.kuromoji/kuromoji "0.7.7"]]


リポジトリのURLの追加方法が最初分からず、いろいろ調べたが、
sample.project.cljのサンプルが参考になった。


サンプルコード

(ns gosen.core
  (:import (org.atilika.kuromoji Token Tokenizer)))

(defn -main []
  (let [tokenizer (. (Tokenizer/builder) build)]
    (doseq [token (. tokenizer tokenize "Javaより楽しいClojure。")]
      (println (str (. token getSurfaceForm) "\t"
                    (. token getAllFeatures))))))


何のことはない。Kuromojiのクラスを使う単純なコードだ。

実行結果

replより実行した。

gosen.core> (-main)
Java    名詞,固有名詞,組織,*,*,*,*
より    助詞,格助詞,一般,*,*,*,より,ヨリ,ヨリ
楽しい    形容詞,自立,*,*,形容詞・イ段,基本形,楽しい,タノシイ,タノシイ
Clojure    名詞,一般,*,*,*,*,*
。    記号,句点,*,*,*,*,。,。,。
nil

ユーザ辞書を追加することも簡単なようなので、試してみる予定。

参考

Java製形態素解析器「Kuromoji」を試してみる

2013年12月2日月曜日

[Clojure][Emacs]Clojure Cheatsheet for Emacs

EmacsでClojureのCheatsheetを閲覧できるELispがあった。
Clojure Cheatsheet for Emacs
試しに使ってみたら、結構便利。

インストール

Emacs24なら、MELPA経由で簡単にインストールできる。

Emacs初期化ファイルに以下のような設定を書いておけば良い。

;; MELPAを有効にする
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)


サイトの説明通り、以下のコマンドでインストールする。
M-x package-refresh-contents
M-x package-install RET clojure-cheatsheet

実行

M-x clojure-cheatsheet を実行すると、
ミニバッファに
pattern:
と表示されるので、検索したい文字列を入力する。
sort mapを入力した場合は、次のように表示される。



キーバインドは次の通り。
C-p 前の行
C-n 次の行
RET 選択した項目の表示

clojure-mode時に有効になるような、キーバインドを書いておくと便利かも。
試していないが、Helmのsourceにも対応している。

2013年12月1日日曜日

[Haskell][Clojure]逆ポーランド記法の解析処理

Learn You a Haskell for Great Good で書かれていた逆ポーランド記法の解析処理をClojureで書いてみた。
四則演算のみサポートする単純な処理である。

Haskellの場合

module RPN where
       
solveRPN :: String -> Double
solveRPN = head . foldl func [] . words
    where
      func (x:y:ys) "+" = (y + x) : ys
      func (x:y:ys) "-" = (y - x) : ys
      func (x:y:ys) "*" = (y * x) : ys
      func (x:y:ys) "/" = (y / x) : ys
      func xs num = read num : xs

*RPN> solveRPN "1 2 + 3 * 1 - 2 /"
4.0
     
whereを使うとコードが分かり易くて、なかなか良いね。

Clojureの場合

(ns rpn.core
  (:use [clojure.string :only (split)]))

(defn words [s]
  (split s #"\s+"))

(defn op2 [[x y & ys] f]
  (conj ys (apply f [y x])))

(defn operate [stack item]
  (case item
    "+" (op2 stack +)
    "-" (op2 stack -)
    "*" (op2 stack *)
    "/" (op2 stack /)
    (conj stack (Double/parseDouble item))))

(defn solve-rpn [exprs]
  (first (reduce operate '() (words exprs))))

rpn.core> (solve-rpn "1 2 + 3 * 1 - 2 /")
4.0

solve-rpn関数の中でoperate関数を定義することも可能だが、かえって分かり難くなりそうなので、外出しして関数定義した。
Haskellに比べると冗長になってしまった。
もっと、すっきり書けるのかな?
文字列のdouble型への変換 (Double/parseDouble item) は美しくない。→と思ったときは parse-double関数を作れば良いのだけど。

2013年10月9日水曜日

[Clojure][Emacs] Windows環境のnreplで表示される^Mを消す

Windows環境でnreplを使うと、改行文字の^Mが表示されてしまい、とても目障りだ。

user> (dotimes [i 5] (println (str "hello" i)))
hello0^M ←◆これが目障り
hello1^M
hello2^M
hello3^M
hello4^M
nil
user>

Emacs Lispを使いbuffer-display-tableで^Mを表示しないように設定して、対処した。
もっと簡単な方法は無いのかな?

^Mを消すためのEmacs Lisp

(defun remove-dos-eol ()
  "Do not show ^M in files containing mixed UNIX and DOS line endings."
  (interactive)
  (setq buffer-display-table (make-display-table))
  (aset buffer-display-table ?\^M []))

(add-hook 'nrepl-repl-mode-hook
 'remove-dos-eol)

適用後

user> (dotimes [i 5] (println (str "hello" i)))
hello0 ← ^M が消えてスッキリ
hello1
hello2
hello3
hello4
nil
user> 

参考





2013年10月6日日曜日

[Clojure] clj-webdriverでChromeのUser-Agentを変更する方法(その2)

[Clojure] clj-webdriverでChromeのUser-Agentを変更する方法 でUser-Agentを変更する方法を書いたが、先日、最新のChromeとchromedriverを使ってみると、User-Agentが変更できなくなっていた。
原因を調べてみると、DesiredCapabilitiesオブジェクトにchrome.switchesを追加しても、Chromeの起動オプションに追加されなくなっていた。
起動オプションの追加方法が変更されたようで、ChromeOptions#addArgumentsを使うと問題なく動作した。

実行環境

  • Windows 8
  • clj-webdriver 0.6.0
  • chromedriver 2.4
chromedriver 2.4 はこちらからダウンロードした。
従来のダウンロード先にあったドライバは全てdeprecatedになっており、http://code.google.com/p/chromedriver/wiki/WheredAllTheDownloadsGo?tm=2 では、以下の説明があった。
Downloads have been moved to http://chromedriver.storage.googleapis.com/index.html, because Google Code downloads are being deprecated!

project.clj

次のライブラリをdependenciesに追加した。

[clj-webdriver "0.6.0"]
[org.seleniumhq.selenium/selenium-java "2.35.0"]

src/cli_webdriver_patch.clj

前回と同様に、clj-webdriver.coreの関数を再定義して対応する。

(ns clj-webdriver-patch)

(in-ns 'clj-webdriver.core)
(import 'org.openqa.selenium.chrome.ChromeOptions)
(declare new-chrome-driver)

(defn new-driver
  "Start a new Driver instance. The `browser-spec` can include `:browser`, `:profile`, and `:cache-spec` keys.
The `:browser` can be one of `:firefox`, `:ie`, `:chrome` or `:htmlunit`.
The `:profile` should be an instance of FirefoxProfile you wish to use.
The `:cache-spec` can contain `:strategy`, `:args`, `:include` and/or `:exclude keys. See documentation on caching for more details."
  ([browser-spec]
     (let [{:keys [browser profile chrome-switches cache-spec]
            :or {browser :firefox
                 profile nil
                 chrome-switches nil
                 cache-spec {}}} browser-spec]
       (if (= browser :chrome)
         (new-chrome-driver chrome-switches)
         (init-driver {:webdriver (new-webdriver* {:browser browser
                                                   :profile profile})
                       :cache-spec cache-spec})))))
(defn new-chrome-driver
  [chrome-switches]
  (let [option (ChromeOptions.)]
    ;; for Linux
    ;; (.setBinary option "chrome.binary" "/usr/bin/google-chrome")
    (if chrome-switches
      (.addArguments option (into-array chrome-switches)))
    (init-driver (ChromeDriver. option))))


src/chrometest/core.clj

サンプルコード。
User-AgentにiPhoneを設定し、googleで「hogehoge」を検索する。

(ns chrometest.core
  (:require [clj-webdriver.core])
  (:use clj-webdriver-patch)
  (:require [clj-webdriver.taxi :as taxi]))

(System/setProperty "webdriver.chrome.driver" "c:/Application/chromedriver/chromedriver-2.4.exe")

(def ^:dynamic *ua-iPhone-3G* "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5B108 Safari/525.20")

(defn user-agent-switch [user-agent]
 (str "--user-agent=\"" user-agent "\""))

(defn test1 []
  (taxi/set-driver! {:browser :chrome
                     :chrome-switches [(user-agent-switch *ua-iPhone-3G*)]})
  (taxi/to "https://www.google.com/")
  (taxi/input-text "input[name='q']" "hogehoge")
  (taxi/click "button[name='btnG']"))


Debian Wheezyでの実行

chromedriverの最新版はglibc2.1.15に依存しており、glibcのバージョンを上げなければならない。
How to upgrade glibc from version 2.13 to 2.15 on Debian? にglibcのバージョンを上げる方法が書かれていたが、試していない。

2013年5月29日水曜日

[Clojure] clj-webdriverでChromeのUser-Agentを変更する方法

clj-webdriverを利用すると、Clojureでブラウザを制御できる。プログラムでWebアプリの自動テストや、ブラウザの自動制御が簡単にできるので、便利に使っている。
clj-webdriverでは任意のブラウザを制御できるので、ChromeのUser-Agentを変更してスマホ用のWebアプリを制御しようとしたが、clj-webdriver 0.6.0 では、Chrome Driver へ Capability を渡すコードがコメントアウトされており、User-Agentの変更ができないようだった。
そこで、該当箇所の関数を再定義して、ChromeでUser-Agentを変更できるようにした。

clj-webdriver-patch.clj

 

関数を再定義するプログラムは以下の通り。

(require 'clj-webdriver.core)

(ns clj-webdriver.core
  (:use [clj-webdriver driver])
  (:import org.openqa.selenium.remote.DesiredCapabilities))

(declare new-chrome-driver)

(defn new-driver
 "Start a new Driver instance. The `browser-spec` can include `:browser`, `:profile`, and `:cache-spec` keys.
The `:browser` can be one of `:firefox`, `:ie`, `:chrome` or `:htmlunit`.
The `:profile` should be an instance of FirefoxProfile you wish to use.
The `:cache-spec` can contain `:strategy`, `:args`, `:include` and/or `:exclude keys. See documentation on caching for more details."
 ([browser-spec]
    (let [{:keys [browser profile chrome-switches cache-spec]
           :or {browser :firefox
                profile nil
                chrome-switches nil
                cache-spec {}}} browser-spec]
      (if (= browser :chrome)
        (new-chrome-driver chrome-switches)
        (init-driver {:webdriver (new-webdriver* {:browser browser
                                                  :profile profile})
                      :cache-spec cache-spec})))))

(defn new-chrome-driver
  [chrome-switches]
  (let [cap (DesiredCapabilities/chrome)]
    ;; for Linux
    (.setCapability cap "chrome.binary" "/usr/lib/chromium-browser/chromium-browser")
    (if chrome-switches
      (.setCapability cap "chrome.switches" (into-array chrome-switches)))
    (init-driver (ChromeDriver. cap))))



サンプルコード


User-Agentを iPhone-3G にするコードを以下に示す。

http://code.google.com/p/chromedriver/downloads/list から Chrome Driver をダウンロードし、任意の場所に解凍しておく。
Chrome Driver実行ファイルのパスは以下のコードの (System/setProperty 〜) で設定する。

(ns webdriver-test.core
  (:require [clj-webdriver.taxi :as taxi]))

;; Driver path
(System/setProperty "webdriver.chrome.driver" "/home/hogehoge/opt/chromedriver")
;; (System/setProperty "webdriver.ie.driver" "set ie driver path")

(def ^:dynamic *ua-iPhone-3G* "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5B108 Safari/525.20")

(defn open-browser
  "Open browser."
  [browser]
  (taxi/set-driver! {:browser browser}))

(defn user-agent-switch [user-agent]
  (str "--user-agent=\"" user-agent "\""))

(defn open-chrome [url]
  (taxi/set-driver! {:browser :chrome
                     :chrome-switches [(user-agent-switch *ua-iPhone-3G*)]}
                    url))



(open-chrome "https://www.google.com/") を実行すると スマホ用のGoogleトップを表示できる。