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

  • 0
    いいね
  • 0
    コメント

    あー、テーブル抽出したい!テーブル抽出したい!

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

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

    デモ・ソースコード

    デモ
    Git

    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
    

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

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

    bots_controller.rb
    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]
    

    次にビューです。

    new.html.erb
    
    
    <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%

    bots_controller.rb
        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
    
    crawl.html.erb
    <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>
    
    index.html.erb
    
    
    <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>
    
    routes.rb
      get 'bots/crawl', to: 'bots#crawl'
    

    xpathテスト

    対象サイト

    http://yume.hacca.jp/koiki/css/table/table.htm

    xpath取得

    faG7YESfHG92DT71494431659_1494431675.png

    crawlリンク押した結果

    okeWadSEgQg8guO1494431763_1494431790.png

    できました!

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

    続き


    「作ったアプリを発信しましょう!」
    自分が作ったものを他者に発信しましょう。

    Ruppishはあなたが作ったものを世に出すお手伝いをします。
    あなたの投稿が1000人にリーチします。

    Ruppish