質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.58%

rubyのmechanizeを使用したYahooビジネスへのログインについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,166

majin

score 10

 前提・実現したいこと

最終的にやりたいこと→
Yahooプロモーション広告でリスティングを複数サイト運用しており、
サイトごとに前日にかかったコストをSlackに通知したい。
※Google広告も同時に運用しておりそちらはアクションスクリプトでスラックに通知実装完了済み
※さらに発展させ、コストレポートの内容をbigqueryに突っ込むっていう話もあるけど一旦お預け中。

現状とか→
本当はYahooのAPIを使用できるのが一番いいのは承知しているのですが、
YahooはGoogleと違って使用申請が必要かつ、おそらく運用費用に応じてAPI開放審査があるようで
問い合わせても全然開放してくれません。
さらに運用サイトが複数あるので、おそらく1つのAccountでAPIが使えるようになっても、他のAccountでは使えないことが想定されます。
なので、rubyのmechanizeを使用して、ログインし管理画面上(レポート画面?)の値をnokogiriでスクレイピングしたい。
・・・が現状スクレイピングどころかログインで詰まっている。

別にrubyやmechanizeにこだわっているわけではないので「この方法ならサクッとできるよ。」的なものがあれば代替え案は歓迎です。

 発生している問題・エラーメッセージ

Yahooビジネスにログインできない。

補足:
ブラウザで見ているページとrubyでアクセスしたときのページが違う気がする。
ブラウザでログインページにアクセスするとタイトルが「ログイン - Yahoo! JAPAN」だが、おなじURL(https://login.bizmanager.yahoo.co.jp/login)にmechanizedでアクセスすると「Login - Yahoo! JAPAN」になっている。

 該当のソースコード

ソースが汚いのは許して…

# -*- coding: utf-8 -*- 
require 'nokogiri'
require 'mechanize'

#HTMLテキストをxpathに沿ってパース
def parse_html( html_text , xpath )
    begin
        #HTMLテキストをxpathでパースできる形に変換
        content = Nokogiri::HTML( html_text )
        #パースした結果を返す
        return content.xpath( xpath )
    rescue
        #正しくパースできない場合はエラー値を返す。
        return Nokogiri::HTML( "" ).xpath( "" )
    end
end

#Yahoo用のクラス
class Yahoo
    #初期化で諸々変数を設定
    def initialize( user , pass )
        # 必要そうな項目。
        @url        = "https://login.bizmanager.yahoo.co.jp/login"
        @report_url = "https://promotionalads.business.yahoo.co.jp/Advertiser/Dashboard"
        @user       = user
        @pass       = pass
        @agent      = Mechanize.new
        @agent.user_agent_alias = 'Windows Mozilla'
        #ログイン処理
        @this_page = login()

        ##### テスト用出力 #####

        #ログインページのURLとタイトルを表示
        puts get_uri()
        puts parse_html( get_content() , "//title" ).inner_text.to_s

        #ダッシュボードページに移動、URLとタイトルを表示
        @this_page = jump( @report_url )
        puts get_uri()
        puts parse_html( get_content() , "//title" ).inner_text.to_s

        ##### テスト用出力 #####

    end

    #ログイン処理 
    def login()
        @agent.get( @url ) do |page|
            page.form_with(name:"login_form") do |form|
                form.field_with(:name=>"user_name").value = @user
                form.field_with(:name=>"password").value  = @pass
            end.submit
        end
    end

    #ページ移動
    def jump(url)
        @this_page = @agent.get( url )
    end

    #なんかデータとってきたいとき用。
    def get_this_page()
        @this_page
    end

    def get_uri()
        @this_page.uri
    end

    def get_content()
        @this_page.content.toutf8
    end
end

#Yahooレポートを出力するクラスを準備。
rep = 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上に環境を作る予定。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Yahoo! サイト側が、 ログインフォームへの直接遷移を許可していない ことが原因と思われます。

今回、処理の対象となっているフォームには、 .crumb という name の hidden field が存在するのですが、こちらの値が空欄の場合、フォームを送信してもエラーすら表示されず、同じフォームの再表示が行われるようです。また、 .crumb の valueは、一度関連する Yahoo! のページを閲覧するなどして Cookie を持っている場合は何らかの値が埋め込まれ、逆に Cookie を持っていないユーザでは空欄になるように見えます。

以上の事実と、また "crumb" という名前から見て、恐らく 何らかのルールで Yahoo! サイト上の遷移してきたページを記憶しており、そのページ遷移が想定外の場合、不正なログインと見做してフォームの再表示をしている 実装になっているのではないでしょうか。目的は CSRF 等の対策と思われます。

というわけで、ログインフォームを開く前にどこかの適切な Yahoo! サイト上ページを開いておけば良いことになりますが、一番単純なのは ログインフォームを二回開いて、二回目にフォーム値を埋めて POST する 方法でしょうか。つまり、login() メソッドの先頭に一行、 (見かけ上は無意義な) @agent.get(@url) を追加して適切な Cookie を受け取り、それから改めてログイン処理を行うという寸法です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/12 09:29

    ありがとうございます。
    こちらで解決できました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る