【Ruby】「めざましテレビ」朝の占い結果を表示するメソッドを作成(スクレイピング)

プログラミング初心者の勉強ブログ #64

めざましテレビのコーナーの一つ、「めざまし占い」の毎日の結果をHPからスクレイピングして、引数に星座名を入れると、占い結果が出るメソッドを作成したので紹介します。「Faraday」ライブラリを用いた方法です。indexメソッドとsliceメソッドを使う練習になります。

 

目次

[toc]

 

スクレイピングとは

今回のメソッド作成は「スクレイピング」を使用しております。スクレイピングとは、「ウェブサイトから情報を取得し、その情報を加工して新たな情報を生成すること」です。

これを用いて、めざまし占いの公式HPから占い結果を取得し、メソッド定義を行っていきます。

 

ライブラリ「Faraday」

スクレイピングを行うにあたって、便利なライブラリがFaradayです。

Github Faraday

Faradayは、URLを指定することで、そのURLのHTMLソースを取得することができます。このFaradayで取得したHTMLから、占い結果を取得していきます。

 

使用するRubyメソッド

HTMLソースから、必要な情報のみを取得するためには、Rubyのindexメソッドやsliceメソッドなどを組み合わせて行います。

 

indexメソッド

indexメソッドは、引数で指定した文字列のオフセット(基準点からの距離)を取得します。文字の並び(今回のスクレイピングの場合はHTMLソース全体)を、一つの配列として捉え、指定した文字列の頭文字のインデックス番号が、返り値として返ってくるメソッドです。

indexメソッド

 

rindexメソッド

rindexメソッドは、インデックス番号の一番後ろから検索をかけ、引数で指定した文字のインデックス番号を返すものです。indexメソッドの逆バージョンであり、こちらを用いた方が取得しやすい場合もあります。

rindexメソッド

sliceメソッド

sliceメソッドは、引数で指定したインデックス番号に該当する文字列を取得するメソッドです。引数の指定方法は2通りあり、以下のように設定し、取得できます。

sliceメソッド

 

めざまし占い公式HPから占い結果を取得

上で書いたライブラリとメソッドを使い、実際にHPからスクレイピングを行います。

[blogcard url=”http://fcs2.sp2.fujitv.co.jp/fortune.php”]

めざまし占い

 

ここのHTMLソースを見ると、

めざまし占いHTMLソース

 

こんな形となっております。

今回はクラスで指定されている「wordBgnng」や「starTitle」、「rank」をキーワードとし、星座名を引数にとる「mezamashiFortune(sign)」メソッドを定義します。

 

実際のコード

 

test.rb

require 'faraday'

// めざまし占い(めざましテレビ/フジ/月〜土/8時更新 ※土のみ8時半更新)
def nezamashiFortune(sign)
  page = Faraday.get('http://fcs2.sp2.fujitv.co.jp/fortune.php')
  #URL指定
  page_ja = page.body.force_encoding('utf-8')
  #body要素のみ取得し、日本語化
  
  number = page_ja.index(sign)

  rank_num = page_ja.rindex('rank', number)
  start_num = page_ja.index('>', rank_num)
  end_num = page_ja.index('<', start_num)
  rank = page_ja.slice(start_num+1..end_num-1)
 #「rank」クラスの位置から辿り、占い順位を取得

  wordBgnng_num = page_ja.index('wordBgnng', number)
  start_num = page_ja.index('>', wordBgnng_num)
  end_num = page_ja.index('<', start_num)
  text1 = page_ja.slice(start_num+1..end_num-1)
 #「wordBgnng」クラスの位置から辿り、コメントを取得

  start_num = page_ja.index('>', end_num)
  end_num = page_ja.index('<', start_num)
  text2 = page_ja.slice(start_num+1..end_num-1)
 #「wordBgnng」クラスの位置から辿り、コメントを取得

  p sign + "-----------" + rank
  p text1
  p text2

  3.times do
    if page_ja.index('starTitle', number) < page_ja.index('fortunerank', number)
      starTitle_num = page_ja.index('starTitle', number)
      start_num = page_ja.index('>', starTitle_num)
      end_num = page_ja.index('<', start_num)
      starTitle = page_ja.slice(start_num+1..end_num-1)

      start_num = page_ja.index('<td>', end_num)
      end_num = page_ja.index('</td>', start_num)
      starContent = page_ja.slice(start_num+4..end_num-1)
    #「starTitle」クラスの位置から辿り、ラッキーポイント等を取得
    else
      starTitle = nil
      starContent = nil
    end
    p starTitle
    p starContent
    number = end_num
  end
end

 

この関数を

mazamashiFortune(“おひつじ座”)

のように引数を入れて呼び出すと、

占い結果

その日のおひつじ座の占い結果が出てきます。

 

おうし座はどうでしょうか。

mazamashiFortune(“おうし座”)

めざまし占い2

 

9位ですね。

 

めざまし占いは「12位」には「ラッキーポイント」だけでなく、「おまじない」と「アドバイス」が付いてきます。

※同じように「1位」も「ラッキーポイント」と「アドバイス」が出てきます。

 

この例外対応のため、以下の「3.times do」の繰り返し構文を使用しました。

3.times do
    if page_ja.index('starTitle', number) < page_ja.index('fortunerank', number)
      starTitle_num = page_ja.index('starTitle', number)
      start_num = page_ja.index('>', starTitle_num)
      end_num = page_ja.index('<', start_num)
      starTitle = page_ja.slice(start_num+1..end_num-1)

      start_num = page_ja.index('<td>', end_num)
      end_num = page_ja.index('</td>', start_num)
      starContent = page_ja.slice(start_num+4..end_num-1)
    #「starTitle」クラスの位置から辿り、ラッキーポイント等を取得
    else
      starTitle = nil
      starContent = nil
    end
    p starTitle
    p starContent
    number = end_num
end

 

これで1位と12位の情報を全て取得でき、2〜11位の場合は「nil」が返ってきます。

だいぶ環境依存な関数なので、公式HPのHTMLソースが変わってしまう場合はもちろん、めざまし占いの使用自体が変わってしまった場合も修正が必要になります。

もっとスマートな書き方はいくらでもあるのかもしれませんが、スクレイピングは少なからず環境に依存するコーディングになってしまう気がします。

 

まとめ

今回の「mazamashiFortuneメソッド」はスクレイピングのため、HPが変わらない限り占い結果は毎日更新されたものを呼び出してくれます。なかなか面白いです。また他のサイトもスクレイピングしてみたいと思います。

 

以上ありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA