You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Clojure中从指定目录动态加载所有文件的函数用于爬虫逻辑?

在Clojure中动态加载目录下所有Scraper的函数

方法一:通过文件路径动态加载

先定位src/scraper/scrapers目录下的所有.clj文件,用load-file加载每个文件后,从对应命名空间提取fetch、collect、parse三个函数。

示例代码(写入scrape.clj的main函数):

(require '[clojure.java.io :as io])
(require '[clojure.string :as str])

(defn load-all-scrapers []
  (let [scrapers-dir (io/file "src/scraper/scrapers")
        clj-files (filter #(str/ends-with? (.getName %) ".clj") (.listFiles scrapers-dir))]
    (for [file clj-files
          :let [ns-name (-> (.getName file)
                            (str/replace #"\.clj$" "")
                            (str/replace "_" "-")
                            (str "scraper.scrapers."))
                _ (load-file (.getPath file))
                fetch-fn (ns-resolve (symbol ns-name) 'fetch)
                collect-fn (ns-resolve (symbol ns-name) 'collect)
                parse-fn (ns-resolve (symbol ns-name) 'parse)]]
      {:fetch fetch-fn :collect collect-fn :parse parse-fn})))

(defn -main []
  (let [scrapers (load-all-scrapers)]
    (doseq [scraper scrapers]
      ;; 调用你的scrape函数,传入三个目标函数
      (scrape (:fetch scraper) (:collect scraper) (:parse scraper)))))

方法二:通过命名空间扫描加载

如果每个scraper文件遵循Clojure命名空间规范(比如scraper_a.clj对应scraper.scrapers.scraper-a命名空间),可以通过扫描类路径下的命名空间实现动态加载:

(require '[clojure.java.io :as io])
(require '[clojure.string :as str])

(defn find-and-load-scraper-nses []
  (let [scrapers-dir (io/file "src/scraper/scrapers")
        clj-files (filter #(str/ends-with? (.getName %) ".clj") (.listFiles scrapers-dir))]
    (doseq [file clj-files]
      (let [ns-name (-> (.getName file)
                        (str/replace #"\.clj$" "")
                        (str/replace "_" "-")
                        (str "scraper.scrapers."))]
        (require (symbol ns-name))))))

(defn load-all-scrapers []
  (let [scraper-ns-prefix "scraper.scrapers."
        matching-nses (filter #(str/starts-with? (name %) scraper-ns-prefix) (all-ns))]
    (for [ns matching-nses
          :let [fetch-fn (ns-resolve ns 'fetch)
                collect-fn (ns-resolve ns 'collect)
                parse-fn (ns-resolve ns 'parse)]]
      {:fetch fetch-fn :collect collect-fn :parse parse-fn})))

(defn -main []
  (find-and-load-scraper-nses)
  (let [scrapers (load-all-scrapers)]
    (doseq [scraper scrapers]
      (scrape (:fetch scraper) (:collect scraper) (:parse scraper)))))

关键注意事项

  • 每个scraper_x.clj文件顶部必须正确声明命名空间,比如scraper_a.clj要写(ns scraper.scrapers.scraper-a)
  • load-file会直接执行文件内容,require则会保证命名空间只被加载一次
  • 若打包成JAR运行,需确保scraper文件被正确包含在类路径中

内容的提问来源于stack exchange,提问作者probablyjg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 12:45:11