【问题标题】:How to write this clojure enlive program so it can parse multiple urls?如何编写这个 clojure enlive 程序以便它可以解析多个 url?
【发布时间】:2013-05-07 10:44:55
【问题描述】:

这是一个解析一些网站的程序。第一个站点是site1。解析该特定站点的所有逻辑都位于 (-> config :site1)

(ns program.core
    (require [net.cgrand.enlive-html :as html])) 

(def config 
    {:site1   
        {:site-url 
            ["http://www.site1.com/page/1"
             "http://www.site1.com/page/2"
                 "http://www.site1.com/page/3"
             "http://www.site1.com/page/4"]
        :url-encoding "iso-8859-1"
        :parsing-index
            {:date
                {:selector 
                    [[:td.PadMed (html/nth-of-type 1)] :table [:tr (html/nth-of-type 2)] 
                    [:td (html/nth-of-type 3)] [:span]]
                :trimming-fn
                    (comp first :content) ; (first) to remove extra parenthese
                }
            :title 
                {:selector
                    [[:td.PadMed (html/nth-of-type 1)] :table :tr [:td (html/nth-of-type 2)] [:a]]
                :trimming-fn
                    (comp first :content first :content)
                }
            :url 
                {:selector
                    [[:td.PadMed (html/nth-of-type 1)] :table :tr [:td (html/nth-of-type 2)] [:a]]
                :trimming-fn 
                    #(str "http://www.site.com" (:href (:attrs %)))
                }
            }
        }})
    ;=== Fetch fn ===;

    (defn fetch-encoded-url 
        ([url] (fetch-encoded-url url "utf-8"))
        ([url encoding] (-> url java.net.URL. 
                    .getContent 
                    (java.io.InputStreamReader. encoding)
                    html/html-resource)))

现在我要解析 (-> config :site1 :site-url) 中包含的页面所有的网址?

(defn parse-element [element]
    (into [] (map (-> config :site1 :parsing-index element :trimming-fn)
            (html/select 
              (fetch-encoded-url
                (-> config :site1 :site-url first)
                (-> config :site1 :url-encoding))
              (-> config :site1 :parsing-index element :selector)))))

(def element-lists
    (apply map vector
        (map parse-element (-> config :site1 :parsing-index keys))))

(def tagged-lists
    (into [] (for [element-list element-lists]
           (zipmap [:date :title :url] element-list))))

;==== Fn call ====
    (println tagged-lists)

【问题讨论】:

  • 你不是在 4 小时前问了同样的问题吗?
  • 很抱歉。刚刚删除了之前的问题,谢谢!

标签: clojure enlive


【解决方案1】:

:site1 作为参数传递给parse-elementelements-list

(defn parse-element [site element]
    (into [] (map (-> config site :parsing-index element :trimming-fn)
        (html/select 
          (fetch-encoded-url
            (-> config site :site-url first)
            (-> config site :url-encoding))
          (-> config site :parsing-index element :selector)))))

(def element-lists [site]
    (apply map vector
        (map (partial parse-element site) (-> config site :parsing-index keys))))

然后映射到:site1 :site2…键。


附录以回答 cmets 中的进一步问题。

您可以将html/select 包裹在map 中,覆盖:site-urls。比如:

(defn parse-element [site element]
  (let [site-urls (-> config site :site-url)]  
    (into [] (map (-> config site :parsing-index element :trimming-fn)
       map
        #(html/select 
          (fetch-encoded-url
            %
            (-> config site :url-encoding))
          (-> config site :parsing-index element :selector)))
        site-urls)))

(我希望我的括号是正确的。)

然后您可能需要检查 :trimming-fn,以便它处理嵌套。 apply 就足够了。

【讨论】:

  • 太棒了!对于给定站点中的多个 url,我该怎么做? :site-url ["site1.com/page/1" "site1.com/page/2" "site1.com/page/3" "site1.com/page/4"]
  • 您将需要重写parse-element 以映射:site-url 向量,而不是通过包装整个html/select 来获取它的第一个元素。查看我的编辑。
  • @user1184248 如果答案符合您的期望,请考虑投票和/或接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多