在clojure

时间:2016-05-14 09:58:06

标签: clojure jsoup clojure-java-interop

我不想刮一个网站,这需要我登录。我决定用Jsoup来做这件事。我遇到了麻烦"翻译"这段代码正确地适用于Clojure:

Connection.Response loginForm = Jsoup.connect("**url**")
        .method(Connection.Method.GET)
        .execute();

如果没有在我的Clojure代码中指定类Connection.Response,则连接具有类jsoup.helper.HttpConnect,它缺少会话中的cookie所需的方法。

到目前为止,我已经提出了以下Clojure代码:

(import (org.jsoup Jsoup Connection
               Connection$Response Connection$Method))
(do
 (def url "*URL*")
 (def res (doto (org.jsoup.Jsoup/connect url)
   (.data "username" "*USERNAME*")
   (.data "password" "*PASSWORD")
   (.method Connection$Method/POST)
   (.execute)))
 (type res))

1 个答案:

答案 0 :(得分:5)

问题是你在doto使用->线程宏:

(let [url "*URL*"]
  (-> url
      (org.jsoup.Jsoup/connect)
      (.data "username" "*USERNAME*")
      (.data "password" "*PASSWORD*")
      (.method "Connection$Method/POST)
      (.execute)))
当您需要设置一个Java对象时,通常会使用

doto表单,该对象提供类似于setter的方法,返回void并阻止您使用线程。

(doto (SomeClass.)
  (.setA 1)
  (.setB 2)
  (.execute))

转换为:

(let [obj (SomeClass.)]
  (.setA obj 1)
  (.setB obj 2)
  (.execute obj)
  obj)

正如您所看到的,doto没有返回最后一个方法调用的结果,但是作为第一个参数提供的对象(在这种情况下为SomeClass对象)。因此,您当前的代码将返回由Jsoup/connect方法(jsoup.helper.HttpConnect发出通知时)创建的对象,而不是Connection.Response方法调用的execute()结果。

您需要的是:

(-> (SomeClass.)
    (.withA 1)
    (.withB 2)
    (.execute))

其中with*是返回this而不是void的构建器方法。

上述线程表相当于:

(.execute
  (.withB
    (.withA
      (SomeClass.)
      1)
    2))