2014年1月29日水曜日

cookpadのレシピをオブジェクト化する

cookpadのレシピ情報が欲しくなったが、cookpadはapiを公開してないのでhtmlをパースして情報を取得することにした。
htmlの構成が変わったらアウトだけどrubyのnokogiriが意外と簡単で以下の様なクラスを作って対応。

cookpad class

#!/usr/bin/env ruby
# -*- mode:ruby; coding:utf-8 -*-
require 'open-uri'
require 'nokogiri'

class Cookpad
  def initialize(options={})
  end

  def get_recipe(uri)
    r = {}
    doc = Nokogiri::HTML(open('http://cookpad.com' << uri))
    r[:title] = doc.xpath('//*[@id="recipe-title"]/h1/text()').shift.content.strip
    r[:image] = doc.xpath('//*[@id="main-photo"]/img').shift.attributes['src'].value
    r[:summary] = doc.xpath('//*[@id="description"]/text()').shift.content.strip
    r[:servings_for] = doc.xpath('//*[@id="ingredients"]/div[1]/h3/div[1]/span[2]').shift.children.shift.content.strip.gsub(%r![()()]!, '')
    r[:ingredients_list] = []
    doc.xpath('//*[@id="ingredients_list"]').children.each do |ingredient|
      next if ingredient.xpath('div[1]/span').empty?
      r[:ingredients_list] << {:name => ingredient.xpath('div[1]/span').children.shift.content, :quantity => ingredient.xpath('div[2]').children.shift.content}
    end
    r[:steps] = []
    doc.xpath('//*[@id="steps"]').children.each do |step|
      next if step.xpath('dl/dt/h3').empty?
      r[:steps] << {:step => step.xpath('dl/dt/h3').children.shift.content.strip, :instruction => step.xpath('dl/dd/p').children.shift.content.strip}
    end
    r
  end
end

if __FILE__ == $0
  require 'pp'
  cookpad = Cookpad.new
  pp cookpad.get_recipe('/recipe/1012764')
end

実行結果

{:title=>"簡単・濃厚・ぶり大根",
 :image=>
  "http://img.cpcdn.com/recipes/1012764/280/15ecbb2f22d6e0ab7aa374abc9df9a7f.jpg?u=1845293&p=1348990478",
 :summary=>"話題入&H26/1/29ピックアップ掲載大感謝です✿静岡県伊豆の金目鯛姿煮を参考にした濃厚味の簡単ぶり大根です✿",
 :servings_for=>"2人分",
 :ingredients_list=>
  [{:name=>"ブリ切り身", :quantity=>"2切れ"},
   {:name=>"大根", :quantity=>"5cm(好みの量で)"},
   {:name=>"しいたけ(なくてもよいです)", :quantity=>"2こ"},
   {:name=>"生姜(スライスしておく)", :quantity=>"3cm(好みの量で)"},
   {:name=>"醤油", :quantity=>"大さじ4"},
   {:name=>"砂糖", :quantity=>"30~40g(大さじ3~4)"},
   {:name=>"日本酒", :quantity=>"100cc"},
   {:name=>"水", :quantity=>"150cc"},
   {:name=>"飾り用の柚子・生姜の千切り", :quantity=>"適量"},
   {:name=>"塩(ブリの下処理用)", :quantity=>"適量"}],
 :steps=>
  [{:step=>"1", :instruction=>"ブリの下処理(臭み抜き)をします。ブリ切り身に少々塩をふり、上から熱湯をかけます。"},
   {:step=>"2", :instruction=>"皮をむいた大根を1cm程の厚さに短冊切り(いちょう切り)にします。"},
   {:step=>"3",
    :instruction=>"煮る時間短縮の為、大根を電子レンジ(500w)で1分加熱します。この工程はなくてもOKです。"},
   {:step=>"4", :instruction=>"鍋に醤油&砂糖&日本酒&水を入れて混ぜます。"},
   {:step=>"5", :instruction=>"4の鍋に1のブリ&3の大根&しいたけ&生姜を入れ、落し蓋をして煮ます(最初は中火→弱火)。"},
   {:step=>"6", :instruction=>"煮汁が少なくなってくるまで煮たら完成です。飾りで柚子や生姜の千切りを添えてください。"},
   {:step=>"7", :instruction=>"H22年10月26日に話題入り致しました!本当にありがとうございます✿"},
   {:step=>"8",
    :instruction=>"H24年9月29日に二度目の話題入り(100人つくれぽ)致しました!本当にありがとうございます!!"},
   {:step=>"9", :instruction=>"H24年9月30日、写真を更新致しました。"},
   {:step=>"10", :instruction=>"H25年2月15日、200人つくれぽを頂きました✿皆様、本当にありがとうございます!!"},
   {:step=>"11",
    :instruction=>"H26年1月29日「本日のピックアップレシピ」に掲載されました!皆様、本当にありがとうございます✿"}]}

2014年1月18日土曜日

jqueryでリンク切れの画像を消す

画像リンクを貼っていて何かのタイミングで元の画像が消されると見た目が残念なことになる。


jqueryでimgタグのsrcを1x1の透過gifに変更するものを準備しておく
function imageOnError(img) {
    $(img).attr('src', 'http://cadillac.psychobil.ly/b');
    return true;
}

imgタグにはエラーの時の挙動を予め仕込んでおく。
<img onerror="return imageOnError(this);" src="xxx" />

これで仮にリンク先の画像が消されても残念な画像が出ずに済みます。

2014年1月2日木曜日

mediawikiに2ちゃんのまとめを自動投稿してみた#1

mediawikiに2ちゃんのまとめを自動投稿してみた。

mediawikiの設定

LocalSettings.phpにhtmlタグがそのまま使えるように設定を入れておく
$wgRawHtml = true;

rubyでmediawikiへ投稿する

#!/usr/bin/env ruby

require 'media_wiki'

mw = MediaWiki::Gateway.new("http://matome.t15.org/api.php")
mw.login('username', 'password')
title = 'タイトル'
contents = 'コンテンツ'
mw.create(title, contents, :summary => title)