ラズパイでRubyのWebクローリング/スクレイピング環境構築メモ

先日、ラズパイ上で、Ruby,SeleniumWebDriverのWebクローラー/スクレイピング環境を構築しました。Windows上では環境構築したことがありましたが、Linux系OS上では初めて環境構築しました。手間取ったことも多く、いくつか試行錯誤しながら作業したので、備忘録として手順をまとめたいと思います。



## 動作確認環境
環境構築前は、次のような環境でした。

- Raspberry Pi Model B Rev.2
- Raspbian GNU/Linux 7 (wheezy)
- Linux raspberrypi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l GNU/Linux
- Ruby 1.9.3p194 (2012-04-20 revision 35410) [arm-linux-eabihf]
- RubyでWebクローラー/スクレイピングするためのソフトウェアやライブラリなし

今回の作業後は、次の環境になりました。変更点のみ記述します。

- Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv6l GNU/Linux
- rbenv 0.3.0
- Ruby 2.2.4p230 (2015-12-16 revision 53155) [armv6l-linux-eabihf]
- Rubyジェム
 - Selenium-WebDriver 2.53.0
 - Nokogiri 1.6.7.2
 - Headless 2.2.3
- Mozilla Iceweasel 38.7.1



## 作業の流れ
- OSアップデート
- Ruby管理ツールインストール
- Rubyインストール
- Rubyジェムインストール（Selenium-WebDriver,Nokogiri）
- Rubyジェムインストール（Headless）

Rubyをインストールするまでの手順は、次のサイトに従って行いました。

