それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

rubyでYahoo Japanにログインする。Cookie発行してもらう

Yahoo!Japanにログインして、いろいろ自動化したいなと思いました。なんでもスクレーパー無いと面倒くさい。

Yahoo!japanのログインの仕組み

  • 何処かページを開く
  • ログインをクリックする
  • ログイン画面が表示される
  • ログイン情報を入力する
    • 過去にログイン済みCOOKIEがない場合
    • CAPTCHAが表示される
    • CAPTCHAを通す
    • CAPTCHA認証済みCookiをもらう
    • 再度ログイン画面に戻る
  • 元いたページヘのリダイレクトページが出てくる

CAPTCHAの自動演算はモラル的にどうかと思うので、自分で使う分には、自分で画像を見て通すことにする。
つまり、ブラウザのCOOKIERubyに初期設定するのと実質変わりないからセーフセーフ。

Yahoo!JapanのログインCookieを作る

id = "takuyaXXXXX"
pw = "XXXXXXXX"

cookie_jar_path = YahooJapan::Login.gen_cookie(id,pw)
puts cookie_jar_path

実行すると、CAPTCHA画像をダウンロードし、プレビューで開く。自分で文字を読み取って、ターミナルに入力する。

enter captcha:あああああいいいいい
i got captcha あああああいいいいい

ここまでで、Cookieが生成されて、カレント・ディレクトリに"mech_cookie.yaml" が出てくる。


次回からはCookie_JARをロードすればOK!

cookie_jar_path = "mech_cookie.yaml"
m = Mechanize.new()
m.cookie_jar.load cookie_jar_path
m.get "http://www.yahoo.co.jp"
puts m.page.body.to_s.toutf8

これで、YahooのサービスにRubyのMechanizeでログイン済みアクセスできる。
JavaScriptを使わないサービス程度なら、これでログイン出来る。

CAPTHCA表示部分

#!/usr/bin/env ruby
#coding:utf-8
require 'rubygems'
require 'mechanize'
require 'open-uri'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE


module YahooJapan
	class Login
		def Login.gen_cookie(id,pw)
			cookie_jar_yaml_path = "mech_cookie.yaml"
			m = Mechanize.new
			m.get "http://auction.yahoo.co.jp/"
			m.page.links_with( :text=> "ログイン").first.click
			f=m.page.forms[0]
			f.fields_with( :name=>"login")[0].value=id
			f.fields_with( :name=>"passwd")[0].value=pw
			f.submit

			#CAPTHCA
			str = m.page.body.match( %r!"https://captcha.yahoo.co.jp:443/n/captcha[^"]+!).to_s.gsub(/"/,"")
			puts str
			tmp = open "captcha#{Time.now.to_i}.jpg", "w"
			tmp.puts open(str).read
			tmp.flush
			if RUBY_PLATFORM.downcase=~ /mswin(?!ce)|mingw|cygwin|bccwin/
				open_cmd = ""
			elsif RUBY_PLATFORM.downcase =~/darwin/
				open_cmd = "open"
			elsif RUBY_PLATFORM.downcase =~/linux/
				open_cmd = "xdg-open" 
			end
			`#{open_cmd} #{tmp.path}` 
			capthca = ''
			$stdout.print 'enter captcha:'
			captcha = $stdin.readline
			puts "i got captcha#{captcha}"
			m.page.forms.first.fields_with(:type=>"text").first.value=captcha
			m.page.forms.first.submit
			File.unlink tmp.path
			#CAPTHCA後の再ログイン
			f=m.page.forms[0]
			f.fields_with( :name=>"login")[0].value=id
			f.fields_with( :name=>"passwd")[0].value=pw
			f.submit


			puts m.page.body.to_s.toutf8

			m.cookie_jar.save_as(cookie_jar_yaml_path)
			File.expand_path cookie_jar_yaml_path
		end
	end
end


CAPTCHA認証部分はあくまで自分でやることが前提。

さて、これで自分のヤフオクの出品一覧にアクセスできるぞ。たぶんヤフオクとか、10年以上動いているプログラムは、そう簡単には書き換えられないので、一度スクレーパーを書いちゃうと暫く動き続ける。楽しみです。

OAuthとAPIについて思うことなど

OAUTHすればいいんだけど。面倒なんだもん*1。あとYahooAPIもバージョンも変わりそうで追いかけるのが面倒なんだよね。
自分のデータを取得するのにOAUTHも無いわ。

OAuthは、第三者を常に想定していて、自分で自分のデータにアクセスする手段としてはちょっと不的確なんですよねぇ。
自分で自分のデータにアクセするだけなら、Secret Keyを秘匿だけでいいんだよね。流出&乱用されたらRevokeすればいいだけ。

もともとTwitterクライアントやTwitterユーザー連携用に設計されてるので、、、第三者にキーを渡すぶんにはいいんだけど、自アプリ内で秘密キーを使えるならそれがやっぱり楽なんだよ。Consumer KeyをGenerate&Revokeする仕組みをAPI提供側が持つべきだと思う。id_rsa/id_rsa.pubのように。

あと、API提供されてない機能(出品)があるってのも良くない。API未提供の機能が今回のようなCookie生成の動機になる。だから折角OAuthやるなら出来る限り全機能公開して欲しいところです。


Yahoo Japan の場合 OAuth 実装でWEB画面が必須っぽいので、それは無いよなぁ。そのoAuthは片手落ちだよなぁと思うわけです。

*1:場合に依ってはドメイン維持したりとかもさー