CrystalによるWebスクレイピング

  • 6
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

この記事はCrystal Advent Calendar 2015 22日目の記事です。
当初は@pine613さんが書く場所だったのですが、
譲っていただきました。 ありがとうございます。


というわけで今回はCrystalを使ってWebスクレイピングしたいと思います。
RubyでWebスクレイピングをする際はNokogiriという非常に使いやすいライブラリを使用するのですが
CrystalにはまだNokogiriのようなすぐれたライブラリが存在しない(と思っている)ので
今回はxpathを使用します。

コードとしてはそれほど難しいことはしていません。
Crystal Advent Calendar 2015に接続して
日付、ブログ記載者、ブログタイトルそしてブログのURLを取得するというプログラムです。

test.cr
require "xml"
require "http/client"

res = HTTP::Client.get "http://www.adventar.org/calendars/800"
xml = XML.parse_html(res.body)
# 毎日のカレンダーの情報のノードを取得
nodes = xml.xpath_nodes "//th[@class=\"mod-entryList-date\"]/parent::node()"

nodes.each{|node|
  puts "------------------"
  x = XML.parse_html(node.to_xml)
  puts x.xpath_node("//th").text # 日付
  puts x.xpath_node("//td[@class=\"mod-entryList-user\"]/a/span").text # 記者
  puts x.xpath_node("//div[@class=\"mod-entryList-title\"]").text # タイトル
  puts x.xpath_node("//div[@class=\"mod-entryList-url\"]/a")["href"] #URL
  puts "------------------"
}

ここで注意が必要なのは(当然なのだが)Crystalでxmlライブラリを使用する際は
コンパイルの際に幾つかのライブラリが必要となります。
ですので、ライブラリが存在しない場合は入れておく必要があります。

libssl
libxml2
libevent
librt
libpcl
libgc
libpthread
libdl

コンパイルするとエラーになる

上記ライブラリが存在しないとコンパイルするときにエラーになります。
エラー内容は下記のような感じ。

Error: execution of command failed with code: 1: `cc -o "/home/.../crystal-run-test.tmp" "${@}"  -rdynamic  -lssl -lxml2 -levent -lrt -lpcl -lpcre -lgc -lpthread -ldl`

libgc.aはCrystalのライブラリディレクトリ(crystal/embedded/lib)に
存在するのですが、なぜか私の環境ではパスが通っていなかったため
コンパイルエラーになっていました。
なので必要に応じてパスを通します。

CSSセレクタがほしい

やってみてわかったことですが、RubyのNokogiriはやはりかなり優れたライブラリです。
本当はCrystalでNokogiriのようなCSSセレクタを作成して
Webスクレイピングしたという記事を書きたかったのですが
今の段階でCSSセレクタを作るのが難しいので断念してしまいました。

というのも、Rubyでは標準としてRaccというLALRのパーサージェネレータが存在し、
Nokogiriでもそれを使用しています。
CrystalにはLALRパーサーがない(はずな)のでまずはそっちからかなと思っています。

冬休みの宿題

なので今年の冬休みの宿題は

  • RaccのようなLALR(1)パースジェネレータを作成する
  • NokogiriのようなCSSセレクタを作成する

では明日のCrystal Advent Calendar 2015は kmizu さんです。
よろしくお願いします。