>[Raspberry PiにRubyをインストール - DesignAssembler](http://hyottokoaloha.hatenablog.com/entry/2015/04/25/100605)



## OSアップデート
以降の作業を安定して進めるため、次のコマンドでOSをアップデートしました。

    $ sudo apt-get update

### 補足
今回作業の中で、試行錯誤した際に、次のコマンドも実行しました。必要な作業であったかどうかは不明です。

    $ sudo apt-get upgrade



## Ruby管理ツールインストール
今回初めて、rbenvの存在を知りました。バージョン違いのRubyをインストール、管理するツールのようです。Rubyには、下位互換性が低いバージョンがいくつかあるようなので、複数バージョンを管理できるツールがあるのは便利ですね。

次のコマンドでインストールしました。

    $ sudo apt-get install rbenv
    $ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

次のコマンドで、インストールしたコマンドが使用可能な状態になったことを確認しました。

    $ rbenv -h

### トラブル体験
ruby-buildは、apt-getでもインストールできました。その場合、インストール可能なRubyのバージョンが「2.0.0-dev」までしか表示されませんでした。

apt-getとgitの両方のruby-buildをインストールしてしまったことがありました。その場合、`rbenv install --list`ではインストール可能なRubyバージョンが色々表示されましたが、`ruby-build --definitions`では「2.0.0-dev」までしか表示されず、`rbenv install 2.2.4`を実行すると、なぜかコマンドの使用方法が表示され、インストールできませんでした。

apt-getでruby-buildをインストールしたときは、次のコマンドでアンインストールしました。

    $ sudo apt-get remove ruby-build
    $ sudo apt-get autoremove



## Rubyインストール
まずは、次のようにして、Rubyで必要となるライブラリ類をインストールし、その設定を行いました。

    $ sudo apt-get install autoconf
    $ sudo apt-get install libreadline-dev
    $ sudo apt-get install libssl-dev
    $ sudo apt-get install ruby-dev
    $ dpkg -l autoconf libreadline-dev libssl-dev ruby-dev
    $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
    $ . .bashrc

次に、インストール可能なRubyバージョンを確認し、インストールしました。インストールしたRubyバージョンは、普段使っているWindows環境に合わせ2.2.4にしました。インストールには数時間かかり、動作しているかどうか不安になるため、オプション「-v」を付けて、詳細メッセージを表示するようにしました。

    $ rbenv install --list
    $ rbenv install -v 2.2.4
    $ rbenv versions
    * 2.2.4 (set by /home/xxx/.rbenv/version)

次のようにして、バージョン2.2.4が適用されていることを確認しました。

    $ rbenv global 2.2.4
    $ rbenv rehash
    $ ruby -v
    ruby 2.2.4p230 (2015-12-16 revision 53155) [armv6l-linux-eabihf]
    $ gem -v
    2.4.5.1

### トラブル体験
autoconfのインストールをせずに作業を進めたときは、`rbenv install`のときに、次のようなエラーが発生してしまいました。

    /usr/bin/ruby-build: 行 161: autoconf: コマンドが見つかりません

libreadline-devのインストールをせずに作業を進めたときは、`rbenv install`のときに、次のようなエラーが発生してしまいました。

    Try running `apt-get install -y libreadline-dev` to fetch missing dependencies.



## Rubyジェムインストール（Selenium-WebDriver,Nokogiri）
RubyでWebクローリング/スクレイピングするのに便利なジェムとして、Selenium-WebDriver、Nokogiriをインストールすることにしました。インストールは、次のように行いました。

    $ gem install selenium-webdriver
    $ gem install nokogiri

Selenium-WebDriverが動作するように次の設定を行いました。この設定が必須なのかどうかは不明です。

    $ sudo vi /etc/hosts
    $ diff /etc/hosts.bk20160403 /etc/hosts
    2,6c2,6
    < ::1           localhost ip6-localhost ip6-loopback
    < fe00::0               ip6-localnet
    < ff00::0               ip6-mcastprefix
    < ff02::1               ip6-allnodes
    < ff02::2               ip6-allrouters
    ---
    > #::1          localhost ip6-localhost ip6-loopback
    > #fe00::0              ip6-localnet
    > #ff00::0              ip6-mcastprefix
    > #ff02::1              ip6-allnodes
    > #ff02::2              ip6-allrouters

Selenium-WebDriverから制御可能なブラウザとして、Firefoxを使うことにしました。Linuxの世界では、Firefoxの代替（？）が、Iceweaselらしいので次のようにしてインストールしました。

    $ sudo apt-get install iceweasel

ここまでの手順で、ラズパイのX端末環境において、RubyでWebクローリング/スクレイピングができるようになりました。ただし、X端末が必要ですし、Selenium-WebDriver動作時にはブラウザが画面表示されます。これだと、CUI環境で動作させることはできませんでした。

### トラブル体験
hostsファイルのIPv6設定を有効にしたまま、RubyジェムのSelenium-WebDriverを使うと、次のようなエラーが発生しました。

    /home/xxx/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.0/lib/selenium/webdriver/common/port_prober.rb:47:in `initialize': Address family not supported by protocol - socket(2) for "::1" port 7055 (Errno::EAFNOSUPPORT)

このエラーは、次のページをみて解決することができました。感謝！

>[nginxでsocket() failed (97: Address family not supported by protocol) : PHPやめてRuby使うぞ日記](http://blog.livedoor.jp/st_monkey/archives/27975009.html)

Firefox(Iceweasel)をインストールせずに、RubyジェムのSelenium-WebDriverを使うと、次のようなエラーが発生しました。

    /home/xxx/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.0/lib/selenium/webdriver/firefox/binary.rb:150:in `path': Could not find Firefox binary (os=linux). Make sure Firefox is installed or set the path manually with Selenium::WebDriver::Firefox::Binary.path= (Selenium::WebDriver::Error::WebDriverError)

このエラー発生時には、次のページにお世話になりました。このぺーじでIceweaselの存在を知り、インストール方法が分かりました。

>[Raspberry Piで遊ぼう [No.10:firefox(iceweasel)をインストールしてみよう]：アシマネくんのほんわか日記：So-netブログ](http://assimane.blog.so-net.ne.jp/2013-04-02)

ここまでの手順の状態（CUI環境で動作させるための環境構築を未実施）にも関わらず、CUI環境でRubyジェムのSelenium-WebDriverを使うと、次のようなエラーが発生しました。

    /home/xxx/.rbenv/versions/2.2.4/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.0/lib/selenium/webdriver/firefox/launcher.rb:90:in `connect_until_stable': unable to obtain stable firefox connection in 60 seconds (127.0.0.1:7055) (Selenium::WebDriver::Error::WebDriverError)

このとき、次のページを見つけて、Headlessの存在を知りました。

>[Raspberry PiでSeleniumを使ってスクレイピング | あっかぎのページ](http://akkagi.info/20150925_web/)



## Rubyジェムインストール（Headless）
今回初めて知ったのですが、Selenium-WebDriverをCUI環境で動作させるためには、Headlessというジェムがありました。次のようにして、Headlessジェムと、そのジェムを動作させるためのライブラリ類をインストールしました。

    $ sudo apt-get install xvfb
    $ gem install headless
    $ sudo vi /etc/modprobe.d/ipv6.conf
    $ diff /etc/modprobe.d/ipv6.conf.bk20160403 /etc/modprobe.d/ipv6.conf
    3c3,4
    < #alias ipv6 off
    ---
    > alias ipv6 off

これで、CUI環境でも、Selenium-WebDriverが動作するようになりました。

### トラブル体験
Selenium-WebDriverでブラウザを上手く起動できない時がありました。その場合、`export DISPLAY=:99`としてから、動作させると上手く起動できました。でも、最終的にはその手順をしなくても動作するようになりましたので、必須の手順ではないようです。

Selenium-WebDriverでWebクローリングしたところ、取得したWebページが英語表記になってしまうことがありました。その場合は、Rubyスクリプトで次のようにすることで解決しました。

    profile = Selenium::WebDriver::Firefox::Profile.new
    profile['intl.accept_languages'] = "ja"
    profile['general.useragent.locale'] = "ja-JP"
    driver = Selenium::WebDriver.for :firefox, :profile => profile

この際は、こちらのページに助けられました。

>[SeleniumWebdriverで使用するブラウザの言語を設定する - Qiita](http://qiita.com/oh_rusty_nail/items/9f521f6c784b53924af6)

Selenium-WebDriverでWebクローリングしたところ、画面表示に時間がかかるページがあり、次のようなエラーが発生しました。

    /home/xxx/.rbenv/versions/2.2.4/lib/ruby/2.2.0/net/protocol.rb:158:in `rescue in rbuf_fill': Net::ReadTimeout (Net::ReadTimeout)

その場合、Rubyスクリプトで次のようにすると解決しました。

    # タイムアウト値を大きくする（デフォルトは60秒。）
    client = Selenium::WebDriver::Remote::Http::Default.new
    client.timeout = 120
    driver = Selenium::WebDriver.for :firefox, :http_client => client

この際は、こちらのページに助けられました。

>[webdriverのタイムアウトを設定する - Qiita](http://qiita.com/yooo_gooo/items/50e66aa2624f521183a2)

## おわり
非常に手間と時間がかかりましたが、環境構築を無事完了できてよかった。