この記事はCrystal Advent Calendar 2015 22日目の記事です。
当初は@pine613さんが書く場所だったのですが、
譲っていただきました。 ありがとうございます。
というわけで今回はCrystalを使ってWebスクレイピングしたいと思います。
RubyでWebスクレイピングをする際はNokogiriという非常に使いやすいライブラリを使用するのですが
CrystalにはまだNokogiriのようなすぐれたライブラリが存在しない(と思っている)ので
今回はxpathを使用します。
コードとしてはそれほど難しいことはしていません。
Crystal Advent Calendar 2015に接続して
日付、ブログ記載者、ブログタイトルそしてブログのURLを取得するというプログラムです。
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 さんです。
よろしくお願いします。