sk

開発で得たこと

5分でRailsでクローラーを作る。【その1】【xpath】

今回は、Railsクローラーアプリを作成します。
抽出対象はテーブルです。

自治体の選挙開票結果を抽出してくれるクローラーを作れたりします。

nokogiriのインストール

gem "nokogiri"
bundle

nokogiriはHTML解析をしてくれるライブラリです。

MVCの作成

rails g model bot name:text url:text xpath word1:text word2:text word3:text upper:text lower:text
rails g controller bots
rake db:migrate


カラムの量が尋常じゃなく多いのは、テーブル取得のアプローチを複数用意して柔軟に対応できるためです。
自治体のテーブルは我流で書かれていたり、とりあえずよくわからない構造で書かれてることが多くそういったものに対応するために必要になってくるんですね。


基本のアクションをさっと用意します。

class BotsController < ApplicationController
    require 'open-uri' #Gem入れたんですが
    require 'nokogiri' #なぜか動かなかったので一応
    def new
     @bot = Bot.new
    end

    def create
     @bot = Bot.new(bot_params)
     @bot.save
     redirect_to bots_path
    end
    
    def index
      @bots = Bot.all
    end
    
      private
      
        def bot_params
          params.require(:bot).permit(:name, :url, :xpath)
        end
end


ルーティングです。

  resources :bots, only: [:create, :index, :new]


次にビューです。


<div class="col-xs-12">
<table class="type07">
    <thead>
    <tr>
        <th scope="cols"></th>
        <th scope="cols">サイト名</th>
        <th scope="cols">URL</th>
        <th scope="cols">Xpath</th>
    </tr>
    </thead>
    <tbody>
        
    <% @bots.each do |bot| %>

        <tr>
            <th scope="row"><%= bot.id %></th>
    		<td><%= bot.name  %></td>
    		<td><%= bot.url.truncate(20) %></td>
    		<td><%= bot.xpath %></td>
        </tr>
        
    <% end %>
    </tbody>
</table>
</div>

new
sEzndEZaRDy8Y_n1494428772_1494428789.png


index
CHh5p8QwJTds2nx1494428875_1494428900.png

とりあえずこんな感じまでパパッと作ります。

xpathで取得 ---- 精度70%

    def crawl
        @bot = Bot.find(params[:id]) #保存した抽出対象データを呼び出す。
        doc = Nokogiri::HTML(open("#{@bot.url}")) #url先のHTML開放
        @crawl = doc.xpath("#{@bot.xpath}").inner_html #xpathで取得、HTMLで出力
    end
<div class="form align">
    <div class="jumbotron font">
        取得に成功しました!
    </div>
    
    取得した内容
    <div class="jumbotron padding height">
        <%= @crawl.encode("UTF-8") %>
    </div>
    
    プレビュー
    <div class="jumbotron">
        <%= simple_format("<table>" + @crawl.encode("UTF-8") + "</table>") %>
    </div>

    プレビュー2
        <%= "<table>#{@crawl.encode("UTF-8")}</table>".html_safe %> #htmlとして表示したい場合
</div>

<div class="col-xs-12">
<table class="type07">
    <thead>
    <tr>
        <th scope="cols"></th>
        <th scope="cols">選挙名</th>
        <th scope="cols">URL</th>
        <th scope="cols">Xpath</th>
        <th scope="cols">取得方法</th> #追加
    </tr>
    </thead>
    <tbody>
        
    <% @bots.each do |bot| %>

        <tr>
            <th scope="row"><%= bot.id %></th>
    		<td><%= bot.name  %></td>
    		<td><%= bot.url.truncate(20) %></td>
    		<td><%= bot.xpath %></td>
            <td><%= link_to "crawl", bots_crawl_path(id: bot.id) %></td> #追加
        </tr>
        
    <% end %>
    </tbody>
</table>
</div>
  get 'bots/crawl', to: 'bots#crawl'

xpathテスト

xpath取得

faG7YESfHG92DT71494431659_1494431675.png

crawlリンク押した結果

okeWadSEgQg8guO1494431763_1494431790.png



できました!





長くなりそうなので、
残りの2つは別記事で書きます。

ProgateやRailsチュートリアル、プログラミングスクールを通い終えたが現場のコードはかけない、

一体どうやって書くの?と思っているエンジニアのみなさんのためのチュートリアルを公開しています。

チュートリアル