黒縁眼鏡は海を飛ぶ

IT中心にそこはかとなく

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はリストとして返している模様。
しかし文字化けしてますね。。。

文字化けを何とかする

文字コードutf-8にすればなんとかなる!

? (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だとパースするだけ(私の調査力不足かもしれん)っぽかったりしたので、結局plumpclssを使います。

ros installしたら、REPLで以下のように打ちます。

? (defvar *parse-html* (plump:parse *html*))
? (plump:text (car (coerce (clss:select "title" *parse-html*) 'list)))
"黒縁眼鏡のお休み処"

わからないところは、たとえば<a href="index.html" title="ほげ">というタグがあった時に、ほげを抽出する方法がわからない。。

参考にさせていただいた記事とか