Ruby
スクレイピング
Gem
RubyOnRails
SEO

新米エンジニアが月300万PVのサイトを作った時に役立ったGem20選(+SEOの小技)

More than 1 year has passed since last update.


はじめに

皆様こんにちは。@naotaka1128と申します。

データサイエンティスト(?)としてWEB広告のアトリビューション分析などを担当してます。

リブセンスでは今までSEO担当/WEBマーケター/WEBディレクターもしてました。

え?なにやってる奴かよくわかんない?

僕も正直わかんないです。

そんな僕ですが、個人の趣味で Ruby on Rails 勉強してサイト作ってます。

個人サイトのアクセス伸ばすのが最近の密かなマイブーム(死語)です。

ますます意味わかんないですね。

プロエンジニアの皆様の足元にも及ばない新米素人エンジニア(?)なので、

サイト制作は全面的にライブラリに頼りっぱなしです。

初めてサイト制作した時は「サイト制作に必要な Gem まとめ」とかなくて

ググりまくりながら作ったものです。凄く時間が掛かったのを今でも覚えてます。

(その分、新しい発見をするたびに嬉しかったのも良き思い出です。)

んなわけで今回、僕がサイト制作時に常用している Gem をまとめてみました。

リブセンスのSEO担当として身に付けた「SEOの小技」も書き添えたので、

知識古いかもですが参考にしてもらえると嬉しいです。


注意点


  • ぼっち開発でテスト全く書かない(書けない)し、コードのリーダビリティとかも気にしない(できない)のでそういう系は全く入ってません。ご容赦下さい。

  • サンプルコードは基本的にウンコードと思って頂き、参考程度に留めて下さい。


目次


  • サイト構築&SEO対策


    • パンくず: gretel

    • ページネーション: kaminari

    • METAタグ: meta-tags

    • サイトマップ生成: sitemap-generator

    • デバイス判別: mobylette



  • デザイン


    • Bootstrapテーマ適用: Bootswatch

    • Webフォントの利用:Font Awesome



  • 検索


    • 検索機能の実装:Ransack



  • 開発補助・デバッグツール


    • デバッグ:pry

    • N+1問題検知:bullet

    • 実行速度計測:rack-mini-profiler



  • リリース


    • デプロイサポート:capistrano



  • サイト監視


    • 監視ツール:NewRelic



  • スクレイピング・クローリング など


    • nokogiri

    • Mechanize

    • PhantomJS

    • open-uri-redirector

    • Parallel

    • Feedlr



  • おまけ


    • Tor-privoxy




サイト構築&SEO対策


パンくず: gretel


① 使ったgemと概要


② 参考にしたサイト


③ 使用例


Gemfile

# Breadcrumbs

gem 'gretel'


config/breadcrumbs.rb

# ↓↓ 完成品イメージ ↓↓

# TOP > 東京都 > 渋谷駅 > 【時給1300円】事務のお仕事!
crumb :root do
link 'TOP', root_path
end

# parent を指定しないと rootの 配下に設置されます
crumb :pref do |pref|
link "#{pref.name}", pref_path(pref)
end

# parentで親階層の指定をするのが使いやすい!
crumb :station do |station|
link "#{station.name}", station_path(station)
parent :pref, station.pref
end

# ちなみに使用例でよく出てくる offer は求人案件をイメージしています
crumb :offer do |offer|
link "#{offer.title}", offer_path(offer)
parent :station, offer.station
end

# 複数の親子関係を作ることも可能です
# TOP > 東京都 > リブセンス > 【時給1300円】事務のお仕事!
crumb :company do |company|
link "#{company.name}", company_path(company)
parent :pref, company.pref
end



app/views/layouts/application.html.erb

<body>



<% # パンくず表示位置・オプションの指定 %>
<% # リッチスニペット対応の semantic: true を忘れがちなので注意! %>
<%= breadcrumbs semantic: true %>


</body>


app/views/stations/show.html.erb

<% # パンくず表示階層の指定(例は駅の階層) %>

<% # 表示位置は上で決めているのでどこでも良いが、基本はファイル文頭に。 %>
<% breadcrumb :station, @station %>


