Clojure:读取CSV文件并传递列值以卷曲

Clojure: Reading CSV file and passing column values to curl

新的Clojure用户在这里。 。 。有点纠结。

项目目标:

  • 从csv文件读取数据
  • 隔离第4列中的值
  • 将值传递给html参数
  • 在curl调用中使用动态创建的url

我陷入了两个特定领域:

1)如果我在进程文件中取出了println,则开始不知道如何处理'%'而出现错误(无法解析符号:在此情况下为%)

2)在调用卷曲中,我似乎无法将传入的id值获取到URL的id参数中。

1
2
3
4
5
6
7
8
9
10
11
12
13
(defn call-curl [id]
  (let [url"-d id=%s&format=pdf&cpull=1"]
    (shell/sh"curl""-u""username:password""http://wwwin-search.com/protected-cgi-bin/office2pdf.cgi" (format url id))))

(defn process-files
  "Take file name and read data"
   [file]
   (let [data (slurp file)
         rows (rest (c/parse-csv data))]
     (dorun
     (map #(println (call-curl (nth % 3 nil))) rows))))

(process-files"output.csv")

我怀疑出现第一个问题是因为没有println的代码如下所示:

1
(map (call-curl (nth % 3 nil)) rows)

而不是:

1
(map #(call-curl (nth % 3 nil)) rows)

如果您只是为了副作用而遍历整个序列,我建议doseq

1
2
(doseq [row rows]
  (call-curl (nth row 3 nil)))

或者您可以使用run!

1
(run! call-curl (map #(nth % 3 nil)))

但我认为doseq版本更具可读性。

对于第二个问题,我认为您需要为curl调用提供每个单独的参数作为单独的字符串:应为

"-d""..."

而不是

"-d ..."

我对其进行了一些重构以使其更具可读性:

1
2
3
(defn call-curl [id]
  (let [data (format"id=%s&format=pdf&cpull=1" id)]
    (shell/sh"curl""-u""username:password""-d" data"http://wwwin-search.com/protected-cgi-bin/office2pdf.cgi")))

再说一遍,根据您的代码,您不是在URL中传递参数,而是将数据作为请求正文传递。来自man curl

-d, --data

(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has
filled in an HTML form and presses the submit button. This will cause
curl
to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to -F,
--form.

-d, --data is the same as --data-ascii. --data-raw is almost the same but does not have a special interpretation of the @ character. To post data purely binary, you
should instead use the --data-
binary option. To URL-encode the value of a form field you may use --data-urlencode.

我不确定为什么您确实要调用curl而不是直接从Clojure调用HTTP端点,但是现在当您评论您确实确实想直接执行此操作时,让我建议您使用clj-http库这个目的。有了它的帮助,它变得像:

1
2
3
4
5
6
7
8
(require '[clj-http.client :as http])

(defn call-url [id]
  (http/post"http://wwwin-search.com/protected-cgi-bin/office2pdf.cgi"
    {:basic-auth ["username""password"]
     :form-params {:id id
                   :format"pdf"
                   :cpull 1}}))


有帮助吗?

使用str而不是format,在某种程度上满足了对let块的需求:

1
2
3
(shell/sh
  "curl""-u""username:password""http://wwwin-search.com/protected-cgi-bin/office2pdf.cgi"
  "-d" (str"id=" id"&format=pdf&cpull=1"))

使用:out关键字从call-curl返回输出:

1
#((call-curl (nth % 3 nil)) :out)

修改后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(require '[clojure.java.shell :as shell])
(defn call-curl [id]
  (shell/sh
  "curl""-u""username:password""http://wwwin-search.com/protected-cgi-bin/office2pdf.cgi"
  "-d" (str"id=" id"&format=pdf&cpull=1")))

(defn process-files
 "Take file name and read data"
  [file]
  (let [data (slurp file)
        rows (rest (c/parse-csv data))]
    (dorun
     (map #(do (prn %) (call-curl (nth % 3 nil)))
          rows))))

(process-files"output.csv")