【问题标题】:clojure.data.json write/read affects enlive dataclojure.data.json 写入/读取影响实时数据
【发布时间】:2015-01-23 21:19:59
【问题描述】:

保存和重新加载enlivehtml-resource 输出的适当json 方式是什么。

以下过程不保留数据结构(注意我要求 json/read-str 将键映射到符号):

(require net.cgrand.enlive-html :as html)
(require clojure.data.json :as json)


(def craig-home
  (html/html-resource (java.net.URL. "http://www.craigslist.org/about/sites")))
(spit "./data/test_json_flow.json" (json/write-str  craig-home))

(def craig-reloaded
  (json/read-str (slurp "./data/test_json_flow.json") :key-fn keyword))

(defn count-nodes [page] (count (html/select page [:div.box :h4])))
(println (count-nodes craig-home)) ;; => 140
(println (count-nodes craig-reloaded)) ;; => 0

谢谢。

更新

为了解决 Mark Fischer 的评论,我发布了一个不同的代码,地址为 html/select 而不是 html/html-resource

(def craig-home
  (html/html-resource (java.net.URL. "http://www.craigslist.org/about/sites")))
(def craig-boxes (html/select craig-home [:div.box]))
(count (html/select craig-boxes [:h4])) ;; => 140

(spit "./data/test_json_flow.json" (json/write-str  craig-boxes))
(def craig-boxes-reloaded
  (json/read-str (slurp "./data/test_json_flow.json") :key-fn keyword))
(count (html/select craig-boxes-reloaded [:h4])) ;; => 0

【问题讨论】:

  • 这似乎不对,您的 craig-reloaded 和 craig-home 返回不同的类型,重新加载的版本没有返回 count-nodes 方法可以使用的 html,是吗?跨度>
  • @mark 你是对的。我搞砸了我的例子。实际上我的问题是关于 jsonizing html/select 结果并进一步解析它们。我更新了例子

标签: json clojure enlive


【解决方案1】:

更简单的方法是使用 Clojure edn 进行写入/读取:

(require '[net.cgrand.enlive-html :as html])
(require '[clojure.data.json :as json])

(def craig-home (html/html-resource (java.net.URL. "http://www.craigslist.org/about/sites")))

(spit "./data/test_json_flow.json" (pr-str craig-home))

(def craig-reloaded
  (clojure.edn/read-string (slurp "./data/test_json_flow.json")))

(defn count-nodes [page] (count (html/select page [:div.box :h4])))
(println (count-nodes craig-home)) ;=>140
(println (count-nodes craig-reloaded)) ;=>140

Enlive 期望标签名称值也是关键字,如果标签名称值是字符串(这是 json/write-str 和 json/read-str 将关键字转换为的内容),则不会找到节点。

(json/write-str '({:tag :h4, :attrs nil, :content ("Illinois")}))
;=> "[{\"tag\":\"h4,\",\"attrs\":null,\"content\":[\"Illinois\"]}]"

(json/read-str (json/write-str '({:tag :h4, :attrs nil, :content ("Illinois")})) :key-fn keyword)
;=> [{:tag "h4", :attrs nil, :content ["Illinois"]}]

(pr-str '({:tag :h4 :attrs nil :content ("Illinois")}))
;=> "({:tag :h4, :attrs nil, :content (\"Illinois\")})"

(clojure.edn/read-string (pr-str '({:tag :h4, :attrs nil, :content ("Illinois")})))
;=> ({:tag :h4, :attrs nil, :content ("Illinois")})

如果您必须使用 json,那么您可以使用以下方法将 :tag 值转换为关键字:

(clojure.walk/postwalk #(if-let [v (and (map? %) (:tag %))]
                          (assoc % :tag (keyword v)) %)
                       craig-reloaded)

【讨论】:

  • 感谢 edn 的建议。它解决了我在clojure这个词中的问题。现在假设我想导出结果并在 python 中进一步解析。有没有办法以“通用”格式制作和导出?
  • 我已经更新了我的答案,包括在通过 Enlive 之前将标签值转换为关键字时读取 json 的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 2020-04-24
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多