④ 注意点


  • 色々オプションあるので公式見てください

  • 思いつくようなものは大概出来るはず


    • 複数リンク表示とか もろもろ




⑤ SEO-Tips


  • リッチスニペットのマークアップオプションを忘れないように。

  • 効果の程は不明かつ古いテクニックですが、以下のようにパンくずのリンクにキーワードを含めると良い効果があるかもしれません。(効果測定したことはないです笑)


    • TOP > 東京のバイト > 渋谷区のバイト > ・・・




ページネーション


① 使ったgemと概要


② 参考にしたサイト


③ 使用例


準備編


Gemfile

# Pagination

gem 'kaminari'

# bootstrapデザインの適用

rails g kaminari:views bootstrap


config/locales/ja.yml

# ページングの文言を色々変えられます

ja:
views:
pagination:
first: "最初"
last: "最後"
previous: "前"
next: "次"
truncate: "..."
helpers:
page_entries_info:
one_page:
zero: "<b>該当データがありません</b>"
one: "<b> 1件 / 全1件</b>"
display_entries: '1 %{count}件 / 全%{count}件'
more_pages:
display_entries: '%{first} %{last}件 / 全%{total}件'


使用編


app/controllers/stations_controller.rb

class StationsController < ApplicationController

# 渋谷駅のアルバイト求人一覧みたいなページの実装イメージ
def show
@station = Station.find(params[:id])
load_offers(@station)
end
end


app/controllers/application_controller.rb

# 「駅の求人一覧」みたいなの以外に「区の求人一覧」とかも

# 作ることが想定されるため、メソッドとしておくと楽。
def load_offers(object)
page_num = (params[:page].presence || 1).to_i
@offers = object.offers.page(page_num).per(@offers_per_page)
end


app/views/stations/show.html.erb

<% # 「○件〜◯件/全◎件」表示 %>

<%= page_entries_info @offers %>

<% # ページャー表示 %>
<%= paginate @offers %>

<% # 参考: PCは画面が大きいのでページング多め、Mobileは少なめ、とかも可能 %>
<% # is_mobile_request? は後で紹介するMobileアクセス判定ヘルパーメソッド %>
<% window_size = is_mobile_request? ? 1 : 2 %>
<%= paginate @offers, :window => window_size %>



④ 注意点


  • rails g kaminari:config で設定ファイル作成も可能


    • 設定可能な内容は参考にしたサイトをご覧ください

    • 標準設定ではスマートフォンでデザイン崩れることがあるので注意




⑤ SEO-Tips

特にありません。あえて言うならば、2ページ目以降はURLが ?page=2 と動的になります。古参のSEO担当者は静的URLを好むのでURLパラメーターを嫌う人もいますが、個人的にはGoogleは標準的なURLパラメーターをもう完璧に理解できると思っているのであまり気にしていません。

botのログを見ていると、サイト内で勝手にフリーワード検索を行うような挙動もあるし、むしろそっちの制御を行っています。(例:勝手にフリーワード検索とか始めないようにrobots.txtでDisallowする / フリーワード検索結果にnoindexをかける など場合によって使い分ける)


METAタグ: meta-tags


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

※実装はかなり僕の独自実装なので参考程度に


Gemfile

# META

gem 'meta-tags', :require => 'meta_tags'


config/meta_tags.yml

# YAMLに設定を書いておいて、Controllerから読み出します。

# デフォルトのMETAタグ設定
default:
name: 'サイト名だよ!バイトン!'
reverse: true
title: 'タイトルだよ!ユーザー満足度No.1!バイトン!'
description: 'メタディスクリプションだよ。全国津々浦々のアルバイトがいーっぱい!'
page_keywords: ['キーワード1', 'キーワード2', 'アルバイト', 'バイト', '求人']
prefix: ''
separator: ' / '
suffix: ''

top:
index:
title: 'トップページのタイトルだよ!アルバイト・バイト情報のバイトン!'
description: 'トップページのメタディスクリプションだよ!バイト検索ちゅ〜ならバイトン!求人掲載数1000万件突破!'

