如何在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
相关产品推荐
相关产品推荐

