Friday, November 9, 2018

Web scraping notes

最近公司的工作裡有一部分是做 web scraping 。要做的事,大致可以分成 2 個步驟:
a.  login/authentication
b.  extract data from web page

其中,登入的部分,客戶的網站大概可以分成兩大類別:
(1) token based authentication
最新一代的標準是 JSON Web token 。
(2) session based authentication
這種通常都需要去處理 cookie 才有辦法登入

客戶的網站有的是 backend rendering ,有的是 frontend rendering 。如果是前者,通常 backend API 傳回的資料是 JSON ,算是最容易處理。如果是後者,backend API 傳回的資料則是 HTML/XML 的格式

要從 HTML/XML 中提出資料,通常可以考慮三種做法:
(1) Regular expression  => 直接硬做字串的比對
(2) XPath                       => 可以看懂 XML tree ,透過資料的結構關系去定位資料的位置。
(3) CSS selector            => 表達能力比 XPath 略弱一些,但是使用比較廣泛。


Wednesday, November 7, 2018

Effective REPL-driven Clojure

Effective REPL-driven Clojure 這篇文章裡,介紹了一系列 REPL-driven 的好用技巧:

1. Evaluate forms frequently
每次如果修改了某個 forms  ,尤其是它是 def 的 form ,就可以考慮把它重新求值一下。 求值的作用可以想象成是一種存檔。

2. Start stateful things in REPL before you do anythings else
使用 mount 或是 component

3. Use comment forms to document your experiments
在 REPL 要做的求值實驗,可以考慮用 (comment ... ) 記錄在程式裡,方便日後理解。

4. Use def for debugging
REPL 可以對定義好的函數輕易地求值。然而,函數內部的 form 要如何 debug 呢? 函數內部的 form 往往會依賴於函數的 arguments 。很簡單,就是用 def 把函數的 arguments 指定一個固定值,這樣子就可以 debug 了。記得 git commit 之前要把這種 debugging 的 def 移除。範例

5. Unmap namespace during experimentation
ns-unaliasns-unmap 可以視為 def 和 require 的反運算。

6. Re-open libraries for exploration
在 require 某個 library 之後,使用 in-ns 可以進入該 library 的 namespace 裡,並且在這邊重新定義變數,以達成除錯或是取得執行資訊的目的。(monkey-patch)

7. Pretty Print
使用 clojure.pprint 這個函式庫來做輸出