# 動的に値が変わるところはプレースホルダ的にしておきます
stations:
index:
title: '%{city_name}の駅一覧'
description: ''
show:
title: '%{paginate_info}%{station_name}駅のバイト・アルバイト情報'
description: '%{paginate_info}%{station_name}駅のバイト情報 →%{offer_num}← 件掲載ちゅ〜!短期や高収入や日払いも掲載チュー!アルバイト・バイト・パート求人情報探すならバイトン!'



app/controllers/stations_controller.rb

class StationsController < ApplicationController

# 渋谷区の駅一覧みたいなページの実装イメージ
def index
@city = City.find(params[:id])
load_metas() # METAタグ用メソッド(後述)を呼ぶ
end

# 渋谷駅のアルバイト求人一覧みたいなページの実装イメージ
def show
@station = Station.find(params[:id])
load_metas(@station.offers)
end
end



app/controllers/application_controller.rb

# partial: _meta_tags で使用

META_TAGS = YAML.load_file('config/meta_tags.yml').freeze

# メソッドを書くファイルはどこでもいいです
def load_metas(offers_all = {})
# タイトル、ディスクリプションの設定ファイル読み出し
# 公式Githubの中の"Using MetaTags in controller"のところはよく読む
init_tags rescue default_tags

# プレースホルダを書き換えて動的なタイトルやディスクリプションにしている。
case params[:controller] + '#' + params[:action]
when "stations#index"
@page_title.gsub!('%{city_name}', @city.name)
@page_description.gsub!('%{city_name}', @city.name)
when "stations#show"
@page_title.gsub!('%{station_name}', @station.name)
@page_description.gsub!('%{station_name}', @station.name)
convert_offer_num(offers_all)
convert_paginate_info
end
end

def init_tags
@page_title = meta_tag_list[params[:controller]][params[:action]]['title']
@page_description = meta_tag_list[params[:controller]][params[:action]]['description']
end

def default_tags
@page_title = meta_tag_list['default']['title']
@page_description = meta_tag_list['default']['description']
end

# meta desc に XX件 と入れるためのメソッド
def convert_offer_num(offers_all)
convert_to = offers_all.size > 0 ? "#{offers_all.count}" : ''
@page_description.gsub!('%{offer_num}', convert_to)
end

# XXページ目、と入れるためのメソッド
def convert_paginate_info
convert_to = params[:page] ? "(#{params[:page]}ページ目)" : ''
@page_title.gsub!('%{paginate_info}', convert_to)
@page_description.gsub!('%{paginate_info}', convert_to)
end

def meta_tag_list
# FIXME: ここの実装イケてないのでなんとかしたい…。
# 定数だと上書きされる可能性があり、毎回ファイルのIOが発生させてしまっている(´・ω・`)
YAML.load_file('config/meta_tags.yml')
end



app/views/layouts/application.html.erb

<head>



<%= render partial: 'shared/meta_tags' %>


</head>


app/views/shared/_meta_tags.html.erb

<% # 基本的にデフォルトのを読み出しておいて、公式のGithubの中の %>

<% # "Using MetaTags in controller"のところの機能を使って上書きしている %>
<%= display_meta_tags({
title: ApplicationController::META_TAGS['default']['page_title'],
description: ApplicationController::META_TAGS['default']['page_description'],
keywords: ApplicationController::META_TAGS['default']['page_keywords'],
canonical: request.original_url,
noindex: @offers.count == 0 ? true : false
}) %>


④ 注意点

上記のウンコードは適宜修正してご利用下さい


⑤ SEO-Tips

META系はSEOに多大なる影響があります。

