Common Lispでスクレイピング
Common LispでWebの大波を泳いでみる
最近Land of Lispと初めての人のためのLsipを読んでいるので、せっかくだから遊んでみます。
環境は以下の通り。
- OS
- ArchLinux Kernel(4.18.13-ARCH)
- Lisp処理系
- Clozure-CL 1.11
リクエストをぽいっと投げる
Drakmaでぽい
Drakmaとは、Common Lispのhttp clientです。
早速試してみます。
ros run
と実行して、以下のコマンドを入力します。
? (ql:quickload :drakma) ? (drakma:http-request "http://ryoana.com") ... 略 <body link=\"black\" vlink=\"black\" alink=\"black\"> <div class=\"content\"> <div class=\"header\"> é»ç¸ç¼é¡ã®ãä¼ã¿å¦ </div> </body> </html> " 200 ((:SERVER . "nginx") (:DATE . "Thu, 29 Dec 2016 12:45:23 GMT") (:CONTENT-TYPE . "text/html") (:CONTENT-LENGTH . "1854") (:LAST-MODIFIED . "Sun, 30 Oct 2016 10:17:27 GMT") (:CONNECTION . "close") (:ETAG . "\"5815c8b7-73e\"") (:ACCEPT-RANGES . "bytes")) #<URI http://ryoana.com/> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x302001C9A3ED> T
response body
を文字列として、response header
はリストとして返している模様。
しかし文字化けしてますね。。。
文字化けを何とかする
? (setq drakma:*drakma-default-external-format* :utf-8) ? (drakma:http-request "http://ryoana.com") ...略 <body link=\"black\" vlink=\"black\" alink=\"black\"> <div class=\"content\"> <div class=\"header\"> 黒縁眼鏡のお休み処 </div>
文字化けしなくなったので、取得できたhtmlを変数に入れておきましょう。
? (defvar *html* (drakma:http-request "http://ryoana.com")) *HTML*
今気づいたけど、ダブルクォートの前にエスケープが入っている。。。?
htmlをパースするぞい
plumpとclss
このままだと参考にさせていただいた記事を写経しているだけなので、Quickdocsからいい感じのライブラリを探したんですが、cl-html-parse
だとパースするだけ(私の調査力不足かもしれん)っぽかったりしたので、結局plump
とclss
を使います。
ros install
したら、REPLで以下のように打ちます。
? (defvar *parse-html* (plump:parse *html*)) ? (plump:text (car (coerce (clss:select "title" *parse-html*) 'list))) "黒縁眼鏡のお休み処"
わからないところは、たとえば<a href="index.html" title="ほげ">
というタグがあった時に、ほげ
を抽出する方法がわからない。。