質問: Yahoo.new("[YahooビジネスID]","[パスワード]") ``` ### 実行結果 ``` $ ruby get_report_yahoo.rb https://login.bizmanager.yahoo.co.jp/login Login - Yahoo! JAPAN https://login.bizmanager.yahoo.co.jp/login?url=https://promotionalads.business.yahoo.co.jp%2fAdvertiser%2fDashboard Login - Yahoo! JAPAN ``` 正しくログインできていれば下の出力は下記になるはず。 「ダッシュボード - Yahoo!プロモーション広告 広告管理ツール」 @report_url の値をログインが不要でアクセスできるURLに変えるとちゃんと動いてるっぽいのでログインできていないのだと思う。 ### 補足情報(FW/ツールのバージョンなど) 環境について Ubuntu 16.04.5 LTS (Xenial Xerus) ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] mechanize (2.7.6) Nokogiri (1.8.5) ※Windows Subsystem for Linuxにてubuntuを導入して開発中。最終的にはGCE上に環境を作る予定。
回答: Yahoo! サイト側が、 **ログインフォームへの直接遷移を許可していない** ことが原因と思われます。 今回、処理の対象となっているフォームには、 `.crumb` という name の hidden field が存在するのですが、こちらの値が空欄の場合、フォームを送信してもエラーすら表示されず、同じフォームの再表示が行われるようです。また、 `.crumb` の valueは、一度関連する Yahoo! のページを閲覧するなどして Cookie を持っている場合は何らかの値が埋め込まれ、逆に Cookie を持っていないユーザでは空欄になるように見えます。 以上の事実と、また "crumb" という名前から見て、恐らく **何らかのルールで Yahoo! サイト上の遷移してきたページを記憶しており、そのページ遷移が想定外の場合、不正なログインと見做してフォームの再表示をしている** 実装になっているのではないでしょうか。目的は CSRF 等の対策と思われます。 というわけで、ログインフォームを開く前にどこかの適切な Yahoo! サイト上ページを開いておけば良いことになりますが、一番単純なのは **ログインフォームを二回開いて、二回目にフォーム値を埋めて POST する** 方法でしょうか。つまり、`login()` メソッドの先頭に一行、 (見かけ上は無意義な) `@agent.get(@url)` を追加して適切な Cookie を受け取り、それから改めてログイン処理を行うという寸法です。