その中でも、タイトルと noindex について少しコツを書いておきます


  • タイトル:とにかく気合を入れて考えましょう


    • 必要なキーワードを盛り込むのは当たり前


      • ロングテールではタイトルにキーワードが入っているだけで順位が如実に向上する


        • ロングテール集客は莫大なトラフィックが見込めるので非常に重要

        • 掛けあわせワードはよく考えて





    • Google/Yahoo!での検索結果画面での見栄えも考えましょう


      • Google検索結果でのCTRは検索順位に影響があると考えられている

      • Googleはたまにわけの分からん省略をしてしまうので28文字程度をメドに簡潔に

      • タイトルの頭に【求人多数】【厳選】とかつけるとCTRに好影響があった事例も


        • これはサイトによって色々違うのでABテストを推奨





    • 効果を検証したわけではないですが笑、以下の様な噂があります(僕は一応採用しています)


      • 2ページ目以降でタイトルの頭に(XXページ目)と入れる

      • → botが1ページ目とそれ以外を区別しやすくなる

      • → 1ページ目が自ずと検索結果に出やすくなる

      • → 順位に若干の好影響?(本当?)





  • Noindex


    • Noindex付与による検索順位への影響は諸説ありますが、僕は意味があると信じてます。

    • Noindexすべきページ


      • 検索結果0件のページ

      • 他サイトと内容が酷似していると捉えかねられないページ


        • パンダペナルティや手動ペナルティ(低品質)をくらわないために

        • 手動ペナルティ(低品質)は解除が困難を極めるので気をつけて



      • その他、ユーザーがすぐに帰ってしまうような内容の薄いページ


        • 直帰率高いと検索順位に悪影響があると言われています








サイトマップ生成: sitemap-generator


① 使ったgemと概要


② 参考にしたサイト


③ 使用例


Gemfile

# SITEMAP

gem 'sitemap_generator'

# config/sitemap.rb の作成

rake sitemap:install


config/sitemap.rb

# ドメイン名を書くのを忘れがちだから気をつけて

SitemapGenerator::Sitemap.default_host = "http://www.baiton.com/"

# サイトのデータ構成に応じて下記を変更する
SitemapGenerator::Sitemap.create do
# priority: 重要度 / changefreq: 更新頻度 は適宜変更
Station.find_each do |station|
add station_path(station), :priority => 0.7, :changefreq => 'daily'
end

Offer.find_each do |offer|
add offer_path(offer), :priority => 0.5, :lastmod => offer.updated_at
end
end



サイトマップ生成(public/に作られる)

# 開発環境用コマンド (Google&Bingへのping送信を行わない)

rake sitemap:refresh:no_ping

# 本番環境用コマンド (Google&Bingへのping送信を行う)
rake sitemap:refresh



日次データ更新時とかに無理くりリフレッシュしてます

# Cronのデータ更新タスク終了後とかに

ssh user_name@XXX.XXX.XXX.XX "cd /rails_app_path/ && source ~/.bashrc && export PATH=$PATH && bundle exec rake sitemap:refresh RAILS_ENV=production"


④ 注意点


  • 自動更新のやり方は非常に怪しいです。


    • Capistrano でデプロイと同時にできるみたいなのでそちらでやる方が良い、かな…?

    • 個人の勝手サイトなので結構色々適当ですみません…。




⑤ SEO-Tips


  • (書いといてアレですが) SiteMapを送らないプロの方もいらっしゃるようです


    • 末端ページにbotがどれくらい来るか(≒リンクジュースがどこまで行き渡っているか)を知りたいらしい

    • というわけで必ずしも送らないといけないわけではないので悪しからず。



  • 個人的には SearchConsole で Index率 が見れるので嬉しい


    • ロングテールページのコンテンツ量調整とかに使います


      • Index率悪かったら自動生成コンテンツ増やしてみたりとか





  • サイトマップは良くも悪くも意外と強力


    • カスページがサイトマップに混入しないように気をつけましょう。

    • 404になるページを大量にサイトマップに混入させたことがあり、クロールエラー出まくりました。




デバイス判別: mobylette


① 使ったgemと概要


② 参考にしたサイト


  • 特になし


③ 使用例


Gemfile

gem 'mobylette'



app/controllers/application_controller.rb

include Mobylette::RespondToMobileRequests



app/views/layouts/application.html.erb

<% # is_mobile_request? ってHelperMethodでMobile(true) / PC(false)が分かります %>

<% # あくまで参考例 %>
<% if is_mobile_request? %>
<%= render partial: 'shared/contents/smartphone' %>
<% else %>
<%= render partial: 'shared/contents/pc' %>
<% end %>



