Tech Racho エンジニアの「?」を「!」に。
  • 開発

Rails4でサイト構築をする-スクレイピング機能編(Nokogiri)

[Rails4でサイト構築をする]
- Rails環境構築編
- Scaffold利用編
- Bootstrap導入編
- WYSIWYG導入編
- CSV出力機能編
- スクレイピング機能編(nokogiri)
- 非同期処理導入編(delayed_job)
- デプロイ環境構築編(capistrano3)
上記を毎週1つずつ出す予定

今回は別のサイトのHTMLをパースして情報を取得する機能を作ってみたいと思います。

HTMLのパースにはNokogiriというプラグインを使います。

Nokogiriのインストール

Gemfileに以下を追加する

gem 'nokogiri'

そして、bundle install

Nokogiriを使って別サイトのHTMLから情報を取得する

対象サイトのHTMLを把握する

試しに、弊社のサイト(//www.bpsinc.jp)のグローバルナビの情報を取得してみたいと思います。
画像の赤枠部分。
tech12

画像の赤枠部分のHTML

<div id="menu" style="padding-bottom: 0px;">
<div class="container clearfix">
<ul id="primary" class="nav">
<li id="menu-item-7768" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-7768"><a href="https://www.bpsinc.jp/">Home</a></li>
<li id="menu-item-7532" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7532"><a href="https://www.bpsinc.jp/company">会社概要</a></li>
<li id="menu-item-7733" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7733"><a href="https://www.bpsinc.jp/rails">Ruby on Rails</a></li>
<li id="menu-item-7736" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7736"><a href="https://www.bpsinc.jp/epub">EPUB電子書籍</a></li>
<li id="menu-item-11426" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-11426"><a href="https://www.bpsinc.jp/manga_translation">漫画翻訳</a></li>
<li id="menu-item-7730" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7730"><a href="https://www.bpsinc.jp/manga-reborn">MANGAREBORN</a></li>
<li id="menu-item-10493" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10493"><a href="https://www.bpsinc.jp/seo-lpo-efo-listing-analytics">SEO対策</a></li>
<li id="menu-item-9336" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-9336"><a target="_blank" href="https://techracho.bpsinc.jp/">開発ブログ</a></li>
<li id="menu-item-7735" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7735"><a href="https://www.bpsinc.jp/recruit">採用</a></li>
<li id="menu-item-7734" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-7734"><a href="https://www.bpsinc.jp/contact">お問い合わせ</a></li>
</ul>
</div> <!-- end .container -->
</div> <!-- end #menu -->

目的とするグローバルナビの要素(会社概要とか、漫画翻訳など)のCSSを特定するにはどうすればよいかを考えてみます。
liタグにidがついており、idはすべて"menu-item-任意の数字"となっています。そしてそのあとにaタグといった構造になっています。
なので、'li[id*="menu-item-"] a'としてあげればよさそうです。

HTMLをパースする機能を持つモジュールの作成

モジュールを作らなければできないなんてことはないですが、モジュールとしてまとめて使いまわせるようにしておくと何かと便利です。

モジュールの作成

lib/scrape.rb

require 'nokogiri'
require 'open-uri'
module Scrape
BPS_SITE_URL = '//www.bpsinc.jp'
BPS_TARGET_CSS = 'li[id*="menu-item-"] a'

def self.bps_global_navi
doc = Nokogiri::HTML(open(BPS_SITE_URL)) # スクレイピング先のURLを指定
navi_list = Array.new
doc.css(BPS_TARGET_CSS).each do |link| #
navi_list << link.content end return navi_list end end

Railsコンソールで実行した結果

rails console
> Scrape.bps_global_navi
=> ["Home", "会社概要", "Ruby on Rails", "EPUB電子書籍", "漫画翻訳", "MANGAREBORN", "SEO対策", "開発ブログ", "採用", "お問い合わせ"]

自動読み込みの設定

lib/以下のファイルは自動で読み込まれません。Controller等で使う場合は自動で読み込むようにしておくと楽です。

config/application.rbに以下を追加

config.autoload_paths += %W(#{config.root}/lib)

コラム

社内で簡単にCSSパスをコピーする方法が挙がったので記載しておきます。

CSSパスをコピーする

CSSパスを自分で読み取って書くのが面倒な人はブラウザの機能を使って目的の要素のCSSパスを簡単にコピーすることができます。
■ Firefox(28.0)
右クリック=>要素を調査=>目的とする要素で右クリック=>一意なセレクタをコピー
tech13
・画像のところでコピーした結果
#menu-item-7532 > a:nth-child(1)

■ Chrome(34.0.1847.116 m)
右クリック=>要素を検証=>目的とする要素で右クリック=> Copy CSS path
tech14
・画像のところでコピーした結果
#menu-item-7532 > a

■ IE11
F12で開発者ツールが出るのですが、CSSパスをコピーするようなのは見つからなかったです。

まとめ

Nokogiriを使うことでかなり簡単にサイトの情報を取得することができるので、
サイトから情報を取得するような機能を作成する場合はNokogiriがおすすめです。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。