Clojure スクレイピング技術概論

Clojureによるスクレイピング技術まとめ.

Cljure Scraping Basic

いろいろとしらべると, HTTPクライアント(http-kit or clj-http) + enliveが王道. enlive はClojureにおけるHTML parserの筆頭. HTTPクライアントのGet RequestでHTMLデータを取得してあとはゴリゴリ解析すればいい.

スクレイピングにClojureを選択する利点は,

  • Lispはそもそもparser処理に強い.
  • REPLによるインタラクティブな解析.
  • defaultでパラレルな処理に長けている.

つまりライブラリがなくともデフォルトで強い. いざとなればJavaのライブラリが使える(playwright とか).


基本的には以下の流れだ.

  • url指定で get requestでHTMLの素のデータを取得.
  • enliveでhtmlデータをHashMapに変換.
  • defでREPLにbinding(キャッシュする).
  • キャッシュしたHashMapに対するパーサーをREPLと対話しながら作成.

🔧enlive-html

ref: Getting started · cgrand/enlive Wiki

enlive はClojureにおけるテンプレートエンジンであるが, その中でもenlive-htmlがCSS-baseパーサーライブラリ.

(require '[net.cgrand.enlive-html :as html])

html-resource で URLに対してget requestをしてbodyをtreeデータ(hash-maps)にパースしてくれる. もしくは, 自前でhttp getしてbodyを html-snipet に突っ込んでもい.

(html/html-resource (java.net.URL url))

そしてこのデータは単なるClojureのhash-mapに過ぎないので,素のClojure関数でゴリゴリ中をみれるわけだ. clojure.pprint/pprint なんかでREPLに出力できる(HTMLデータが大きいときは注意).

enliveには select という関数があり, これでCSSセレクタを指定してアクセスできる. get-in のようにアクセス可能.

enlive select Idioms

enliveのよくあるパターンの例まとめ. 🔖cljidiom

ref. Enlive selectors syntax - GitHub

タイトル取得

;; title取得
(html/select [:title])
 
;; head取得
(html/select [:head])

特定のタグ

大抵, :hogehoge で取れる. たとえば videoのようなタグは

(html/select [:video])

name属性取得

name=“description”という属性をもつ要素を取得.

(html/select page [(html/attr= :name "description")])

a tagのhrefの中身を取得

:a でアクセス. a.xxxだとclass:xxxをオプションで追加.

パースに取得成功すると [:atters :href]にurlがあるのでこれをMap操作で取得すればいい.

Clojure Scraping Topics

💡REPL上でゴニョゴニョパーサーをかける

結局HTMLを取得してそれをMapデータ構造とみなしてそれに対するパーサーを書くのがスクレイピングのキモだとすると, REPLで対話しながら欲しい情報を抜き出す処理をいろいろ試しながらできるのはとても強い.

📝Clojure REPL駆動開発と大変相性がいいのがスクレイピングだ.

💡Lazy Sequence + pmap + doallの並列スクレイピングが強い

複数ページにまたがるような処理だったり, offsetを指定してAPIを呼び出す時の並列スクレイピングが強い.

具体的にはページごとのスクレイピングの処理をpmapで遅延シーケンスに詰め込み, doallで実行することによってAPIを並列で発射刷ることが可能.

スクレイピングの並列化について各言語で実装は可能なもののClojureのこの気軽さはとても強い.

たくさんのページのスクレイピングに時間がかかるなあとかいっている並行プログラミングができない駆け出しエンジニアは情弱である.

clojure pmap

References