④ 注意点


  • なんか色々ヘルパーありますが、僕は is_mobile_request? ってのしか使ってません

  • 結構古いGemで更新もされてなさそうなのであくまで自己責任でご利用下さい。


⑤ SEO-Tips


  • 直接 Gem に関連ないですが、PC⇔Mobileのサイトの作り方の基本の考え方を。


    • PCサイト


      • botでもコンテンツ内容をきちんと理解できるようにページを構成する


        • bot(機械)がきちんと内容理解できればユーザー(人間様)は余裕で理解できるはず。



      • 基本的にページ上部に有用なコンテンツやワードを(多少無理矢理でも)織り込むのが良い。


        • 特に H1見出し下(正確には周辺)のテキストは比較的評価されやすいと言われている

        • (自然な)自動生成文章でワード織り込むテクニックはロングテールSEOに有用





    • モバイルサイト


      • 基本的にコンテンツ内容(ワードとか) は "直接的には" SEOに関係ないので、


        • 直帰率を下げたり、滞在時間を延ばせるコンテンツを中心にする

        • 1stビューに置くものは極限までコンパクトにして、ユーザー行動を促す

        • 1stビューにメインのコンテンツ(アルバイトサイトで言うと求人案件)が見えていないと如実に直帰率が上がる肌感がある。








デザイン


Bootstrapテーマ適用: Bootswatch


① 使ったgemと概要


② 参考にしたサイト


③ 使用例


Gemfile

# JavaScriptコードを実行するためのエンジン

gem 'execjs'

# Bootswatch
gem 'twitter-bootswatch-rails', '~> 3.1.1'
gem 'twitter-bootswatch-rails-helpers'



適用

# paper の部分は選んだテンプレート名に適宜変更

rails g bootswatch:install paper
rails g bootswatch:import paper
rails g bootswatch:layout paper


app/assets/javascripts/application.js

// 下記を追記、paperの部分は(ry

//= require paper/loader
//= require paper/bootswatch


app/assets/stylesheets/application.css

/*

* 下記を追記、paperの(ry
*= require paper/loader
*= require paper/bootswatch
*/



④ 注意点


  • 僕のミスかもしれませんが、たまにデプロイ時にコンパイル(?)に失敗するテーマもありました


    • その時は無理くり直したけど、普通に他のテーマにしたら良かった。




Font Awesome


① 使ったgemと概要


② 参考にしたサイト


  • 特に無し

  • しいて言うなら本家


    • アイコンの種類調べるのに、って当たり前よね。




③ 使用例


Gemfile

gem "font-awesome-rails"



app/assets/stylesheets/application.css

/*

* 下記を追記
*= require font-awesome
*/



app/views/layouts/application.html.erb

<% # あくまで一例 %>

<%= link_to fa_icon('home'), root_path %>
<%= fa_icon('fa fa-camera-retro fa-2x') %>


検索


Ransack


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

サイト構成によって使用例は相当変わるので、

参考にしたサイトを見ていただければと思います。


開発補助・デバッグツール


pry


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

binding.pry以外の機能を全く使いこなせてないので恐縮ですが。


Gemfile

group :development do

...
gem 'pry'
...
end


Controllerの中に書くときは

# binding.pry が記入してある行で処理が止まってくれる

binding.pry if Rails.env.development?


Viewの中に書くときは

<% # binding.pry が記入してある行で処理が止まってくれる %>

<% binding.pry if Rails.env.development? %>


bullet


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

参考サイトの使用例の通りで大丈夫です


④ 注意点とSEO-Tips


  • ページ読込速度は直帰率に関係する可能性が高いので、SEOに影響あると考えられます。


    • 鬼のように速くても仕方ないのですが笑

    • よって、参考ページに書いてあるような高速化チューニングは大切


      • が!ここからが重要なのですが、キャッシュが強力すぎて、個人的にはN+1対策とかあまり関係無かったような印象が…。(もっと大きなサイトなら不可欠なのかな?)

      • というわけでアクセスが無事増えてきて、サイトが落ち始めたら、まずはキャッシュ導入から始めることをおすすめします。



    • ちなみに、ページ読込が早いと以下の様な嬉しいこともあります。


      • 1日あたりのbotのクロールページ数が増える(※)

      • → ロングテールページのINDEXが比較的早期に行われる

      • → サイト立上げ時の集客増が比較的早くなって嬉しい(・∀・)

      • ※ 念のため解説


        • botは基本的に1サイト当たりのクロール時間を決めて回っている

        • 読み込み時間が短いと決まった時間でより多くのページが回れる








rack-mini-profiler


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

参考サイトの使用例の通りで大丈夫です。


リリース


Capistrano


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

サーバー構成によってかなり違うと思うので、

使用するサーバーのドキュメントを参照いただければと思います。


④ おまけ


  • 初めてのサイト制作には DigitalOcean が凄い便利でした

  • 便利だった点


    • 安い (AWSの1/3ぐらい)

    • 1クリックで Ruby on Rails がインストールされたサーバーを準備できる

    • シンガポールリージョンが比較的早い

    • わかりやすいチュートリアル&ドキュメントが充実






サイト監視


NewRelic


① 使ったgemと概要


② 参考にしたサイト


③ 使用例

config/newrelic.yml 内の app_name を書き換える必要があること以外は、

参考にしたサイトの通りで大丈夫だと思います。

(最初は4分じゃ無理だと思いますがw)


④ 注意点



  • AWSユーザなら無料で使えるNew Relic導入方法


    • 僕はAWSユーザーじゃないので使ってませんが、有料版を無料で使うことも可能なようです。

    • 個人的には無料版でも特に不都合は感じていませんが、ちょっと羨ましい笑。




スクレイピング・クローリング など

本章の内容はRailsアプリに直接は関係ありませんが、

サイト制作時にデータ収集することもあるかと思うので、

便利なやつを軽く紹介しておきます。(ほぼ参考サイトの紹介のみです)


Nokogiri


① 使ったgemと概要


② 参考にしたサイト


③ 注意点


  • スクレイピングは色々面倒です。


    • 初心者だとCSSセレクタとかXPathも覚えないとダメだし、

    • 対象サイトの変更あればちょいちょいコード書換えないとダメ。



  • 目的をきちんと考え、最短の時間で成果を出す方法を選択しましょう。


    • 例:


      • APIないかな?

      • RSS吐いてくれてないかな?


        • RSSがあれば以下の様なことも可能です。


          • FeedlyにRSS登録

          • (後述の)FeedlrでAPI取得







    • (まぁ、とはいえスクレイピングに頼ることも多いと思います…。)




Mechanize


① 使ったgemと概要


  • Mechanize: http://mechanize.rubyforge.org/

  • ざっくり言うと:スクレイピングの補助をしてくれる(フォーム操作とか検索とか)


② 参考にしたサイト


PhantomJS


① 使ったgemと概要


  • PhantomJS: https://github.com/colszowka/phantomjs-gem

  • ざっくり言うと


    • 高度なスクレイピングを可能に(javascriptを動かす、キャプチャ撮る、等)

    • (本来はテスト用のツールなのかな…?)




② 参考にしたサイト


open-uri-redirections


① 使ったgemと概要


② 参考にしたサイト


Parallel


① 使ったgemと概要


② 参考にしたサイト


③ 注意点


  • Rubyの仕様から、Parallelで超多並列処理にすると実行速度が遅くなるらしい。


    • 50とか100並列での処理が必要な場合は、eventmachineを使って実装すると良いらしい。

    • 僕はやったことがなく、詳細知らないのでググッていただければと思います。




Feedlr


① 使ったgemと概要


② 参考にしたサイト


③ 注意点

Feedly-APIの日次アクセス制限数が "250" とかなり少ないのでご注意下さい。

(もちろん、Tokenを再発行してもリセットされません。)


おまけ

用法用量を守って(略


Tor-privoxy


① 使ったgemと概要


② 参考にしたサイト


③ 注意点


  • 事前にTorのインストールが必要です



  • Tor経由のアクセスを弾いているサイトは結構有るらしい